Merge pull request #876 from practicalswift/swiftc-28191-swift-typebase-getcanonicaltype
[swiftc] Add test case for crash triggered in swift::TypeBase::getCanonicalType()
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 3622065..8f94f8e 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2382,7 +2382,7 @@
/// The type that represents this (sugared) name alias.
mutable NameAliasType *AliasTy;
- SourceLoc TypeAliasLoc; // The location of the 'typalias' keyword
+ SourceLoc TypeAliasLoc; // The location of the 'typealias' keyword
TypeLoc UnderlyingTy;
public:
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index d78b660..1bcbb1c 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1815,6 +1815,8 @@
"contextual type %0 cannot be used with array literal", (Type))
NOTE(meant_dictionary_lit, sema_tce,none,
"did you mean to use a dictionary literal instead?", ())
+ERROR(should_use_empty_dictionary_literal,sema_tce,none,
+ "use [:] to get an empty dictionary literal", ())
// Dictionary literals
ERROR(dictionary_protocol_broken,sema_tce,none,
diff --git a/include/swift/AST/DiagnosticsSema.h b/include/swift/AST/DiagnosticsSema.h
index f452d6d..4947560 100644
--- a/include/swift/AST/DiagnosticsSema.h
+++ b/include/swift/AST/DiagnosticsSema.h
@@ -23,7 +23,7 @@
namespace swift {
namespace diag {
- /// Describes the kind of requirement in a protocl.
+ /// Describes the kind of requirement in a protocol.
enum class RequirementKind : uint8_t {
Constructor,
Func,
diff --git a/include/swift/AST/KnownProtocols.def b/include/swift/AST/KnownProtocols.def
index a41610e..615f9d6 100644
--- a/include/swift/AST/KnownProtocols.def
+++ b/include/swift/AST/KnownProtocols.def
@@ -1,4 +1,4 @@
-//===-- KnownProtocols.def - Compiler protocol metaprogramming --*- C++ -*-===//
+//===--- KnownProtocols.def - Compiler protocol metaprogramming -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 6b6aa02..60dc438 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -252,7 +252,7 @@
return mem;
}
- /// Print a parsable and human-readable description of the identifying
+ /// Print a parseable and human-readable description of the identifying
/// information of the protocol conformance.
void printName(raw_ostream &os,
const PrintOptions &PO = PrintOptions()) const;
diff --git a/include/swift/Basic/StringExtras.h b/include/swift/Basic/StringExtras.h
index 4686012..7f3e81d 100644
--- a/include/swift/Basic/StringExtras.h
+++ b/include/swift/Basic/StringExtras.h
@@ -49,7 +49,6 @@
Unknown,
Preposition,
Verb,
- AuxiliaryVerb,
Gerund,
};
diff --git a/include/swift/IDE/REPLCodeCompletion.h b/include/swift/IDE/REPLCodeCompletion.h
index 25768a0..834a3d7 100644
--- a/include/swift/IDE/REPLCodeCompletion.h
+++ b/include/swift/IDE/REPLCodeCompletion.h
@@ -1,4 +1,4 @@
-//===--- REPLCodeCompletion.h - Code completion for REPL ----------* C++ *-===//
+//===--- REPLCodeCompletion.h - Code completion for REPL --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Parse/CodeCompletionCallbacks.h b/include/swift/Parse/CodeCompletionCallbacks.h
index 1e7f395..3b36640 100644
--- a/include/swift/Parse/CodeCompletionCallbacks.h
+++ b/include/swift/Parse/CodeCompletionCallbacks.h
@@ -1,4 +1,4 @@
-//===- CodeCompletionCallbacks.h - Parser's interface to code completion --===//
+//===--- CodeCompletionCallbacks.h - Parser's interface to code completion ===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Parse/DelayedParsingCallbacks.h b/include/swift/Parse/DelayedParsingCallbacks.h
index 671a5ad..a1ea003 100644
--- a/include/swift/Parse/DelayedParsingCallbacks.h
+++ b/include/swift/Parse/DelayedParsingCallbacks.h
@@ -1,4 +1,4 @@
-//===- DelayedParsingCallbacks.h - Callbacks for Parser's delayed parsing -===//
+//===--- DelayedParsingCallbacks.h - Delayed parsing callbacks ------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Runtime/ObjCBridge.h b/include/swift/Runtime/ObjCBridge.h
index 0fcf39c..44f2ad4 100644
--- a/include/swift/Runtime/ObjCBridge.h
+++ b/include/swift/Runtime/ObjCBridge.h
@@ -54,7 +54,7 @@
} objc_image_info;
// Class and metaclass construction from a compiler-generated memory image.
-// cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.·
+// cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
// Extra bytes not used the metadata must be zero.
// info is the same objc_image_info that would be emitted by a static compiler.
// Returns nil if a class with the same name already exists.
diff --git a/include/swift/SIL/Dominance.h b/include/swift/SIL/Dominance.h
index 6f588aa..62da9a5 100644
--- a/include/swift/SIL/Dominance.h
+++ b/include/swift/SIL/Dominance.h
@@ -138,6 +138,16 @@
if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
return true;
+ if (!R->getBlock()) {
+ // The post dom-tree has multiple roots. The compare() function can not
+ // cope with multiple roots if at least one of the roots is caused by
+ // an infinite loop in the CFG (it crashes because no nodes are allocated
+ // for the blocks in the infinite loop).
+ // So we return a conservative false in this case.
+ // TODO: eventually fix the DominatorTreeBase::compare() function.
+ return false;
+ }
+
// Returns *false* if they match.
if (compare(Other))
return true;
diff --git a/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h b/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h
index 037c8e9..602ad92 100644
--- a/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h
@@ -1,4 +1,4 @@
-//===-- ClassHierarchyAnalysis.h - Analysis of Class Hierarchy --*- C++ -*-===//
+//===--- ClassHierarchyAnalysis.h - Analysis of Class Hierarchy -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/SILOptimizer/Utils/ConstantFolding.h b/include/swift/SILOptimizer/Utils/ConstantFolding.h
index b653e74..4e90407 100644
--- a/include/swift/SILOptimizer/Utils/ConstantFolding.h
+++ b/include/swift/SILOptimizer/Utils/ConstantFolding.h
@@ -1,4 +1,4 @@
-//===-- ConstantFolding.h - Utilities for SIL constant folding --*- C++ -*-===//
+//===--- ConstantFolding.h - Utilities for SIL constant folding -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Sema/TypeCheckRequestKinds.def b/include/swift/Sema/TypeCheckRequestKinds.def
index aeef48b..e64b81b 100644
--- a/include/swift/Sema/TypeCheckRequestKinds.def
+++ b/include/swift/Sema/TypeCheckRequestKinds.def
@@ -1,4 +1,4 @@
-//===-- TypeCheckRequestKinds.def - Type Checking Request Kinds -*- C++ -*-===//
+//===--- TypeCheckRequestKinds.def - Type Check Request Kinds ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 6a181f7..0241c78 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -1003,7 +1003,6 @@
DeclIDField, // ParamDecl
BCFixed<1>, // isVariadic?
DefaultArgumentField // default argument
- // The element pattern trails the record.
>;
using ParenPatternLayout = BCRecordLayout<
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index c388060..f35eac6 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -1,4 +1,4 @@
-//===--- ASTDumper.cpp - Swift Language AST Dumper-------------------------===//
+//===--- ASTDumper.cpp - Swift Language AST Dumper ------------------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index d2140a2..2817a8a 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -1,4 +1,4 @@
-//===--- ASTPrinter.cpp - Swift Language AST Printer-----------------------===//
+//===--- ASTPrinter.cpp - Swift Language AST Printer ----------------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ea094cd..9267d5e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3152,7 +3152,7 @@
}
SourceRange VarDecl::getTypeSourceRangeForDiagnostics() const {
- // For a parameter, map back to it's parameter to get the TypeLoc.
+ // For a parameter, map back to its parameter to get the TypeLoc.
if (auto *PD = dyn_cast<ParamDecl>(this)) {
if (auto typeRepr = PD->getTypeLoc().getTypeRepr())
return typeRepr->getSourceRange();
@@ -3221,7 +3221,10 @@
}
bool VarDecl::isSelfParameter() const {
- return isa<ParamDecl>(this) && getName() == getASTContext().Id_self;
+ // Note: we need to check the isImplicit() bit here to make sure that we
+ // don't classify explicit parameters declared with `self` as the self param.
+ return isa<ParamDecl>(this) && getName() == getASTContext().Id_self &&
+ isImplicit();
}
/// Return true if this stored property needs to be accessed with getters and
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index c670d1d..aee1542 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -300,6 +300,8 @@
}
case DeclContextKind::SubscriptDecl:
+ // FIXME: We may need to do something here if subscripts contain any symbols
+ // exposed with linkage names.
return mangleContext(ctx->getParent(), shouldBind);
case DeclContextKind::Initializer:
diff --git a/lib/AST/Verifier.cpp b/lib/AST/Verifier.cpp
index 2cd714c..820a987 100644
--- a/lib/AST/Verifier.cpp
+++ b/lib/AST/Verifier.cpp
@@ -1618,7 +1618,6 @@
// Make sure that there are no archetypes in the interface type.
if (VD->getDeclContext()->isTypeContext() &&
!hasEnclosingFunctionContext(VD->getDeclContext()) &&
- // !isa<ParamDecl>(VD) && /* because of subscripts */
VD->getInterfaceType().findIf([](Type type) {
return type->is<ArchetypeType>();
})) {
diff --git a/lib/Basic/PartsOfSpeech.def b/lib/Basic/PartsOfSpeech.def
index 713867c..dec4af5 100644
--- a/lib/Basic/PartsOfSpeech.def
+++ b/lib/Basic/PartsOfSpeech.def
@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
// This file lists words that map to various parts of speech.
-// ===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
#if !defined(PREPOSITION) && !defined(VERB)
# error define one or more of PREPOSITION, VERB
@@ -28,10 +28,6 @@
# define VERB(Word)
#endif
-#ifndef AUXILIARY_VERB
-# define AUXILIARY_VERB(Word)
-#endif
-
DIRECTIONAL_PREPOSITION(above)
DIRECTIONAL_PREPOSITION(after)
DIRECTIONAL_PREPOSITION(along)
@@ -842,33 +838,6 @@
VERB(zip)
VERB(zoom)
-AUXILIARY_VERB(am)
-AUXILIARY_VERB(are)
-AUXILIARY_VERB(been)
-AUXILIARY_VERB(being)
-AUXILIARY_VERB(can)
-AUXILIARY_VERB(could)
-AUXILIARY_VERB(did)
-AUXILIARY_VERB(does)
-AUXILIARY_VERB(had)
-AUXILIARY_VERB(has)
-AUXILIARY_VERB(have)
-AUXILIARY_VERB(having)
-AUXILIARY_VERB(is)
-AUXILIARY_VERB(may)
-AUXILIARY_VERB(might)
-AUXILIARY_VERB(must)
-AUXILIARY_VERB(need)
-AUXILIARY_VERB(needs)
-AUXILIARY_VERB(ought)
-AUXILIARY_VERB(shall)
-AUXILIARY_VERB(should)
-AUXILIARY_VERB(was)
-AUXILIARY_VERB(were)
-AUXILIARY_VERB(will)
-AUXILIARY_VERB(would)
-
-#undef AUXILIARY_VERB
#undef VERB
#undef DIRECTIONAL_PREPOSITION
#undef PREPOSITION
diff --git a/lib/Basic/StringExtras.cpp b/lib/Basic/StringExtras.cpp
index c4601ac..3ffb9f4 100644
--- a/lib/Basic/StringExtras.cpp
+++ b/lib/Basic/StringExtras.cpp
@@ -54,9 +54,6 @@
#define VERB(Word) \
if (word.equals_lower(#Word)) \
return PartOfSpeech::Verb;
-#define AUXILIARY_VERB(Word) \
- if (word.equals_lower(#Word)) \
- return PartOfSpeech::AuxiliaryVerb;
#include "PartsOfSpeech.def"
// Identify gerunds, which always end in "ing".
@@ -671,7 +668,6 @@
break;
case PartOfSpeech::Unknown:
- case PartOfSpeech::AuxiliaryVerb:
// Assume it's a noun or adjective; don't strip anything.
break;
}
@@ -703,23 +699,6 @@
return name;
}
-/// Determine whether the given word indicates a boolean result.
-static bool nameIndicatesBooleanResult(StringRef name) {
- for (auto word: camel_case::getWords(name)) {
- // Auxiliary verbs indicate Boolean results.
- if (getPartOfSpeech(word) == PartOfSpeech::AuxiliaryVerb)
- return true;
-
- // Words that end in "s" indicate either Boolean results---it
- // could be a verb in the present continuous tense---or some kind
- // of plural, for which "is" would be inappropriate anyway.
- if (word.back() == 's')
- return true;
- }
-
- return false;
-}
-
/// A form of toLowercaseWord that also lowercases acronyms.
static StringRef toLowercaseWordAndAcronym(StringRef string,
StringScratchSpace &scratch) {
@@ -730,12 +709,19 @@
if (!clang::isUppercase(string[0]))
return string;
- // Lowercase until we hit the end there is an uppercase letter
- // followed by a non-uppercase letter.
+ // Lowercase until we hit the an uppercase letter followed by a
+ // non-uppercase letter.
llvm::SmallString<32> scratchStr;
for (unsigned i = 0, n = string.size(); i != n; ++i) {
// If the next character is not uppercase, stop.
if (i < n - 1 && !clang::isUppercase(string[i+1])) {
+ // If the next non-uppercase character was alphanumeric, we should
+ // still lowercase the character we're on.
+ if (!clang::isLetter(string[i+1])) {
+ scratchStr.push_back(clang::toLowercase(string[i]));
+ ++i;
+ }
+
scratchStr.append(string.substr(i));
break;
}
@@ -805,16 +791,6 @@
}
}
- // Boolean properties should start with "is", unless their
- // first word already implies a Boolean result.
- if (resultType.isBoolean() && isProperty &&
- !nameIndicatesBooleanResult(baseName)) {
- SmallString<32> newName("is");
- camel_case::appendSentenceCase(newName, baseName);
- baseName = scratch.copyString(newName);
- anyChanges = true;
- }
-
return lowercaseAcronymsForReturn();
}
@@ -864,7 +840,6 @@
break;
case PartOfSpeech::Unknown:
- case PartOfSpeech::AuxiliaryVerb:
++nameWordRevIter;
break;
}
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 4f104ae..aa11c2c 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -2209,6 +2209,16 @@
case clang::DeclarationName::Identifier:
// Map the identifier.
baseName = D->getDeclName().getAsIdentifierInfo()->getName();
+
+ if (OmitNeedlessWords) {
+ // For Objective-C BOOL properties, use the name of the getter
+ // which, conventionally, has an "is" prefix.
+ if (auto property = dyn_cast<clang::ObjCPropertyDecl>(D)) {
+ if (isBoolType(clangSema.Context, property->getType()))
+ baseName = property->getGetterName().getNameForSlot(0);
+ }
+ }
+
break;
case clang::DeclarationName::ObjCMultiArgSelector:
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index bc96293..7891701 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -2454,9 +2454,7 @@
decl->isVariadic(),
decl->isNoReturn(),
isInSystemModule(dc),
- hasCustomName,
- &bodyParams,
- name);
+ hasCustomName, bodyParams, name);
if (!type)
return nullptr;
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index ddb84e0..962999a 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -1333,7 +1333,7 @@
ArrayRef<const clang::ParmVarDecl *> params,
bool isVariadic, bool isNoReturn,
bool isFromSystemModule, bool hasCustomName,
- ParameterList **parameterList, DeclName &name) {
+ ParameterList *¶meterList, DeclName &name) {
bool allowNSUIntegerAsInt = isFromSystemModule;
if (allowNSUIntegerAsInt) {
@@ -1461,13 +1461,13 @@
}
// Form the parameter list.
- *parameterList = ParameterList::create(SwiftContext, parameters);
+ parameterList = ParameterList::create(SwiftContext, parameters);
FunctionType::ExtInfo extInfo;
extInfo = extInfo.withIsNoReturn(isNoReturn);
// Form the function type.
- auto argTy = (*parameterList)->getType(SwiftContext);
+ auto argTy = parameterList->getType(SwiftContext);
return FunctionType::get(argTy, swiftResultTy, extInfo);
}
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index 55804c2..f62f865 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -1,4 +1,4 @@
-//===--- ImporterImpl.h - Import Clang Modules - Implementation------------===//
+//===--- ImporterImpl.h - Import Clang Modules: Implementation ------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -1128,7 +1128,7 @@
bool isVariadic, bool isNoReturn,
bool isFromSystemModule,
bool hasCustomName,
- ParameterList **parameterList,
+ ParameterList *¶meterList,
DeclName &name);
Type importPropertyType(const clang::ObjCPropertyDecl *clangDecl,
diff --git a/lib/ClangImporter/InferredAttributes.def b/lib/ClangImporter/InferredAttributes.def
index 6af823a..54a14a3 100644
--- a/lib/ClangImporter/InferredAttributes.def
+++ b/lib/ClangImporter/InferredAttributes.def
@@ -22,7 +22,7 @@
// ClassName is the name of the class, i.e., NSManagedObject
// AttributeSet is an OR of attribute names, i.e., requires_stored_property_inits
//
-// ===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
#ifndef INFERRED_ATTRIBUTES
# define INFERRED_ATTRIBUTES(ModuleName, ClassName, AttributeSet)
diff --git a/lib/ClangImporter/MacroTable.def b/lib/ClangImporter/MacroTable.def
index 6a11308..11fc681 100644
--- a/lib/ClangImporter/MacroTable.def
+++ b/lib/ClangImporter/MacroTable.def
@@ -13,7 +13,7 @@
// This file defines the database of macros that should be suppressed during
// API import.
//
-// ===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
#ifndef SUPPRESS_MACRO
/// Describes a macro that should be suppressed.
diff --git a/lib/ClangImporter/SortedCFDatabase.def.gyb b/lib/ClangImporter/SortedCFDatabase.def.gyb
index f77c046..04d327e 100644
--- a/lib/ClangImporter/SortedCFDatabase.def.gyb
+++ b/lib/ClangImporter/SortedCFDatabase.def.gyb
@@ -28,7 +28,7 @@
lineForName = {}
# Load the data file.
-with codecs.open(CFDatabaseFile, encoding=sys.getfilesystemencoding(), errors='strict') as f:
+with codecs.open(CFDatabaseFile, encoding='utf-8', errors='strict') as f:
for line in f:
# Pass through preprocessor directives literally.
# Assume that they all fall into either a strict prologue or epilogue.
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index 8be90e7..ad4845b 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -48,6 +48,7 @@
SyntaxModelContext::SyntaxModelContext(SourceFile &SrcFile)
: Impl(*new Implementation(SrcFile)) {
+ const bool IsPlayground = Impl.LangOpts.Playground;
const SourceManager &SM = Impl.SrcMgr;
std::vector<Token> Tokens = swift::tokenize(Impl.LangOpts, SM,
*Impl.SrcFile.getBufferID(),
@@ -111,7 +112,8 @@
case tok::floating_literal: Kind = SyntaxNodeKind::Floating; break;
case tok::string_literal: Kind = SyntaxNodeKind::String; break;
case tok::comment:
- if (Tok.getText().startswith("///"))
+ if (Tok.getText().startswith("///") ||
+ (IsPlayground && Tok.getText().startswith("//:")))
Kind = SyntaxNodeKind::DocCommentLine;
else if (Tok.getText().startswith("/**"))
Kind = SyntaxNodeKind::DocCommentBlock;
diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt
index 2fb2169..587d93c 100644
--- a/lib/IRGen/CMakeLists.txt
+++ b/lib/IRGen/CMakeLists.txt
@@ -30,6 +30,7 @@
IRGenModule.cpp
IRGenSIL.cpp
Linking.cpp
+ LocalTypeData.cpp
SwiftTargetInfo.cpp
StructLayout.cpp
TypeLayoutVerifier.cpp
diff --git a/lib/IRGen/DominancePoint.h b/lib/IRGen/DominancePoint.h
new file mode 100644
index 0000000..c99611e
--- /dev/null
+++ b/lib/IRGen/DominancePoint.h
@@ -0,0 +1,77 @@
+//===--- DominancePoint.h - Dominance points ----------------------*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines types relating to local dominance calculations
+// during the emission of a function.
+//
+// During the emission of a function, the LLVM IR is not well-formed enough
+// to do accurate dominance computations. For example, a basic block may
+// appear to have a single predecessor, but that may be because a different
+// predecessor has not yet been added.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_DOMINANCEPOINT_H
+#define SWIFT_IRGEN_DOMINANCEPOINT_H
+
+#include <assert.h>
+#include <stdint.h>
+
+namespace swift {
+namespace irgen {
+ class IRGenFunction;
+
+/// An opaque class for storing keys for the dominance callback. The
+/// key is assumed to be something like a (uniqued) pointer, and a
+/// null pointer is assumed to mean a non-dominating point.
+class DominancePoint {
+ uintptr_t Value;
+ enum : uintptr_t {
+ Universal = 0,
+ };
+ explicit DominancePoint(uintptr_t value) : Value(value) {}
+public:
+ explicit DominancePoint(void *value)
+ : Value(reinterpret_cast<uintptr_t>(value)) {
+ assert(isOrdinary());
+ }
+
+ /// Something about the definition is known to dominate all possible
+ /// places that will use it.
+ static DominancePoint universal() { return DominancePoint(Universal); }
+
+ bool isOrdinary() const {
+ return Value != Universal;
+ }
+ bool isUniversal() const {
+ return Value == Universal;
+ }
+
+ template <class T> T* as() const {
+ assert(isOrdinary());
+ return reinterpret_cast<T*>(Value);
+ }
+ bool operator==(DominancePoint other) const { return Value == other.Value; }
+};
+
+/// A dominance resolver is a function that answers the question of
+/// whether one dominance point dominates another.
+///
+/// It will only be asked this question with ordinary dominance points.
+using DominanceResolverFunction = bool(*)(IRGenFunction &IGF,
+ DominancePoint curPoint,
+ DominancePoint definingPoint);
+
+}
+}
+
+#endif
diff --git a/lib/IRGen/DominanceScope.h b/lib/IRGen/DominanceScope.h
new file mode 100644
index 0000000..f0a327e
--- /dev/null
+++ b/lib/IRGen/DominanceScope.h
@@ -0,0 +1,82 @@
+//===--- DominanceScope.h - Dominance scoping ---------------------*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines types relating to local dominance calculations
+// during the emission of a function.
+//
+// During the emission of a function, the LLVM IR is not well-formed enough
+// to do accurate dominance computations. For example, a basic block may
+// appear to have a single predecessor, but that may be because a different
+// predecessor has not yet been added.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_DOMINANCEPOINT_H
+#define SWIFT_IRGEN_DOMINANCEPOINT_H
+
+#include <stdint.h>
+
+namespace swift {
+namespace irgen {
+ class IRGenFunction;
+
+/// An opaque class for storing keys for the dominance callback. The
+/// key is assumed to be something like a (uniqued) pointer, and a
+/// null pointer is assumed to mean a non-dominating point.
+class DominancePoint {
+ uintptr_t Value;
+ enum : uintptr_t {
+ Universal = 0,
+ Unknown = 1,
+ };
+ explicit DominancePoint(uintptr_t value) : Value(value) {}
+public:
+ explicit DominancePoint(void *value)
+ : Value(reinterpret_cast<uintptr_t>(value)) {
+ assert(isOrdinary());
+ }
+
+ /// Something about the definition is known to dominate all possible
+ /// places that will use it.
+ static DominancePoint universal() { return DominanceKey(Universal); }
+
+ /// This definition point has non-obvious dominance rules; don't put
+ /// anything here and assume it'll dominate other things. This should be
+ /// used when IRGen adds its own control flow that might interact awkwardly
+ /// with dominance.
+ static DominancePoint unknown() { return DominanceKey(Unknown); }
+
+ bool isOrdinary() {
+ return Value > Uncacheable;
+ }
+ bool isUniversal() {
+ return Value == Universal;
+ }
+ bool isUnknown() {
+ return Value == Unknown;
+ }
+
+ template <class T> T* as() const {
+ assert(isOrdinary());
+ return reinterpret_cast<T*>(Value);
+ }
+ bool operator==(DominancePoint other) const { return Value == other.Value; }
+};
+
+using DominanceResolverFunction = bool(*)(IRGenFunction &IGF,
+ DominancePoint curPoint,
+ DominancePoint definingPoint);
+
+}
+}
+
+#endif
\ No newline at end of file
diff --git a/lib/IRGen/EnumPayload.h b/lib/IRGen/EnumPayload.h
index 34437db..3b675f4 100644
--- a/lib/IRGen/EnumPayload.h
+++ b/lib/IRGen/EnumPayload.h
@@ -1,4 +1,4 @@
-//===--- EnumPayload.h - Payload management for 'enum' Types ------* C++ *-===//
+//===--- EnumPayload.h - Payload management for 'enum' Types ----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp
index d451026..c02908b 100644
--- a/lib/IRGen/Fulfillment.cpp
+++ b/lib/IRGen/Fulfillment.cpp
@@ -327,3 +327,18 @@
return true;
}
}
+
+bool FulfillmentMap::Everything::isInterestingType(CanType type) const {
+ return true;
+}
+bool FulfillmentMap::Everything::hasInterestingType(CanType type) const {
+ return true;
+}
+bool FulfillmentMap::Everything
+ ::hasLimitedInterestingConformances(CanType type) const {
+ return false;
+}
+GenericSignature::ConformsToArray
+FulfillmentMap::Everything::getInterestingConformances(CanType type) const{
+ return {};
+}
diff --git a/lib/IRGen/Fulfillment.h b/lib/IRGen/Fulfillment.h
index 7679050..c4826bd 100644
--- a/lib/IRGen/Fulfillment.h
+++ b/lib/IRGen/Fulfillment.h
@@ -71,8 +71,22 @@
virtual ~InterestingKeysCallback() = default;
};
+ /// An implementaton of InterestingKeysCallback that returns everything
+ /// fulfillable.
+ struct Everything : InterestingKeysCallback {
+ bool isInterestingType(CanType type) const override;
+ bool hasInterestingType(CanType type) const override;
+ bool hasLimitedInterestingConformances(CanType type) const override;
+ GenericSignature::ConformsToArray
+ getInterestingConformances(CanType type) const override;
+ };
+
FulfillmentMap() = default;
+ using iterator = decltype(Fulfillments)::iterator;
+ iterator begin() { return Fulfillments.begin(); }
+ iterator end() { return Fulfillments.end(); }
+
/// Is it even theoretically possible that we might find a fulfillment
/// in the given type?
static bool isInterestingTypeForFulfillments(CanType type) {
diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp
index 2e1e82f..ec23b39 100644
--- a/lib/IRGen/GenArchetype.cpp
+++ b/lib/IRGen/GenArchetype.cpp
@@ -53,7 +53,7 @@
static llvm::Value *emitArchetypeTypeMetadataRef(IRGenFunction &IGF,
CanArchetypeType archetype) {
- return IGF.getLocalTypeData(archetype, LocalTypeData::forMetatype());
+ return IGF.getLocalTypeData(archetype, LocalTypeDataKind::forMetatype());
}
namespace {
@@ -88,8 +88,9 @@
CanArchetypeType archetype,
unsigned which) const {
assert(which < getNumStoredProtocols());
+ auto protocol = archetype->getConformsTo()[which];
return IGF.getLocalTypeData(archetype,
- LocalTypeData::forArchetypeProtocolWitness(which));
+ LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol));
}
};
@@ -274,7 +275,7 @@
llvm::Value *metadata) {
assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
IGF.setUnscopedLocalTypeData(CanType(archetype),
- LocalTypeData::forMetatype(),
+ LocalTypeDataKind::forMetatype(),
metadata);
// Create a shadow copy of the metadata in an alloca for the debug info.
@@ -298,8 +299,10 @@
llvm::Value *wtable) {
assert(wtable->getType() == IGF.IGM.WitnessTablePtrTy);
assert(protocolIndex < archetype->getConformsTo().size());
+ auto protocol = archetype->getConformsTo()[protocolIndex];
IGF.setUnscopedLocalTypeData(CanType(archetype),
- LocalTypeData::forArchetypeProtocolWitness(protocolIndex), wtable);
+ LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol),
+ wtable);
}
/// Inform IRGenFunction that the given archetype has the given value
diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp
index 1b77d3e..01bc6ab 100644
--- a/lib/IRGen/GenCast.cpp
+++ b/lib/IRGen/GenCast.cpp
@@ -320,7 +320,7 @@
llvm::Twine(name), IGM.getModule());
fn->setAttributes(IGM.constructInitialAttributes());
- auto IGF = IRGenFunction(IGM, fn);
+ IRGenFunction IGF(IGM, fn);
Explosion args = IGF.collectParameters();
auto value = args.claimNext();
@@ -593,6 +593,7 @@
// If we're doing a conditional cast, and the ObjC protocol checks failed,
// then the cast is done.
+ Optional<ConditionalDominanceScope> condition;
llvm::BasicBlock *origBB = nullptr, *successBB = nullptr, *contBB = nullptr;
if (!objcProtos.empty()) {
switch (mode) {
@@ -607,6 +608,7 @@
cast<llvm::PointerType>(objcCast->getType())));
IGF.Builder.CreateCondBr(isNull, contBB, successBB);
IGF.Builder.emitBlock(successBB);
+ condition.emplace(IGF);
}
}
}
@@ -658,6 +660,7 @@
// If we had conditional ObjC checks, join the failure paths.
if (contBB) {
+ condition.reset();
IGF.Builder.CreateBr(contBB);
IGF.Builder.emitBlock(contBB);
diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp
index d6265e6..5e394c9 100644
--- a/lib/IRGen/GenEnum.cpp
+++ b/lib/IRGen/GenEnum.cpp
@@ -561,6 +561,7 @@
IGF.Builder.CreateCondBr(xiBool, xiBB, noXIBB);
IGF.Builder.emitBlock(xiBB);
+ ConditionalDominanceScope condition(IGF);
copyWitnessFromElt(ValueWitness::ExtraInhabitantFlags);
IGF.Builder.CreateBr(noXIBB);
@@ -2083,6 +2084,7 @@
llvm::BasicBlock *endBB = testFixedEnumContainsPayload(IGF, payload, extraTag);
if (PayloadBitCount > 0) {
+ ConditionalDominanceScope condition(IGF);
Explosion payloadValue;
Explosion payloadCopy;
auto &loadableTI = getLoadablePayloadTypeInfo();
@@ -2131,6 +2133,7 @@
// If we did, consume it.
if (PayloadBitCount > 0) {
+ ConditionalDominanceScope condition(IGF);
Explosion payloadValue;
auto &loadableTI = getLoadablePayloadTypeInfo();
loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
@@ -2173,6 +2176,7 @@
// If we did, consume it.
if (PayloadBitCount > 0) {
+ ConditionalDominanceScope condition(IGF);
Explosion payloadValue;
auto &loadableTI = getLoadablePayloadTypeInfo();
loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
@@ -2205,6 +2209,8 @@
// Check that there is a payload at the address.
llvm::BasicBlock *endBB = testEnumContainsPayload(IGF, addr, T);
+ ConditionalDominanceScope condition(IGF);
+
// If there is, project and destroy it.
Address payloadAddr = projectPayloadData(IGF, addr);
getPayloadTypeInfo().destroy(IGF, payloadAddr,
@@ -2288,46 +2294,64 @@
llvm::BasicBlock *noDestPayloadBB
= testEnumContainsPayload(IGF, dest, T);
- // Here, the destination has a payload. Now see if the source also has
- // one.
- llvm::BasicBlock *destNoSrcPayloadBB
- = testEnumContainsPayload(IGF, src, T);
+ {
+ ConditionalDominanceScope destCondition(IGF);
- // Here, both source and destination have payloads. Do the reassignment
- // of the payload in-place.
- if (isTake)
- getPayloadTypeInfo().assignWithTake(IGF, destData, srcData, PayloadT);
- else
- getPayloadTypeInfo().assignWithCopy(IGF, destData, srcData, PayloadT);
- IGF.Builder.CreateBr(endBB);
+ // Here, the destination has a payload. Now see if the source also
+ // has one.
+ llvm::BasicBlock *destNoSrcPayloadBB
+ = testEnumContainsPayload(IGF, src, T);
- // If the destination has a payload but the source doesn't, we can destroy
- // the payload and primitive-store the new no-payload value.
- IGF.Builder.emitBlock(destNoSrcPayloadBB);
- getPayloadTypeInfo().destroy(IGF, destData, PayloadT);
- emitPrimitiveCopy(IGF, dest, src, T);
- IGF.Builder.CreateBr(endBB);
+ {
+ ConditionalDominanceScope destSrcCondition(IGF);
+
+ // Here, both source and destination have payloads. Do the
+ // reassignment of the payload in-place.
+ getPayloadTypeInfo().assign(IGF, destData, srcData,
+ isTake, PayloadT);
+ IGF.Builder.CreateBr(endBB);
+ }
+
+ // If the destination has a payload but the source doesn't, we can
+ // destroy the payload and primitive-store the new no-payload value.
+ IGF.Builder.emitBlock(destNoSrcPayloadBB);
+ {
+ ConditionalDominanceScope destNoSrcCondition(IGF);
+ getPayloadTypeInfo().destroy(IGF, destData, PayloadT);
+ emitPrimitiveCopy(IGF, dest, src, T);
+ IGF.Builder.CreateBr(endBB);
+ }
+ }
// Now, if the destination has no payload, check if the source has one.
IGF.Builder.emitBlock(noDestPayloadBB);
- llvm::BasicBlock *noDestNoSrcPayloadBB
- = testEnumContainsPayload(IGF, src, T);
+ {
+ ConditionalDominanceScope noDestCondition(IGF);
+ llvm::BasicBlock *noDestNoSrcPayloadBB
+ = testEnumContainsPayload(IGF, src, T);
- // Here, the source has a payload but the destination doesn't. We can
- // copy-initialize the source over the destination, then primitive-store
- // the zero extra tag (if any).
- if (isTake)
- getPayloadTypeInfo().initializeWithTake(IGF, destData, srcData, PayloadT);
- else
- getPayloadTypeInfo().initializeWithCopy(IGF, destData, srcData, PayloadT);
- emitInitializeExtraTagBitsForPayload(IGF, dest, T);
- IGF.Builder.CreateBr(endBB);
+ {
+ ConditionalDominanceScope noDestSrcCondition(IGF);
- // If neither destination nor source have payloads, we can just primitive-
- // store the new empty-case value.
- IGF.Builder.emitBlock(noDestNoSrcPayloadBB);
- emitPrimitiveCopy(IGF, dest, src, T);
- IGF.Builder.CreateBr(endBB);
+ // Here, the source has a payload but the destination doesn't.
+ // We can copy-initialize the source over the destination, then
+ // primitive-store the zero extra tag (if any).
+
+ getPayloadTypeInfo().initialize(IGF, destData, srcData, isTake,
+ PayloadT);
+ emitInitializeExtraTagBitsForPayload(IGF, dest, T);
+ IGF.Builder.CreateBr(endBB);
+ }
+
+ // If neither destination nor source have payloads, we can just
+ // primitive- store the new empty-case value.
+ IGF.Builder.emitBlock(noDestNoSrcPayloadBB);
+ {
+ ConditionalDominanceScope noDestNoSrcCondition(IGF);
+ emitPrimitiveCopy(IGF, dest, src, T);
+ IGF.Builder.CreateBr(endBB);
+ }
+ }
IGF.Builder.emitBlock(endBB);
return;
@@ -2377,22 +2401,25 @@
llvm::BasicBlock *noSrcPayloadBB
= testEnumContainsPayload(IGF, src, T);
- // Here, the source value has a payload. Initialize the destination with
- // it, and set the extra tag if any to zero.
- if (isTake)
- getPayloadTypeInfo().initializeWithTake(IGF, destData, srcData,
- getPayloadType(IGF.IGM, T));
- else
- getPayloadTypeInfo().initializeWithCopy(IGF, destData, srcData,
- getPayloadType(IGF.IGM, T));
- emitInitializeExtraTagBitsForPayload(IGF, dest, T);
- IGF.Builder.CreateBr(endBB);
+ {
+ ConditionalDominanceScope condition(IGF);
+
+ // Here, the source value has a payload. Initialize the destination
+ // with it, and set the extra tag if any to zero.
+ getPayloadTypeInfo().initialize(IGF, destData, srcData, isTake,
+ getPayloadType(IGF.IGM, T));
+ emitInitializeExtraTagBitsForPayload(IGF, dest, T);
+ IGF.Builder.CreateBr(endBB);
+ }
// If the source value has no payload, we can primitive-store the
// empty-case value.
IGF.Builder.emitBlock(noSrcPayloadBB);
- emitPrimitiveCopy(IGF, dest, src, T);
- IGF.Builder.CreateBr(endBB);
+ {
+ ConditionalDominanceScope condition(IGF);
+ emitPrimitiveCopy(IGF, dest, src, T);
+ IGF.Builder.CreateBr(endBB);
+ }
IGF.Builder.emitBlock(endBB);
return;
@@ -3561,6 +3588,8 @@
auto *caseBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
swi->addCase(llvm::ConstantInt::get(tagTy, tagIndex), caseBB);
+ ConditionalDominanceScope condition(IGF);
+
IGF.Builder.emitBlock(caseBB);
f(tagIndex, payloadCasePair);
IGF.Builder.CreateBr(endBB);
@@ -3765,6 +3794,7 @@
auto *noAliasBB = llvm::BasicBlock::Create(C);
IGF.Builder.CreateCondBr(alias, endBB, noAliasBB);
IGF.Builder.emitBlock(noAliasBB);
+ ConditionalDominanceScope condition(IGF);
// Destroy the old value.
destroy(IGF, dest, T);
@@ -3843,6 +3873,8 @@
swi->addCase(llvm::ConstantInt::get(tagTy, tagIndex), caseBB);
IGF.Builder.emitBlock(caseBB);
+ ConditionalDominanceScope condition(IGF);
+
// Do the take/copy of the payload.
Address srcData = IGF.Builder.CreateBitCast(src,
payloadTI.getStorageType()->getPointerTo());
@@ -3869,6 +3901,7 @@
// For trivial payloads (including no-payload cases), we can just
// primitive-copy to the destination.
IGF.Builder.emitBlock(trivialBB);
+ ConditionalDominanceScope condition(IGF);
emitPrimitiveCopy(IGF, dest, src, T);
IGF.Builder.CreateBr(endBB);
@@ -4114,14 +4147,20 @@
IGF.Builder.CreateCondBr(cond, noPayloadBB, payloadBB);
IGF.Builder.emitBlock(noPayloadBB);
- llvm::Value *noPayloadTag = IGF.Builder.CreateSub(tag, numPayloadCases);
- storeNoPayloadTag(IGF, enumAddr, noPayloadTag, T);
- IGF.Builder.CreateBr(endBB);
-
+ {
+ ConditionalDominanceScope condition(IGF);
+ llvm::Value *noPayloadTag = IGF.Builder.CreateSub(tag, numPayloadCases);
+ storeNoPayloadTag(IGF, enumAddr, noPayloadTag, T);
+ IGF.Builder.CreateBr(endBB);
+ }
+
IGF.Builder.emitBlock(payloadBB);
- storePayloadTag(IGF, enumAddr, tag, T);
- IGF.Builder.CreateBr(endBB);
-
+ {
+ ConditionalDominanceScope condition(IGF);
+ storePayloadTag(IGF, enumAddr, tag, T);
+ IGF.Builder.CreateBr(endBB);
+ }
+
IGF.Builder.emitBlock(endBB);
}
diff --git a/lib/IRGen/GenEnum.h b/lib/IRGen/GenEnum.h
index 2b3e70b..e9fbe68 100644
--- a/lib/IRGen/GenEnum.h
+++ b/lib/IRGen/GenEnum.h
@@ -1,4 +1,4 @@
-//===--- GenEnum.h - Swift IR Generation For 'enum' Types ---------* C++ *-===//
+//===--- GenEnum.h - Swift IR Generation For 'enum' Types -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index 9d64992..d5265fb 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -1501,6 +1501,8 @@
// Project down to the buffers.
IGF.Builder.emitBlock(contBB);
+ // We don't need a ConditionalDominanceScope here because (1) there's no
+ // code in the other condition and (2) we immediately return.
Address destBuffer = layout.projectExistentialBuffer(IGF, dest);
Address srcBuffer = layout.projectExistentialBuffer(IGF, src);
@@ -1516,10 +1518,10 @@
IGF.Builder.CreateICmpEQ(destMetadata, srcMetadata, "sameMetadata");
IGF.Builder.CreateCondBr(sameMetadata, matchBB, noMatchBB);
- { // (scope to avoid contaminating other branches with these values)
-
- // If so, do a direct assignment.
- IGF.Builder.emitBlock(matchBB);
+ // If so, do a direct assignment.
+ IGF.Builder.emitBlock(matchBB);
+ {
+ ConditionalDominanceScope matchCondition(IGF);
llvm::Value *destObject =
emitProjectBufferCall(IGF, destMetadata, destBuffer);
@@ -1537,30 +1539,33 @@
// the madnesses that boost::variant has to go through, with the
// advantage of address-invariance.
IGF.Builder.emitBlock(noMatchBB);
+ {
+ ConditionalDominanceScope noMatchCondition(IGF);
- // Store the metadata ref.
- IGF.Builder.CreateStore(srcMetadata, destMetadataSlot);
+ // Store the metadata ref.
+ IGF.Builder.CreateStore(srcMetadata, destMetadataSlot);
- // Store the protocol witness tables.
- unsigned numTables = layout.getNumTables();
- for (unsigned i = 0, e = numTables; i != e; ++i) {
- Address destTableSlot = layout.projectWitnessTable(IGF, dest, i);
- llvm::Value *srcTable = layout.loadWitnessTable(IGF, src, i);
+ // Store the protocol witness tables.
+ unsigned numTables = layout.getNumTables();
+ for (unsigned i = 0, e = numTables; i != e; ++i) {
+ Address destTableSlot = layout.projectWitnessTable(IGF, dest, i);
+ llvm::Value *srcTable = layout.loadWitnessTable(IGF, src, i);
- // Overwrite the old witness table.
- IGF.Builder.CreateStore(srcTable, destTableSlot);
+ // Overwrite the old witness table.
+ IGF.Builder.CreateStore(srcTable, destTableSlot);
+ }
+
+ // Destroy the old value.
+ emitDestroyBufferCall(IGF, destMetadata, destBuffer);
+
+ // Copy-initialize with the new value. Again, pull a value
+ // witness table from the source metadata if we can't use a
+ // protocol witness table.
+ emitInitializeBufferWithCopyOfBufferCall(IGF, srcMetadata,
+ destBuffer, srcBuffer);
+ IGF.Builder.CreateBr(doneBB);
}
- // Destroy the old value.
- emitDestroyBufferCall(IGF, destMetadata, destBuffer);
-
- // Copy-initialize with the new value. Again, pull a value
- // witness table from the source metadata if we can't use a
- // protocol witness table.
- emitInitializeBufferWithCopyOfBufferCall(IGF, srcMetadata,
- destBuffer, srcBuffer);
- IGF.Builder.CreateBr(doneBB);
-
// All done.
IGF.Builder.emitBlock(doneBB);
IGF.Builder.CreateRetVoid();
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index c88ac9c..efc7097 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -165,20 +165,17 @@
llvm::Value *metadata = claimNext(IGF.IGM.TypeMetadataPtrTy);
metadata->setName(archetype->getFullName());
IGF.setUnscopedLocalTypeData(CanType(archetype),
- LocalTypeData::forMetatype(),
+ LocalTypeDataKind::forMetatype(),
metadata);
}
// Bind all the argument witness tables.
for (auto archetype : generics.getAllArchetypes()) {
- unsigned nextProtocolIndex = 0;
for (auto protocol : archetype->getConformsTo()) {
- LocalTypeData key
- = LocalTypeData::forArchetypeProtocolWitness(nextProtocolIndex);
- nextProtocolIndex++;
if (!Lowering::TypeConverter::protocolRequiresWitnessTable(protocol))
continue;
llvm::Value *wtable = claimNext(IGF.IGM.WitnessTablePtrTy);
+ auto key = LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol);
IGF.setUnscopedLocalTypeData(CanType(archetype), key, wtable);
}
}
@@ -289,7 +286,7 @@
// reference already.
if (isPattern) {
if (auto cache = IGF.tryGetLocalTypeData(theType,
- LocalTypeData::forMetatype()))
+ LocalTypeDataKind::forMetatype()))
return cache;
}
@@ -325,7 +322,8 @@
result->setDoesNotThrow();
result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::ReadNone);
- IGF.setScopedLocalTypeData(theType, LocalTypeData::forMetatype(), result);
+ IGF.setScopedLocalTypeData(theType, LocalTypeDataKind::forMetatype(),
+ result);
return result;
}
@@ -356,7 +354,8 @@
result->setDoesNotThrow();
result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::ReadNone);
- IGF.setScopedLocalTypeData(theType, LocalTypeData::forMetatype(), result);
+ IGF.setScopedLocalTypeData(theType, LocalTypeDataKind::forMetatype(),
+ result);
return result;
}
@@ -388,7 +387,7 @@
IGF.Builder.CreateLifetimeEnd(argsBuffer,
IGF.IGM.getPointerSize() * genericArgs.Values.size());
- IGF.setScopedLocalTypeData(theType, LocalTypeData::forMetatype(), result);
+ IGF.setScopedLocalTypeData(theType, LocalTypeDataKind::forMetatype(), result);
return result;
}
@@ -963,7 +962,7 @@
}
llvm::Value *visitArchetypeType(CanArchetypeType type) {
- return IGF.getLocalTypeData(type, LocalTypeData::forMetatype());
+ return IGF.getLocalTypeData(type, LocalTypeDataKind::forMetatype());
}
llvm::Value *visitGenericTypeParamType(CanGenericTypeParamType type) {
@@ -992,12 +991,12 @@
/// Try to find the metatype in local data.
llvm::Value *tryGetLocal(CanType type) {
- return IGF.tryGetLocalTypeData(type, LocalTypeData::forMetatype());
+ return IGF.tryGetLocalTypeData(type, LocalTypeDataKind::forMetatype());
}
/// Set the metatype in local data.
llvm::Value *setLocal(CanType type, llvm::Instruction *metatype) {
- IGF.setScopedLocalTypeData(type, LocalTypeData::forMetatype(),
+ IGF.setScopedLocalTypeData(type, LocalTypeDataKind::forMetatype(),
metatype);
return metatype;
}
@@ -1156,7 +1155,8 @@
CanType type,
ForDefinition_t shouldDefine) {
// If we already cached the metadata, use it.
- if (auto local = IGF.tryGetLocalTypeData(type, LocalTypeData::forMetatype()))
+ if (auto local =
+ IGF.tryGetLocalTypeData(type, LocalTypeDataKind::forMetatype()))
return local;
llvm::Constant *accessor =
@@ -1167,7 +1167,7 @@
call->setDoesNotThrow();
// Save the metadata for future lookups.
- IGF.setScopedLocalTypeData(type, LocalTypeData::forMetatype(), call);
+ IGF.setScopedLocalTypeData(type, LocalTypeDataKind::forMetatype(), call);
return call;
}
@@ -1394,13 +1394,13 @@
llvm::Value *tryGetLocal(CanType type) {
return IGF.tryGetLocalTypeDataForLayout(
SILType::getPrimitiveObjectType(type),
- LocalTypeData::forMetatype());
+ LocalTypeDataKind::forMetatype());
}
/// Set the metatype in local data.
llvm::Value *setLocal(CanType type, llvm::Instruction *metatype) {
IGF.setScopedLocalTypeDataForLayout(SILType::getPrimitiveObjectType(type),
- LocalTypeData::forMetatype(),
+ LocalTypeDataKind::forMetatype(),
metatype);
return metatype;
}
@@ -2720,7 +2720,7 @@
value = emitWitnessTableRef(IGF, fillOp.Archetype, fillOp.Protocol);
} else {
value = IGF.getLocalTypeData(fillOp.Archetype,
- LocalTypeData::forMetatype());
+ LocalTypeDataKind::forMetatype());
}
value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
auto dest = createPointerSizedGEP(IGF, metadataWords,
@@ -3681,13 +3681,14 @@
IRGenFunction::emitValueWitnessTableRef(CanType type) {
// See if we have a cached projection we can use.
if (auto cached = tryGetLocalTypeData(type,
- LocalTypeData::forValueWitnessTable())) {
+ LocalTypeDataKind::forValueWitnessTable())) {
return cached;
}
auto metadata = emitTypeMetadataRef(type);
auto vwtable = emitValueWitnessTableRefForMetadata(metadata);
- setScopedLocalTypeData(type, LocalTypeData::forValueWitnessTable(), vwtable);
+ setScopedLocalTypeData(type, LocalTypeDataKind::forValueWitnessTable(),
+ vwtable);
return vwtable;
}
@@ -3715,14 +3716,14 @@
IRGenFunction::emitValueWitnessTableRefForLayout(SILType type) {
// See if we have a cached projection we can use.
if (auto cached = tryGetLocalTypeDataForLayout(type,
- LocalTypeData::forValueWitnessTable())) {
+ LocalTypeDataKind::forValueWitnessTable())) {
return cached;
}
auto metadata = emitTypeMetadataRefForLayout(type);
auto vwtable = emitValueWitnessTableRefForMetadata(metadata);
setScopedLocalTypeDataForLayout(type,
- LocalTypeData::forValueWitnessTable(),
+ LocalTypeDataKind::forValueWitnessTable(),
vwtable);
return vwtable;
}
diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp
index 94c49cf..d39498f 100644
--- a/lib/IRGen/GenOpaque.cpp
+++ b/lib/IRGen/GenOpaque.cpp
@@ -320,25 +320,26 @@
llvm::Value *IRGenFunction::emitValueWitness(CanType type, ValueWitness index) {
if (auto witness =
- tryGetLocalTypeData(type, LocalTypeData::forValueWitness(index)))
+ tryGetLocalTypeData(type, LocalTypeDataKind::forValueWitness(index)))
return witness;
auto vwtable = emitValueWitnessTableRef(type);
auto witness = emitLoadOfValueWitness(*this, vwtable, index);
- setScopedLocalTypeData(type, LocalTypeData::forValueWitness(index), witness);
+ setScopedLocalTypeData(type, LocalTypeDataKind::forValueWitness(index),
+ witness);
return witness;
}
llvm::Value *IRGenFunction::emitValueWitnessForLayout(SILType type,
ValueWitness index) {
if (auto witness = tryGetLocalTypeDataForLayout(type,
- LocalTypeData::forValueWitness(index)))
+ LocalTypeDataKind::forValueWitness(index)))
return witness;
auto vwtable = emitValueWitnessTableRefForLayout(type);
auto witness = emitLoadOfValueWitness(*this, vwtable, index);
setScopedLocalTypeDataForLayout(type,
- LocalTypeData::forValueWitness(index), witness);
+ LocalTypeDataKind::forValueWitness(index), witness);
return witness;
}
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 207a382..d7a7f12 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -559,14 +559,18 @@
IGF.Builder.CreateCondBr(isInline, directBB, indirectBB);
// Emit the indirect path.
- IGF.Builder.emitBlock(indirectBB);
- operation.emitForPacking(IGF, T, type, FixedPacking::Allocate);
- IGF.Builder.CreateBr(contBB);
+ IGF.Builder.emitBlock(indirectBB); {
+ ConditionalDominanceScope condition(IGF);
+ operation.emitForPacking(IGF, T, type, FixedPacking::Allocate);
+ IGF.Builder.CreateBr(contBB);
+ }
// Emit the direct path.
- IGF.Builder.emitBlock(directBB);
- operation.emitForPacking(IGF, T, type, FixedPacking::OffsetZero);
- IGF.Builder.CreateBr(contBB);
+ IGF.Builder.emitBlock(directBB); {
+ ConditionalDominanceScope condition(IGF);
+ operation.emitForPacking(IGF, T, type, FixedPacking::OffsetZero);
+ IGF.Builder.CreateBr(contBB);
+ }
// Enter the continuation block and add the PHI if required.
IGF.Builder.emitBlock(contBB);
@@ -973,6 +977,7 @@
IGF.Builder.CreateCondBr(done, exit, loop);
IGF.Builder.emitBlock(loop);
+ ConditionalDominanceScope condition(IGF);
type.destroy(IGF, element, concreteType);
auto nextCounter = IGF.Builder.CreateSub(counter,
llvm::ConstantInt::get(IGM.SizeTy, 1));
@@ -2956,7 +2961,7 @@
// Mark this as the cached metatype for the l-value's object type.
CanType argTy = getArgTypeInContext(source.getParamIndex());
- IGF.setUnscopedLocalTypeData(argTy, LocalTypeData::forMetatype(),
+ IGF.setUnscopedLocalTypeData(argTy, LocalTypeDataKind::forMetatype(),
metatype);
return metatype;
}
@@ -2969,7 +2974,7 @@
// Mark this as the cached metatype for Self.
CanType argTy = getArgTypeInContext(FnType->getParameters().size() - 1);
IGF.setUnscopedLocalTypeData(argTy,
- LocalTypeData::forMetatype(), metatype);
+ LocalTypeDataKind::forMetatype(), metatype);
return metatype;
}
@@ -3260,7 +3265,7 @@
EmitPolymorphicParameters(IGF, ntd).emitForGenericValueWitness(selfMeta);
// Register the 'Self' argument as generic metadata for the type.
IGF.setUnscopedLocalTypeData(ntd->getDeclaredTypeInContext()->getCanonicalType(),
- LocalTypeData::forMetatype(), selfMeta);
+ LocalTypeDataKind::forMetatype(), selfMeta);
}
/// Get the next argument and use it as the 'self' type metadata.
@@ -3442,14 +3447,13 @@
// Find the metatype for the appropriate archetype and store it in
// the slot.
- llvm::Value *metatype =
- IGF.getLocalTypeData(CanType(archetype), LocalTypeData::forMetatype());
+ llvm::Value *metatype = IGF.getLocalTypeData(CanType(archetype),
+ LocalTypeDataKind::forMetatype());
IGF.Builder.CreateStore(metatype, slot);
// Find the witness tables for the archetype's protocol constraints and
// store them in the slot.
- for (unsigned protocolI : indices(archetype->getConformsTo())) {
- auto protocol = archetype->getConformsTo()[protocolI];
+ for (auto protocol : archetype->getConformsTo()) {
if (!Lowering::TypeConverter::protocolRequiresWitnessTable(protocol))
continue;
Address witnessSlot = IGF.Builder.CreateConstArrayGEP(buffer, metadataI,
@@ -3459,7 +3463,7 @@
++metadataI;
llvm::Value *witness =
IGF.getLocalTypeData(CanType(archetype),
- LocalTypeData::forArchetypeProtocolWitness(protocolI));
+ LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol));
IGF.Builder.CreateStore(witness, witnessSlot);
}
}
diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp
index 53ac36e..b97086b 100644
--- a/lib/IRGen/GenType.cpp
+++ b/lib/IRGen/GenType.cpp
@@ -50,6 +50,24 @@
return t->hasTypeParameter() ? DependentCache : IndependentCache;
}
+void TypeInfo:: assign(IRGenFunction &IGF, Address dest, Address src,
+ IsTake_t isTake, SILType T) const {
+ if (isTake) {
+ assignWithTake(IGF, dest, src, T);
+ } else {
+ assignWithCopy(IGF, dest, src, T);
+ }
+}
+
+void TypeInfo::initialize(IRGenFunction &IGF, Address dest, Address src,
+ IsTake_t isTake, SILType T) const {
+ if (isTake) {
+ initializeWithTake(IGF, dest, src, T);
+ } else {
+ initializeWithCopy(IGF, dest, src, T);
+ }
+}
+
Address TypeInfo::initializeBufferWithTake(IRGenFunction &IGF,
Address destBuffer,
Address srcAddr,
@@ -152,12 +170,14 @@
auto elementVal = IGF.Builder.CreatePHI(array.getType(), 2);
elementVal->addIncoming(array.getAddress(), entry);
Address element(elementVal, array.getAlignment());
-
+
auto done = IGF.Builder.CreateICmpEQ(counter,
llvm::ConstantInt::get(IGF.IGM.SizeTy, 0));
IGF.Builder.CreateCondBr(done, exit, loop);
IGF.Builder.emitBlock(loop);
+ ConditionalDominanceScope condition(IGF);
+
destroy(IGF, element, T);
auto nextCounter = IGF.Builder.CreateSub(counter,
llvm::ConstantInt::get(IGF.IGM.SizeTy, 1));
@@ -196,16 +216,14 @@
srcVal->addIncoming(srcArray.getAddress(), entry);
Address dest(destVal, destArray.getAlignment());
Address src(srcVal, srcArray.getAlignment());
-
+
auto done = IGF.Builder.CreateICmpEQ(counter,
llvm::ConstantInt::get(IGM.SizeTy, 0));
IGF.Builder.CreateCondBr(done, exit, loop);
IGF.Builder.emitBlock(loop);
- if (take)
- type.initializeWithTake(IGF, dest, src, T);
- else
- type.initializeWithCopy(IGF, dest, src, T);
+ ConditionalDominanceScope condition(IGF);
+ type.initialize(IGF, dest, src, take, T);
auto nextCounter = IGF.Builder.CreateSub(counter,
llvm::ConstantInt::get(IGM.SizeTy, 1));
@@ -250,21 +268,19 @@
srcVal->addIncoming(srcEnd.getAddress(), entry);
Address dest(destVal, destArray.getAlignment());
Address src(srcVal, srcArray.getAlignment());
-
+
auto done = IGF.Builder.CreateICmpEQ(counter,
llvm::ConstantInt::get(IGM.SizeTy, 0));
IGF.Builder.CreateCondBr(done, exit, loop);
IGF.Builder.emitBlock(loop);
+ ConditionalDominanceScope condition(IGF);
auto prevDest = type.indexArray(IGF, dest,
llvm::ConstantInt::getSigned(IGM.SizeTy, -1), T);
auto prevSrc = type.indexArray(IGF, src,
llvm::ConstantInt::getSigned(IGM.SizeTy, -1), T);
- if (take)
- type.initializeWithTake(IGF, prevDest, prevSrc, T);
- else
- type.initializeWithCopy(IGF, prevDest, prevSrc, T);
+ type.initialize(IGF, prevDest, prevSrc, take, T);
auto nextCounter = IGF.Builder.CreateSub(counter,
llvm::ConstantInt::get(IGM.SizeTy, 1));
@@ -536,6 +552,7 @@
IGF.Builder.CreateCondBr(isValid, endBB, spareBB);
IGF.Builder.emitBlock(spareBB);
+ ConditionalDominanceScope condition(IGF);
// Gather the occupied bits.
auto OccupiedBits = SpareBits;
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index faddcf5..f041be7 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -1,4 +1,4 @@
-//===--- IRGenDebugInfo.cpp - Debug Info Support---------------------------===//
+//===--- IRGenDebugInfo.cpp - Debug Info Support --------------------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/IRGen/IRGenDebugInfo.h b/lib/IRGen/IRGenDebugInfo.h
index 0324eb0..177b85a 100644
--- a/lib/IRGen/IRGenDebugInfo.h
+++ b/lib/IRGen/IRGenDebugInfo.h
@@ -1,4 +1,4 @@
-//===--- IRGenDebugInfo.h - Debug Info Support-------------------*- C++ -*-===//
+//===--- IRGenDebugInfo.h - Debug Info Support ------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index d96f7f0..d919764 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -52,8 +52,12 @@
IRGenFunction::~IRGenFunction() {
emitEpilogue();
+
// Restore the debug location.
if (IGM.DebugInfo) IGM.DebugInfo->popLoc();
+
+ // Tear down any side-table data structures.
+ if (LocalTypeData) destroyLocalTypeData();
}
/// Call the llvm.memcpy intrinsic. The arguments need not already
@@ -212,40 +216,6 @@
}
}
-llvm::Value *IRGenFunction::lookupTypeDataMap(CanType type, LocalTypeData index,
- const TypeDataMap &scopedMap) {
-
- // First try to lookup in the unscoped cache (= definitions in the entry block
- // of the function).
- auto key = getLocalTypeDataKey(type, index);
- auto it = LocalTypeDataMap.find(key);
- if (it != LocalTypeDataMap.end())
- return it->second;
-
- // Now try to lookup in the scoped cache.
- auto it2 = scopedMap.find(key);
- if (it2 == scopedMap.end())
- return nullptr;
-
- if (auto *I = dyn_cast<llvm::Instruction>(it2->second)) {
- // This is a very very simple dominance check: either the definition is in the
- // entry block or in the current block.
- // TODO: do a better dominance check.
- if (I->getParent() == &CurFn->getEntryBlock() ||
- I->getParent() == Builder.GetInsertBlock()) {
- return I;
- }
- return nullptr;
- }
-
- if (isa<llvm::Constant>(it2->second)) {
- return it2->second;
- }
-
- // TODO: other kinds of value?
- return nullptr;
-}
-
void IRGenFunction::unimplemented(SourceLoc Loc, StringRef Message) {
return IGM.unimplemented(Loc, Message);
}
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index 5fe1903..5ba09d5 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -25,7 +25,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/CallingConv.h"
#include "IRBuilder.h"
-
+#include "LocalTypeDataKind.h"
+#include "DominancePoint.h"
namespace llvm {
class AllocaInst;
@@ -60,53 +61,12 @@
class HeapNonFixedOffsets;
class IRGenModule;
class LinkEntity;
+ class LocalTypeDataCache;
class Scope;
class TypeInfo;
enum class ValueWitness : unsigned;
enum class ReferenceCounting : unsigned char;
-/// A nonce value for storing some sort of locally-known information about a type.
-class LocalTypeData {
- unsigned Value;
-
- explicit LocalTypeData(unsigned Value) : Value(Value) {}
-
- /// Magic values for special kinds of index.
- enum : unsigned {
- Metatype = ~0U,
- ValueWitnessTable = ~1U,
-
- ValueWitnessBase = 0xFFFFFF00U,
- };
-
-public:
- LocalTypeData() = default;
-
- // The magic values are all in the "negative" range and so do
- // not collide with reasonable index values.
-
- /// A reference to the type metadata.
- static LocalTypeData forMetatype() { return LocalTypeData(Metatype); }
- /// A reference to the value witness table.
- static LocalTypeData forValueWitnessTable() {
- return LocalTypeData(ValueWitnessTable);
- }
-
- /// A reference to a specific value witness.
- static LocalTypeData forValueWitness(ValueWitness witness) {
- return LocalTypeData((unsigned)witness + ValueWitnessBase);
- }
-
- /// A reference to a protocol witness table for an archetype.
- static LocalTypeData forArchetypeProtocolWitness(unsigned index) {
- return LocalTypeData(index);
- }
-
- unsigned getValue() const {
- return Value;
- }
-};
-
/// IRGenFunction - Primary class for emitting LLVM instructions for a
/// specific function.
class IRGenFunction {
@@ -404,54 +364,127 @@
/// Look for a mapping for a local type-metadata reference.
/// The lookup is done for the current block which is the Builder's
/// insert-block.
- llvm::Value *tryGetLocalTypeData(CanType type, LocalTypeData index) {
- return lookupTypeDataMap(type, index, ScopedTypeDataMap);
- }
-
- /// The same as tryGetLocalTypeData, just for the Layout metadata.
- llvm::Value *tryGetLocalTypeDataForLayout(SILType type, LocalTypeData index) {
- return lookupTypeDataMap(type.getSwiftRValueType(), index,
- ScopedTypeDataMapForLayout);
- }
+ llvm::Value *tryGetLocalTypeData(CanType type, LocalTypeDataKind kind);
/// Retrieve a local type-metadata reference which is known to exist.
- llvm::Value *getLocalTypeData(CanType type, LocalTypeData index) {
- auto key = getLocalTypeDataKey(type, index);
- assert(LocalTypeDataMap.count(key) && "no mapping for local type data");
- return LocalTypeDataMap.find(key)->second;
- }
+ llvm::Value *getLocalTypeData(CanType type, LocalTypeDataKind kind);
- /// Add a local type-metadata reference at a point which dominates
- /// the entire function.
- void setUnscopedLocalTypeData(CanType type, LocalTypeData index,
- llvm::Value *data) {
- assert(data && "setting a null value for type data!");
-
- auto key = getLocalTypeDataKey(type, index);
- assert(!LocalTypeDataMap.count(key) &&
- "existing mapping for local type data");
- LocalTypeDataMap.insert({key, data});
- }
+ /// Add a local type-metadata reference at a point which definitely
+ /// dominates all of its uses.
+ void setUnscopedLocalTypeData(CanType type, LocalTypeDataKind kind,
+ llvm::Value *data);
- /// Add a local type-metadata reference, which is valid for the containing
- /// block.
- void setScopedLocalTypeData(CanType type, LocalTypeData index,
- llvm::Value *data) {
- assert(_isValidScopedLocalTypeData(data) &&
- "metadata instruction not inserted into the Builder's insert-block");
- ScopedTypeDataMap[getLocalTypeDataKey(type, index)] = data;
+ /// Add a local type-metadata reference, valid at the current insertion
+ /// point.
+ void setScopedLocalTypeData(CanType type, LocalTypeDataKind kind,
+ llvm::Value *data);
+
+ /// The same as tryGetLocalTypeData, just for the Layout metadata.
+ ///
+ /// We use a separate function name for this to clarify that you should
+ /// only ever be looking type metadata for a lowered SILType for the
+ /// purposes of local layout (e.g. of a tuple).
+ llvm::Value *tryGetLocalTypeDataForLayout(SILType type,
+ LocalTypeDataKind kind) {
+ return tryGetLocalTypeData(type.getSwiftRValueType(), kind);
}
/// Add a local type-metadata reference, which is valid for the containing
/// block.
- void setScopedLocalTypeDataForLayout(SILType type, LocalTypeData index,
+ void setScopedLocalTypeDataForLayout(SILType type, LocalTypeDataKind kind,
llvm::Value *data) {
- assert(_isValidScopedLocalTypeData(data) &&
- "metadata instruction not inserted into the Builder's insert-block");
- ScopedTypeDataMapForLayout[
- getLocalTypeDataKey(type.getSwiftRValueType(), index)] = data;
+ setScopedLocalTypeData(type.getSwiftRValueType(), kind, data);
}
+ void setDominanceResolver(DominanceResolverFunction resolver) {
+ assert(DominanceResolver == nullptr);
+ DominanceResolver = resolver;
+ }
+
+ bool isActiveDominancePointDominatedBy(DominancePoint point) {
+ // If the point is universal, it dominates.
+ if (point.isUniversal()) return true;
+
+ assert(!ActiveDominancePoint.isUniversal() &&
+ "active dominance point is universal but there exists a"
+ "non-universal point?");
+
+ // If we don't have a resolver, we're emitting a simple helper
+ // function; just assume dominance.
+ if (!DominanceResolver) return true;
+
+ // Otherwise, ask the resolver.
+ return DominanceResolver(*this, ActiveDominancePoint, point);
+ }
+
+ /// Is the current dominance point conditional in some way not
+ /// tracked by the active dominance point?
+ ///
+ /// This should only be used by the local type data cache code.
+ bool isConditionalDominancePoint() const {
+ return ConditionalDominance != nullptr;
+ }
+
+ void registerConditionalLocalTypeDataKey(LocalTypeDataKey key) {
+ assert(ConditionalDominance != nullptr &&
+ "not in a conditional dominance scope");
+ ConditionalDominance->registerConditionalLocalTypeDataKey(key);
+ }
+
+ /// Return the currently-active dominance point.
+ DominancePoint getActiveDominancePoint() const {
+ return ActiveDominancePoint;
+ }
+
+ /// A RAII object for temporarily changing the dominance of the active
+ /// definition point.
+ class DominanceScope {
+ IRGenFunction &IGF;
+ DominancePoint OldDominancePoint;
+ public:
+ explicit DominanceScope(IRGenFunction &IGF, DominancePoint newPoint)
+ : IGF(IGF), OldDominancePoint(IGF.ActiveDominancePoint) {
+ IGF.ActiveDominancePoint = newPoint;
+ assert(!newPoint.isOrdinary() || IGF.DominanceResolver);
+ }
+
+ DominanceScope(const DominanceScope &other) = delete;
+ DominanceScope &operator=(const DominanceScope &other) = delete;
+
+ ~DominanceScope() {
+ IGF.ActiveDominancePoint = OldDominancePoint;
+ }
+ };
+
+ /// A RAII object for temporarily suppressing type-data caching at the
+ /// active definition point. Do this if you're adding local control flow
+ /// that isn't modeled by the dominance system.
+ class ConditionalDominanceScope {
+ IRGenFunction &IGF;
+ ConditionalDominanceScope *OldScope;
+ SmallVector<LocalTypeDataKey, 2> RegisteredKeys;
+ public:
+ explicit ConditionalDominanceScope(IRGenFunction &IGF)
+ : IGF(IGF), OldScope(IGF.ConditionalDominance) {
+ IGF.ConditionalDominance = this;
+ }
+
+ ConditionalDominanceScope(const ConditionalDominanceScope &other) = delete;
+ ConditionalDominanceScope &operator=(const ConditionalDominanceScope &other)
+ = delete;
+
+ void registerConditionalLocalTypeDataKey(LocalTypeDataKey key) {
+ RegisteredKeys.push_back(key);
+ }
+
+ ~ConditionalDominanceScope() {
+ IGF.ConditionalDominance = OldScope;
+ if (!RegisteredKeys.empty()) {
+ IGF.unregisterConditionalLocalTypeDataKeys(RegisteredKeys);
+ }
+ }
+ };
+
/// The kind of value LocalSelf is.
enum LocalSelfKind {
/// An object reference.
@@ -466,35 +499,17 @@
void setLocalSelfMetadata(llvm::Value *value, LocalSelfKind kind);
private:
-#ifndef NDEBUG
- bool _isValidScopedLocalTypeData(llvm::Value *v) {
- // Constants are valid anywhere.
- if (isa<llvm::Constant>(v))
- return true;
- // Instructions are valid only in the current insert block.
- if (auto inst = dyn_cast<llvm::Instruction>(v))
- return inst->getParent() == Builder.GetInsertBlock();
- // TODO: Other kinds of value?
- return false;
- }
-#endif
+ LocalTypeDataCache &getOrCreateLocalTypeData();
+ void destroyLocalTypeData();
+ void unregisterConditionalLocalTypeDataKeys(ArrayRef<LocalTypeDataKey> keys);
- typedef unsigned LocalTypeDataDepth;
- typedef std::pair<TypeBase*,unsigned> LocalTypeDataPair;
- LocalTypeDataPair getLocalTypeDataKey(CanType type, LocalTypeData index) {
- return LocalTypeDataPair(type.getPointer(), index.getValue());
- }
+ LocalTypeDataCache *LocalTypeData = nullptr;
- typedef llvm::DenseMap<LocalTypeDataPair, llvm::Value*> TypeDataMap;
-
- llvm::Value *lookupTypeDataMap(CanType type, LocalTypeData index,
- const TypeDataMap &scopedMap);
-
- TypeDataMap LocalTypeDataMap;
-
- TypeDataMap ScopedTypeDataMap;
-
- TypeDataMap ScopedTypeDataMapForLayout;
+ /// The dominance resolver. This can be set at most once; when it's not
+ /// set, this emission must never have a non-null active definition point.
+ DominanceResolverFunction DominanceResolver = nullptr;
+ DominancePoint ActiveDominancePoint = DominancePoint::universal();
+ ConditionalDominanceScope *ConditionalDominance = nullptr;
/// The value that satisfies metadata lookups for dynamic Self.
llvm::Value *LocalSelf = nullptr;
@@ -502,6 +517,8 @@
LocalSelfKind SelfKind;
};
+using ConditionalDominanceScope = IRGenFunction::ConditionalDominanceScope;
+
} // end namespace irgen
} // end namespace swift
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index e00a8b7..df74ad8 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -33,6 +33,7 @@
#include "swift/AST/Pattern.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Types.h"
+#include "swift/SIL/Dominance.h"
#include "swift/SIL/PrettyStackTrace.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILDeclRef.h"
@@ -312,6 +313,9 @@
SILFunction *CurSILFn;
Address IndirectReturn;
+
+ // A cached dominance analysis.
+ std::unique_ptr<DominanceInfo> Dominance;
IRGenSILFunction(IRGenModule &IGM, SILFunction *f);
~IRGenSILFunction();
@@ -1286,6 +1290,20 @@
CurSILFn->print(llvm::dbgs()));
assert(!CurSILFn->empty() && "function has no basic blocks?!");
+
+ // Configure the dominance resolver.
+ // TODO: consider re-using a dom analysis from the PassManager
+ // TODO: consider using a cheaper analysis at -O0
+ setDominanceResolver([](IRGenFunction &IGF_,
+ DominancePoint activePoint,
+ DominancePoint dominatingPoint) -> bool {
+ IRGenSILFunction &IGF = static_cast<IRGenSILFunction&>(IGF_);
+ if (!IGF.Dominance) {
+ IGF.Dominance.reset(new DominanceInfo(IGF.CurSILFn));
+ }
+ return IGF.Dominance->dominates(dominatingPoint.as<SILBasicBlock>(),
+ activePoint.as<SILBasicBlock>());
+ });
// FIXME: Or if this is a witness. DebugInfo doesn't have an interface to
// correctly handle the generic parameters of a witness, which can come from
@@ -1324,7 +1342,7 @@
break;
}
emitLocalSelfMetadata(*this);
-
+
assert(params.empty() && "did not map all llvm params to SIL params?!");
// It's really nice to be able to assume that we've already emitted
@@ -1454,6 +1472,11 @@
bool InEntryBlock = BB->pred_empty();
bool ArgsEmitted = false;
+ // Set this block as the dominance point. This implicitly communicates
+ // with the dominance resolver configured in emitSILFunction.
+ DominanceScope dominance(*this, InEntryBlock ? DominancePoint::universal()
+ : DominancePoint(BB));
+
// The basic blocks are visited in a random order. Reset the debug location.
std::unique_ptr<AutoRestoreLocation> ScopedLoc;
if (InEntryBlock)
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
new file mode 100644
index 0000000..f7ccd69
--- /dev/null
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -0,0 +1,303 @@
+//===--- LocalTypeData.cpp - Local type data search -----------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements routines for finding and caching local type data
+// for a search.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LocalTypeData.h"
+#include "Fulfillment.h"
+#include "IRGenFunction.h"
+#include "IRGenModule.h"
+#include "swift/SIL/SILModule.h"
+
+using namespace swift;
+using namespace irgen;
+
+LocalTypeDataCache &IRGenFunction::getOrCreateLocalTypeData() {
+ // Lazily allocate it.
+ if (LocalTypeData) return *LocalTypeData;
+ LocalTypeData = new LocalTypeDataCache();
+ return *LocalTypeData;
+}
+
+void IRGenFunction::destroyLocalTypeData() {
+ delete LocalTypeData;
+}
+
+unsigned LocalTypeDataCache::CacheEntry::cost() const {
+ switch (getKind()) {
+ case Kind::Concrete:
+ return static_cast<const ConcreteCacheEntry*>(this)->cost();
+ case Kind::Abstract:
+ return static_cast<const AbstractCacheEntry*>(this)->cost();
+ }
+ llvm_unreachable("bad cache entry kind");
+}
+
+void LocalTypeDataCache::CacheEntry::erase() const {
+ switch (getKind()) {
+ case Kind::Concrete:
+ delete static_cast<const ConcreteCacheEntry*>(this);
+ return;
+ case Kind::Abstract:
+ delete static_cast<const AbstractCacheEntry*>(this);
+ return;
+ }
+ llvm_unreachable("bad cache entry kind");
+}
+
+llvm::Value *IRGenFunction::getLocalTypeData(CanType type,
+ LocalTypeDataKind kind) {
+ assert(LocalTypeData);
+ return LocalTypeData->get(*this, LocalTypeDataCache::getKey(type, kind));
+}
+
+llvm::Value *IRGenFunction::tryGetLocalTypeData(CanType type,
+ LocalTypeDataKind kind) {
+ if (!LocalTypeData) return nullptr;
+ return LocalTypeData->tryGet(*this, LocalTypeDataCache::getKey(type, kind));
+}
+
+llvm::Value *LocalTypeDataCache::tryGet(IRGenFunction &IGF, Key key) {
+ auto it = Map.find(key);
+ if (it == Map.end()) return nullptr;
+ auto &chain = it->second;
+
+ CacheEntry *best = nullptr, *bestPrev = nullptr;
+ Optional<unsigned> bestCost;
+
+ CacheEntry *next = chain.Root, *nextPrev = nullptr;
+ do {
+ assert(next);
+ CacheEntry *cur = next, *curPrev = nextPrev;
+ nextPrev = cur;
+ next = cur->getNext();
+
+ // Ignore unacceptable entries.
+ if (!IGF.isActiveDominancePointDominatedBy(cur->DefinitionPoint))
+ continue;
+
+ // If there's a collision, compare by cost, ignoring higher-cost entries.
+ if (best) {
+ // Compute the cost of the best entry if we haven't done so already.
+ // If that's zero, go ahead and short-circuit out.
+ if (!bestCost) {
+ bestCost = best->cost();
+ if (*bestCost == 0) break;
+ }
+
+ auto curCost = cur->cost();
+ if (curCost >= *bestCost) continue;
+
+ // Replace the best cost and fall through.
+ bestCost = curCost;
+ }
+ best = cur;
+ bestPrev = curPrev;
+ } while (next);
+
+ // If we didn't find anything, we're done.
+ if (!best) return nullptr;
+
+ // Okay, we've found the best entry available.
+ switch (best->getKind()) {
+
+ // For concrete caches, this is easy.
+ case CacheEntry::Kind::Concrete:
+ return static_cast<ConcreteCacheEntry*>(best)->Value;
+
+ // For abstract caches, we need to follow a path.
+ case CacheEntry::Kind::Abstract: {
+ auto entry = static_cast<AbstractCacheEntry*>(best);
+
+ // Follow the path.
+ auto &source = AbstractSources[entry->SourceIndex];
+ auto result = entry->follow(IGF, source);
+
+ // Make a new concrete entry at the active definition point.
+ auto newEntry =
+ new ConcreteCacheEntry(IGF.getActiveDominancePoint(),
+ IGF.isConditionalDominancePoint(), result);
+
+ // If the active definition point is the same as the old entry's
+ // definition point, delete the old entry.
+ if (best->DefinitionPoint == IGF.getActiveDominancePoint() &&
+ !best->isConditional()) {
+ chain.eraseEntry(bestPrev, best);
+ }
+
+ // Add the new entry to the front of the chain.
+ chain.push_front(newEntry);
+
+ return result;
+ }
+
+ }
+ llvm_unreachable("bad cache entry kind");
+}
+
+llvm::Value *
+LocalTypeDataCache::AbstractCacheEntry::follow(IRGenFunction &IGF,
+ AbstractSource &source) const {
+ switch (source.getKind()) {
+ case AbstractSource::Kind::TypeMetadata:
+ return Path.followFromTypeMetadata(IGF, source.getType(),
+ source.getValue(), &source.getCache());
+
+ case AbstractSource::Kind::WitnessTable:
+ return Path.followFromWitnessTable(IGF, source.getProtocol(),
+ source.getValue(), &source.getCache());
+ }
+ llvm_unreachable("bad source kind");
+}
+
+void IRGenFunction::setScopedLocalTypeData(CanType type, LocalTypeDataKind kind,
+ llvm::Value *data) {
+ if (isConditionalDominancePoint())
+ return;
+
+ getOrCreateLocalTypeData().addConcrete(getActiveDominancePoint(),
+ isConditionalDominancePoint(),
+ LocalTypeDataCache::getKey(type, kind),
+ data);
+}
+
+void IRGenFunction::setUnscopedLocalTypeData(CanType type,
+ LocalTypeDataKind kind,
+ llvm::Value *data) {
+ getOrCreateLocalTypeData()
+ .addConcrete(DominancePoint::universal(), /*conditional*/ false,
+ LocalTypeDataCache::getKey(type, kind), data);
+}
+
+void LocalTypeDataCache::addAbstractForTypeMetadata(IRGenFunction &IGF,
+ CanType type,
+ llvm::Value *metadata) {
+ // Don't bother doing this at a conditional dominance point; we're too
+ // likely to throw it all away.
+ if (IGF.isConditionalDominancePoint())
+ return;
+
+ // Look for anything at all that's fulfilled by this. If we don't find
+ // anything, stop.
+ FulfillmentMap fulfillments;
+ if (!fulfillments.searchTypeMetadata(*IGF.IGM.SILMod->getSwiftModule(),
+ type, FulfillmentMap::IsExact,
+ /*source*/ 0, MetadataPath(),
+ FulfillmentMap::Everything())) {
+ return;
+ }
+
+ addAbstractForFullfillments(IGF, std::move(fulfillments),
+ [&]() -> AbstractSource {
+ return AbstractSource(AbstractSource::Kind::TypeMetadata, type, metadata);
+ });
+}
+
+void LocalTypeDataCache::
+addAbstractForFullfillments(IRGenFunction &IGF, FulfillmentMap &&fulfillments,
+ llvm::function_ref<AbstractSource()> createSource) {
+ // Add the source lazily.
+ Optional<unsigned> sourceIndex;
+ auto getSourceIndex = [&]() -> unsigned {
+ if (!sourceIndex) {
+ AbstractSources.emplace_back(createSource());
+ sourceIndex = AbstractSources.size() - 1;
+ }
+ return *sourceIndex;
+ };
+
+ for (auto &fulfillment : fulfillments) {
+ CanType type = CanType(fulfillment.first.first);
+ LocalTypeDataKind localDataKind;
+
+ // For now, ignore witness-table fulfillments when they're not for
+ // archetypes.
+ if (ProtocolDecl *protocol = fulfillment.first.second) {
+ if (auto archetype = dyn_cast<ArchetypeType>(type)) {
+ auto conformsTo = archetype->getConformsTo();
+ auto it = std::find(conformsTo.begin(), conformsTo.end(), protocol);
+ if (it == conformsTo.end()) continue;
+ localDataKind =LocalTypeDataKind::forArchetypeProtocolWitnessTable(*it);
+ } else {
+ continue;
+ }
+ } else {
+ localDataKind = LocalTypeDataKind::forMetatype();
+ }
+
+ // Find the chain for the key.
+ auto key = getKey(type, localDataKind);
+ auto &chain = Map[key];
+
+ // Check whether there's already an entr that's at least as good as the
+ // fulfillment.
+ Optional<unsigned> fulfillmentCost;
+ auto getFulfillmentCost = [&]() -> unsigned {
+ if (!fulfillmentCost)
+ fulfillmentCost = fulfillment.second.Path.cost();
+ return *fulfillmentCost;
+ };
+
+ bool foundBetter = false;
+ for (CacheEntry *cur = chain.Root, *last = nullptr; cur;
+ last = cur, cur = cur->getNext()) {
+ // Ensure the entry is acceptable.
+ if (!IGF.isActiveDominancePointDominatedBy(cur->DefinitionPoint))
+ continue;
+
+ // Ensure that the entry isn't better than the fulfillment.
+ auto curCost = cur->cost();
+ if (curCost == 0 || curCost <= getFulfillmentCost()) {
+ foundBetter = true;
+ break;
+ }
+
+ // If the entry is defined at the current point, (1) we know there
+ // won't be a better entry and (2) we should remove it.
+ if (cur->DefinitionPoint == IGF.getActiveDominancePoint() &&
+ !cur->isConditional()) {
+ // Splice it out of the chain.
+ chain.eraseEntry(last, cur);
+ break;
+ }
+ }
+ if (foundBetter) continue;
+
+ // Okay, make a new entry.
+ auto newEntry = new AbstractCacheEntry(IGF.getActiveDominancePoint(),
+ IGF.isConditionalDominancePoint(),
+ getSourceIndex(),
+ std::move(fulfillment.second.Path));
+
+ // Add it to the front of the chain.
+ chain.push_front(newEntry);
+ }
+}
+
+void IRGenFunction::unregisterConditionalLocalTypeDataKeys(
+ ArrayRef<LocalTypeDataKey> keys) {
+ assert(!keys.empty());
+ assert(LocalTypeData);
+ LocalTypeData->eraseConditional(keys);
+}
+
+void LocalTypeDataCache::eraseConditional(ArrayRef<LocalTypeDataKey> keys) {
+ for (auto &key : keys) {
+ auto &chain = Map[key];
+ assert(chain.Root);
+ assert(chain.Root->isConditional());
+ chain.eraseEntry(nullptr, chain.Root);
+ }
+}
diff --git a/lib/IRGen/LocalTypeData.h b/lib/IRGen/LocalTypeData.h
new file mode 100644
index 0000000..9c478b9
--- /dev/null
+++ b/lib/IRGen/LocalTypeData.h
@@ -0,0 +1,264 @@
+//===--- LocalTypeData.h - Dominance-scoped type data -------------*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines types relating to the local caching of type data,
+// such as type metadata, value witness tables, and protocol witness tables.
+//
+// Type data may be cached concretely, meaning that it was already fully
+// computed, or abstractly, meaning that we remember how to recreate it
+// but haven't actually done so yet.
+//
+// Type data may be cached at different points within a function.
+// Some of these points may not dominate all possible use sites.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_LOCALTYPEDATA_H
+#define SWIFT_IRGEN_LOCALTYPEDATA_H
+
+#include "LocalTypeDataKind.h"
+#include "DominancePoint.h"
+#include "MetadataPath.h"
+#include "swift/AST/Type.h"
+#include "llvm/ADT/STLExtras.h"
+#include <utility>
+
+namespace swift {
+ class TypeBase;
+
+namespace irgen {
+ class FulfillmentMap;
+
+/// A cache of local type data.
+///
+/// Basic design considerations:
+///
+/// - We want to be able to efficiently look up a key and find something.
+/// Generally this will find something from the entry block. We shouldn't
+/// have to scan all the dominating points first.
+///
+/// - We don't expect to have multiple definitions for a key very often.
+/// Therefore, given a collision, it should be okay to scan a list and
+/// ask whether each is acceptable.
+class LocalTypeDataCache {
+public:
+ using Key = LocalTypeDataKey;
+
+ static Key getKey(CanType type, LocalTypeDataKind index) {
+ return { type, index };
+ }
+
+private:
+ struct CacheEntry {
+ enum class Kind {
+ Concrete, Abstract
+ };
+
+ DominancePoint DefinitionPoint;
+
+ private:
+ enum { KindMask = 0x1, ConditionalMask = 0x2 };
+ llvm::PointerIntPair<CacheEntry*, 2, unsigned> NextAndFlags;
+
+ public:
+ Kind getKind() const {
+ return Kind(NextAndFlags.getInt() & KindMask);
+ }
+ CacheEntry *getNext() const { return NextAndFlags.getPointer(); }
+ void setNext(CacheEntry *next) { NextAndFlags.setPointer(next); }
+
+ /// Return the abstract cost of evaluating this cache entry.
+ unsigned cost() const;
+
+ /// Destruct and deallocate this cache entry.
+ void erase() const;
+
+ bool isConditional() const {
+ return NextAndFlags.getInt() & ConditionalMask;
+ }
+
+ protected:
+ CacheEntry(Kind kind, DominancePoint point, bool isConditional)
+ : DefinitionPoint(point),
+ NextAndFlags(nullptr,
+ unsigned(kind) | (isConditional ? ConditionalMask : 0)) {
+ }
+ ~CacheEntry() = default;
+ };
+
+ /// A concrete entry in the cache, which directly stores the desired value.
+ struct ConcreteCacheEntry : CacheEntry {
+ llvm::Value *Value;
+
+ ConcreteCacheEntry(DominancePoint point, bool isConditional,
+ llvm::Value *value)
+ : CacheEntry(Kind::Concrete, point, isConditional), Value(value) {}
+
+ unsigned cost() const { return 0; }
+ };
+
+ /// A source of concrete data from which abstract cache entries can be
+ /// derived.
+ class AbstractSource {
+ public:
+ enum class Kind {
+ /// Type metadata. The payload is a CanType.
+ TypeMetadata,
+
+ /// A protocol witness table. The payload is a ProtocolDecl*.
+ WitnessTable,
+ };
+
+ private:
+ uintptr_t Payload;
+ MetadataPath::Map<llvm::Value*> Cache;
+ llvm::Value *Value;
+
+ enum : uintptr_t { KindMask = 0x3 };
+
+ explicit AbstractSource(Kind kind, void *ptr, llvm::Value *value)
+ : Payload(uintptr_t(ptr) | unsigned(kind)), Value(value) {}
+
+ public:
+ explicit AbstractSource(Kind kind, CanType type, llvm::Value *metadata)
+ : AbstractSource(kind, type.getPointer(), metadata) {}
+ explicit AbstractSource(Kind kind, ProtocolDecl *protocol,
+ llvm::Value *witnessTable)
+ : AbstractSource(kind, (void*) protocol, witnessTable) {}
+
+ Kind getKind() const {
+ return Kind(Payload & KindMask);
+ }
+
+ CanType getType() const {
+ assert(getKind() == Kind::TypeMetadata);
+ return CanType(reinterpret_cast<TypeBase*>(Payload & ~KindMask));
+ }
+ ProtocolDecl *getProtocol() const {
+ assert(getKind() == Kind::WitnessTable);
+ return reinterpret_cast<ProtocolDecl*>(Payload & ~KindMask);
+ }
+
+ llvm::Value *getValue() const {
+ return Value;
+ }
+
+ MetadataPath::Map<llvm::Value*> &getCache() {
+ return Cache;
+ }
+ };
+
+ /// An abstract entry in the cache, which requires some amount of
+ /// non-trivial evaluation to derive the desired value.
+ struct AbstractCacheEntry : CacheEntry {
+ unsigned SourceIndex;
+ MetadataPath Path;
+
+ AbstractCacheEntry(DominancePoint point, bool isConditional,
+ unsigned sourceIndex, MetadataPath &&path)
+ : CacheEntry(Kind::Abstract, point, isConditional),
+ SourceIndex(sourceIndex), Path(std::move(path)) {}
+
+ llvm::Value *follow(IRGenFunction &IGF, AbstractSource &source) const;
+
+ unsigned cost() const { return Path.cost(); }
+ };
+
+ /// The linked list of cache entries corresponding to a particular key.
+ struct CacheEntryChain {
+ CacheEntry *Root;
+
+ explicit CacheEntryChain(CacheEntry *root = nullptr) : Root(root) {}
+
+ CacheEntryChain(const CacheEntryChain &other) = delete;
+ CacheEntryChain &operator=(const CacheEntryChain &other) = delete;
+
+ CacheEntryChain(CacheEntryChain &&other) : Root(other.Root) {
+ other.Root = nullptr;
+ }
+ CacheEntryChain &operator=(CacheEntryChain &&other) {
+ Root = other.Root;
+ other.Root = nullptr;
+ return *this;
+ }
+
+ void push_front(CacheEntry *entry) {
+ entry->setNext(Root);
+ Root = entry;
+ }
+
+ void eraseEntry(CacheEntry *prev, CacheEntry *entry) {
+ if (prev) {
+ assert(prev->getNext() == entry);
+ prev->setNext(entry->getNext());
+ } else {
+ assert(Root == entry);
+ Root = entry->getNext();
+ }
+ entry->erase();
+ }
+
+ /// Delete the linked list.
+ ~CacheEntryChain() {
+ auto next = Root;
+ while (next) {
+ auto cur = next;
+ next = cur->getNext();
+ cur->erase();
+ }
+ }
+ };
+
+ llvm::DenseMap<Key, CacheEntryChain> Map;
+
+ std::vector<AbstractSource> AbstractSources;
+
+ void addAbstractForFullfillments(IRGenFunction &IGF,
+ FulfillmentMap &&fulfillments,
+ llvm::function_ref<AbstractSource()> createSource);
+
+
+public:
+ LocalTypeDataCache() = default;
+ LocalTypeDataCache(const LocalTypeDataCache &other) = delete;
+ LocalTypeDataCache &operator=(const LocalTypeDataCache &other) = delete;
+
+ /// Load the value from cache if possible. This may require emitting
+ /// code if the value is cached abstractly.
+ llvm::Value *tryGet(IRGenFunction &IGF, Key key);
+
+ /// Load the value from cache, asserting its presence.
+ llvm::Value *get(IRGenFunction &IGF, Key key) {
+ auto result = tryGet(IGF, key);
+ assert(result && "get() on unmapped entry?");
+ return result;
+ }
+
+ /// Add a new concrete entry to the cache at the given definition point.
+ void addConcrete(DominancePoint point, bool isConditional,
+ Key key, llvm::Value *value) {
+ auto newEntry = new ConcreteCacheEntry(point, isConditional, value);
+ Map[key].push_front(newEntry);
+ }
+
+ /// Add abstract entries based on what can be fulfilled from the given
+ /// type metadata.
+ void addAbstractForTypeMetadata(IRGenFunction &IGF, CanType type,
+ llvm::Value *metadata);
+
+ void eraseConditional(ArrayRef<LocalTypeDataKey> keys);
+};
+
+}
+}
+
+#endif
diff --git a/lib/IRGen/LocalTypeDataCache.h b/lib/IRGen/LocalTypeDataCache.h
new file mode 100644
index 0000000..f44b703
--- /dev/null
+++ b/lib/IRGen/LocalTypeDataCache.h
@@ -0,0 +1,141 @@
+//===--- LocalTypeDataCache.h - Dominance-scoped type data cache --*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LocalTypeDataCache type, which is used by
+// IRGenFunction to cache the information available for types in a local
+// context.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_LOCALTYPEDATACACHE_H
+#define SWIFT_IRGEN_LOCALTYPEDATACACHE_H
+
+#include "swift/AST/Type.h"
+#include <utility>
+
+namespace swift {
+class TypeBase;
+
+namespace irgen {
+enum class ValueWitness : unsigned;
+
+/// A nonce value for storing some sort of locally-known information
+/// about a type.
+class LocalTypeData {
+public:
+ using RawType = unsigned;
+private:
+ RawType Value;
+
+ explicit LocalTypeData(unsigned Value) : Value(Value) {}
+
+ /// Magic values for special kinds of index.
+ enum : RawType {
+ Metatype = ~0U,
+ ValueWitnessTable = ~1U,
+
+ ValueWitnessBase = 0xFFFFFF00U,
+ };
+
+public:
+ LocalTypeData() = default;
+
+ // The magic values are all in the "negative" range and so do
+ // not collide with reasonable index values.
+
+ /// A reference to the type metadata.
+ static LocalTypeData forMetatype() { return LocalTypeData(Metatype); }
+ /// A reference to the value witness table.
+ static LocalTypeData forValueWitnessTable() {
+ return LocalTypeData(ValueWitnessTable);
+ }
+
+ /// A reference to a specific value witness.
+ static LocalTypeData forValueWitness(ValueWitness witness) {
+ return LocalTypeData((unsigned)witness + ValueWitnessBase);
+ }
+
+ /// A reference to a protocol witness table for an archetype.
+ static LocalTypeData forArchetypeProtocolWitness(unsigned index) {
+ return LocalTypeData(index);
+ }
+
+ RawType getRawValue() const {
+ return Value;
+ }
+};
+
+class LocalTypeDataCache {
+public:
+ using Key = std::pair<TypeBase*, LocalTypeData::RawType>;
+
+ static Key getKey(CanType type, LocalTypeData index) {
+ return Key(type.getPointer(), index.getRawValue());
+ }
+
+ /// An opaque class for storing keys for the dominance callback. The
+ /// key is assumed to be something like a pointer, and a null pointer is
+ /// assumed to mean a non-dominating point.
+ class DominanceKey {
+ void *Value;
+ public:
+ explicit DominanceKey(void *value = nullptr) : Value(value) {}
+ template <class T> T* as() const { return reinterpret_cast<T*>(Value); }
+ explicit operator bool() const { return Value != nullptr; }
+ };
+
+ /// A RAII object for managing a dominance scope.
+ class DominanceScope {
+ LocalTypeDataCache &Cache;
+ DominanceKey OldDefinitionPoint;
+ public:
+ explicit DominanceScope(LocalTypeDataCache &cache, DominanceKey newPoint)
+ : Cache(cache), OldDefinitionPoint(cache.ActiveDefinitionPoint) {
+ cache.ActiveDefinitionPoint = newPoint;
+ assert(!newPoint || cache.Callback);
+ }
+
+ DominanceScope(const DominanceScope &other) = delete;
+ DominanceScope &operator=(const DominanceScope &other) = delete;
+
+ ~DominanceScope() {
+ Cache.ActiveDefinitionPoint = OldDefinitionPoint;
+ }
+ };
+
+ using DominanceCallback = bool(IRGenFunction &IGF, DominanceKey key);
+
+private:
+ /// The dominance callback. This can be set at most once; when it's not
+ /// set, the cache must never have a non-null active definition point.
+ DominanceCallback *Callback = nullptr;
+ DominanceKey ActiveDefinitionPoint;
+
+ struct CacheEntryBase {
+ DominanceKey DefinitionPoint;
+
+ };
+
+ struct Source {
+ llvm::Value *Value;
+ MetadataPath::Map<llvm::Value*> Path;
+ };
+
+ std::vector<
+
+public:
+};
+
+}
+}
+
+#endif
diff --git a/lib/IRGen/LocalTypeDataKind.h b/lib/IRGen/LocalTypeDataKind.h
new file mode 100644
index 0000000..cb9cc2b
--- /dev/null
+++ b/lib/IRGen/LocalTypeDataKind.h
@@ -0,0 +1,139 @@
+//===--- LocalTypeDataKind.h - Kinds of locally-cached type data --*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LocalTypeDataKind class, which opaquely
+// represents a particular kind of local type data that we might
+// want to cache during emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_LOCALTYPEDATAKIND_H
+#define SWIFT_IRGEN_LOCALTYPEDATAKIND_H
+
+#include "swift/AST/Type.h"
+#include <stdint.h>
+#include "llvm/ADT/DenseMapInfo.h"
+
+namespace swift {
+ class NormalProtocolConformance;
+ class ProtocolDecl;
+
+namespace irgen {
+ enum class ValueWitness : unsigned;
+
+/// The kind of local type data we might want to store for a type.
+class LocalTypeDataKind {
+public:
+ using RawType = uintptr_t;
+private:
+ RawType Value;
+
+ explicit LocalTypeDataKind(unsigned Value) : Value(Value) {}
+
+ /// Magic values for special kinds of type metadata. These should be
+ /// small so that they should never conflict with a valid pointer.
+ ///
+ /// Since this representation is opaque, we don't worry about being able
+ /// to distinguish different kinds of pointer; we just assume that e.g. a
+ /// ProtocolConformance will never have the same address as a Decl.
+ enum : RawType {
+ Metatype,
+ ValueWitnessTable,
+ // <- add more special cases here
+
+ // The first enumerator for an individual value witness.
+ ValueWitnessBase,
+ };
+
+public:
+ LocalTypeDataKind() = default;
+
+ // The magic values are all odd and so do not collide with pointer values.
+
+ /// A reference to the type metadata.
+ static LocalTypeDataKind forMetatype() {
+ return LocalTypeDataKind(Metatype);
+ }
+
+ /// A reference to the value witness table.
+ static LocalTypeDataKind forValueWitnessTable() {
+ return LocalTypeDataKind(ValueWitnessTable);
+ }
+
+ /// A reference to a specific value witness.
+ static LocalTypeDataKind forValueWitness(ValueWitness witness) {
+ return LocalTypeDataKind(ValueWitnessBase + (unsigned)witness);
+ }
+
+ /// A reference to a protocol witness table for an archetype.
+ ///
+ /// This only works for non-concrete types because in principle we might
+ /// have multiple concrete conformoances for a concrete type used in the
+ /// same function.
+ static LocalTypeDataKind
+ forArchetypeProtocolWitnessTable(ProtocolDecl *protocol) {
+ return LocalTypeDataKind(uintptr_t(protocol));
+ }
+
+ /// A reference to a protocol witness table for an archetype.
+ ///
+ /// We assume that the protocol conformance is a sufficiently unique key.
+ /// This implicitly assumes that we don't care about having multiple
+ /// specializations of a conditional conformance for different
+ /// conformances.
+ static LocalTypeDataKind
+ forConcreteProtocolWitnessTable(NormalProtocolConformance *conformance) {
+ return LocalTypeDataKind(uintptr_t(conformance));
+ }
+
+ RawType getRawValue() const {
+ return Value;
+ }
+
+ bool operator==(LocalTypeDataKind other) const {
+ return Value == other.Value;
+ }
+};
+
+struct LocalTypeDataKey {
+ CanType Type;
+ LocalTypeDataKind Kind;
+
+ bool operator==(const LocalTypeDataKey &other) const {
+ return Type == other.Type && Kind == other.Kind;
+ }
+};
+
+}
+}
+
+template <> struct llvm::DenseMapInfo<swift::irgen::LocalTypeDataKey> {
+ using LocalTypeDataKey = swift::irgen::LocalTypeDataKey;
+ using CanTypeInfo = DenseMapInfo<swift::CanType>;
+ static inline LocalTypeDataKey getEmptyKey() {
+ return { CanTypeInfo::getEmptyKey(),
+ swift::irgen::LocalTypeDataKind::forMetatype() };
+ }
+ static inline LocalTypeDataKey getTombstoneKey() {
+ return { CanTypeInfo::getTombstoneKey(),
+ swift::irgen::LocalTypeDataKind::forMetatype() };
+ }
+ static unsigned getHashValue(const LocalTypeDataKey &key) {
+ return combineHashValue(CanTypeInfo::getHashValue(key.Type),
+ key.Kind.getRawValue());
+ }
+ static bool isEqual(const LocalTypeDataKey &a, const LocalTypeDataKey &b) {
+ return a == b;
+ }
+};
+
+#endif
\ No newline at end of file
diff --git a/lib/IRGen/MetadataPath.h b/lib/IRGen/MetadataPath.h
index 8a6a0e6..79fc99a 100644
--- a/lib/IRGen/MetadataPath.h
+++ b/lib/IRGen/MetadataPath.h
@@ -25,7 +25,9 @@
}
namespace swift {
+ class ProtocolDecl;
class CanType;
+ class Decl;
namespace irgen {
class IRGenFunction;
diff --git a/lib/IRGen/TypeInfo.h b/lib/IRGen/TypeInfo.h
index 705133f..ba28779 100644
--- a/lib/IRGen/TypeInfo.h
+++ b/lib/IRGen/TypeInfo.h
@@ -34,6 +34,9 @@
}
namespace swift {
+ enum IsTake_t : bool;
+ class SILType;
+
namespace irgen {
class Address;
class ContainedAddress;
@@ -260,6 +263,12 @@
virtual void deallocateStack(IRGenFunction &IGF, Address addr,
SILType T) const = 0;
+ /// Copy or take a value out of one address and into another, destroying
+ /// old value in the destination. Equivalent to either assignWithCopy
+ /// or assignWithTake depending on the value of isTake.
+ void assign(IRGenFunction &IGF, Address dest, Address src, IsTake_t isTake,
+ SILType T) const;
+
/// Copy a value out of an object and into another, destroying the
/// old value in the destination.
virtual void assignWithCopy(IRGenFunction &IGF, Address dest,
@@ -270,6 +279,13 @@
virtual void assignWithTake(IRGenFunction &IGF, Address dest,
Address src, SILType T) const = 0;
+ /// Copy-initialize or take-initialize an uninitialized object
+ /// with the value from a different object. Equivalent to either
+ /// initializeWithCopy or initializeWithTake depending on the value
+ /// of isTake.
+ void initialize(IRGenFunction &IGF, Address dest, Address src,
+ IsTake_t isTake, SILType T) const;
+
/// Perform a "take-initialization" from the given object. A
/// take-initialization is like a C++ move-initialization, except that
/// the old object is actually no longer permitted to be destroyed.
diff --git a/lib/Immediate/ImmediateImpl.h b/lib/Immediate/ImmediateImpl.h
index aba1e3b..5bc40f0 100644
--- a/lib/Immediate/ImmediateImpl.h
+++ b/lib/Immediate/ImmediateImpl.h
@@ -1,4 +1,4 @@
-//===-- ImmediateImpl.h - Support functions for immediate mode --*- C++ -*-===//
+//===--- ImmediateImpl.h - Support functions for immediate mode -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/LLVMPasses/LLVMARCOpts.h b/lib/LLVMPasses/LLVMARCOpts.h
index 05b7f25..fe84bab 100644
--- a/lib/LLVMPasses/LLVMARCOpts.h
+++ b/lib/LLVMPasses/LLVMARCOpts.h
@@ -1,4 +1,4 @@
-//===- LLVMARCOpts.h - LLVM level ARC Opts Utility Declarations -*- C++ -*-===//
+//===--- LLVMARCOpts.h - LLVM level ARC Opts Util. Declarations -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index ae0cdd8..caebdf8 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2877,7 +2877,7 @@
case AccessorKind::IsMaterializeForSet:
case AccessorKind::NotAccessor:
- llvm_unreachable("not parsable accessors");
+ llvm_unreachable("not parseable accessors");
}
}
diff --git a/lib/SIL/Verifier.cpp b/lib/SIL/Verifier.cpp
index b2f2e13..ee2b584 100644
--- a/lib/SIL/Verifier.cpp
+++ b/lib/SIL/Verifier.cpp
@@ -2018,6 +2018,18 @@
"failure dest of checked_cast_br must take no arguments");
}
+ void checkCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
+ require(CCABI->getSrc().getType().isAddress(),
+ "checked_cast_addr_br src must be an address");
+ require(CCABI->getDest().getType().isAddress(),
+ "checked_cast_addr_br dest must be an address");
+
+ require(CCABI->getSuccessBB()->bbarg_size() == 0,
+ "success dest block of checked_cast_addr_br must not take an argument");
+ require(CCABI->getFailureBB()->bbarg_size() == 0,
+ "failure dest block of checked_cast_addr_br must not take an argument");
+ }
+
void checkThinToThickFunctionInst(ThinToThickFunctionInst *TTFI) {
auto opFTy = requireObjectType(SILFunctionType, TTFI->getOperand(),
"thin_to_thick_function operand");
@@ -2542,7 +2554,7 @@
void checkSwitchEnumAddrInst(SwitchEnumAddrInst *SOI){
require(SOI->getOperand().getType().isAddress(),
- "switch_enum_addr operand must be an object");
+ "switch_enum_addr operand must be an address");
SILType uTy = SOI->getOperand().getType();
EnumDecl *uDecl = uTy.getEnumOrBoundGenericEnum();
diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h
index fd3fa14..548f81d 100644
--- a/lib/SILGen/ArgumentSource.h
+++ b/lib/SILGen/ArgumentSource.h
@@ -1,4 +1,4 @@
-//===--- ArgumentSource.h - Abstracted source of an argument 000-*- C++ -*-===//
+//===--- ArgumentSource.h - Abstracted source of an argument ----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp b/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp
index af7f67c..3e0fe42 100644
--- a/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp
+++ b/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp
@@ -1,4 +1,4 @@
-//===-- GlobalARCPairingAnalysis.cpp - Global ARC Retain Release Pairing --===//
+//===--- GlobalARCPairingAnalysis.cpp - Global ARC Retain Release Pairing -===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp b/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp
index 31085d9..fd90cb3 100644
--- a/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp
@@ -1,4 +1,4 @@
-//===- ClassHierarchyAnalysis.cpp - Analysis of class hierarchy -*- C++ -*-===//
+//===--- ClassHierarchyAnalysis.cpp - Class hierarchy analysis --*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/SILOptimizer/IPO/PerformanceInliner.cpp b/lib/SILOptimizer/IPO/PerformanceInliner.cpp
index f477bb2..6fffb12 100644
--- a/lib/SILOptimizer/IPO/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/IPO/PerformanceInliner.cpp
@@ -1,4 +1,4 @@
-//===- PerformanceInliner.cpp - Basic cost based inlining for performance -===//
+//===--- PerformanceInliner.cpp - Basic cost based performance inlining ---===//
//
// This source file is part of the Swift.org open source project
//
@@ -562,7 +562,7 @@
return false;
}
-// Returns the callee of an apply_inst if it is basically inlinable.
+// Returns the callee of an apply_inst if it is basically inlineable.
SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
SILFunction *Callee = AI.getCalleeFunction();
diff --git a/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp b/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp
index b165499..8665cad 100644
--- a/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp
+++ b/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp
@@ -1,4 +1,4 @@
-//===-- DataflowDiagnostics.cpp - Emits diagnostics based on SIL analysis -===//
+//===--- DataflowDiagnostics.cpp - Emits diagnostics based on SIL analysis ===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
index ab8fac5..6f26549 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
@@ -268,7 +268,7 @@
}
// Not fully covered switches will be diagnosed later. SILGen represents
- // them with a Default basic block with an unrechable instruction.
+ // them with a Default basic block with an unreachable instruction.
// We are going to produce an error on all unreachable instructions not
// eliminated by DCE.
if (!TheSuccessorBlock)
diff --git a/lib/SILOptimizer/SILCombiner/SILCombine.cpp b/lib/SILOptimizer/SILCombiner/SILCombine.cpp
index eb17934..27b7a4b 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombine.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombine.cpp
@@ -212,7 +212,7 @@
auto &TrackingList = *Builder.getTrackingList();
for (SILInstruction *I : TrackingList) {
DEBUG(llvm::dbgs() << "SC: add " << *I <<
- " from trackinglist to worklist\n");
+ " from tracking list to worklist\n");
Worklist.add(I);
}
TrackingList.clear();
diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
index ffa3fca..1277daf 100644
--- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
@@ -283,13 +283,13 @@
switch (Term->getTermKind()) {
case TermKind::ReturnInst:
case TermKind::ThrowInst:
- case TermKind::SwitchEnumAddrInst:
- case TermKind::CheckedCastAddrBranchInst:
case TermKind::Invalid:
llvm_unreachable("Unexpected terminator kind!");
case TermKind::UnreachableInst:
case TermKind::SwitchValueInst:
+ case TermKind::SwitchEnumAddrInst:
+ case TermKind::CheckedCastAddrBranchInst:
llvm_unreachable("Unexpected argument for terminator kind!");
break;
diff --git a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
index 99460f9..d020f47 100644
--- a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
@@ -145,7 +145,7 @@
/// which is a large function.
constexpr unsigned MaxLSLocationBBMultiplicationNone = 256*256;
-/// we could run optimsitic DSE on functions with less than 64 basic blocks
+/// we could run optimistic DSE on functions with less than 64 basic blocks
/// and 64 locations which is a sizeable function.
constexpr unsigned MaxLSLocationBBMultiplicationPessimistic = 64*64;
diff --git a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
index f3be266..24bfb44 100644
--- a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
+++ b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
@@ -141,7 +141,7 @@
/// \brief Find a root value for operand \p In. This function inspects a sil
/// value and strips trivial conversions such as values that are passed
/// as arguments to basic blocks with a single predecessor or type casts.
-/// This is a shallow one-spet search and not a deep recursive search.
+/// This is a shallow one-step search and not a deep recursive search.
///
/// For example, in the SIL code below, the root of %10 is %3, because it is
/// the only possible incoming value.
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index aa9bb60..aaa6c8d 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -1,4 +1,4 @@
-//===-- SpeculativeDevirtualizer.cpp -- Speculatively devirtualize calls --===//
+//===--- SpeculativeDevirtualizer.cpp - Speculatively devirtualize calls --===//
//
// This source file is part of the Swift.org open source project
//
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "sil-speculative-devirtualizer-pass"
+#define DEBUG_TYPE "sil-speculative-devirtualizer"
#include "swift/Basic/DemangleWrappers.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/SIL/SILArgument.h"
diff --git a/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp b/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp
index fef3e77..b05195f 100644
--- a/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp
+++ b/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp
@@ -1,19 +1,19 @@
-///===--- LSLocationPrinter.cpp - Dump all memory locations in program ---===//
-///
-/// This source file is part of the Swift.org open source project
-///
-/// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
-/// Licensed under Apache License v2.0 with Runtime Library Exception
-///
-/// See http://swift.org/LICENSE.txt for license information
-/// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-///
-///===---------------------------------------------------------------------===//
-///
-/// This pass tests type expansion, memlocation expansion and memlocation
-/// reduction.
-///
-///===---------------------------------------------------------------------===//
+//===--- LSLocationPrinter.cpp - Dump all memory locations in program -----===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass tests type expansion, memlocation expansion and memlocation
+// reduction.
+//
+//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-memlocation-dumper"
#include "swift/SILOptimizer/PassManager/Passes.h"
diff --git a/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp b/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
index 04cf943..49a15f4 100644
--- a/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
@@ -2,7 +2,7 @@
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
diff --git a/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp b/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
index 1fffa6b..1bc9b6b 100644
--- a/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
@@ -2,7 +2,7 @@
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
diff --git a/lib/SILOptimizer/Utils/ConstantFolding.cpp b/lib/SILOptimizer/Utils/ConstantFolding.cpp
index 4fa5941..2ed3f9e 100644
--- a/lib/SILOptimizer/Utils/ConstantFolding.cpp
+++ b/lib/SILOptimizer/Utils/ConstantFolding.cpp
@@ -1,4 +1,4 @@
-//===- ConstantFolding.cpp - Utilities for SIL constant folding -*- C++ -*-===//
+//===--- ConstantFolding.cpp - Utils for SIL constant folding ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 7032475..388e43a 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -5667,7 +5667,8 @@
// Coerce the pattern, in case we resolved something.
auto fnType = closure->getType()->castTo<FunctionType>();
- if (tc.coerceParameterListToType(closure, fnType))
+ auto *params = closure->getParameters();
+ if (tc.coerceParameterListToType(params, closure, fnType->getInput()))
return { false, nullptr };
// If this is a single-expression closure, convert the expression
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 8e17f1f..57f3981 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -4164,7 +4164,61 @@
CS->getContextualType()->is<AnyFunctionType>()) {
auto fnType = CS->getContextualType()->castTo<AnyFunctionType>();
- if (CS->TC.coerceParameterListToType(CE, fnType))
+ auto *params = CE->getParameters();
+ Type inferredArgType = fnType->getInput();
+
+ // It is very common for a contextual type to disagree with the argument
+ // list built into the closure expr. This can be because the closure expr
+ // had an explicitly specified pattern, a la:
+ // { a,b in ... }
+ // or could be because the closure has an implicitly generated one:
+ // { $0 + $1 }
+ // in either case, we want to produce nice and clear diagnostics.
+ unsigned actualArgCount = params->size();
+ unsigned inferredArgCount = 1;
+ if (auto *argTupleTy = inferredArgType->getAs<TupleType>())
+ inferredArgCount = argTupleTy->getNumElements();
+
+ // If the actual argument count is 1, it can match a tuple as a whole.
+ if (actualArgCount != 1 && actualArgCount != inferredArgCount) {
+ // If the closure didn't specify any arguments and it is in a context that
+ // needs some, produce a fixit to turn "{...}" into "{ _,_ in ...}".
+ if (actualArgCount == 0 && CE->getInLoc().isInvalid()) {
+ auto diag =
+ diagnose(CE->getStartLoc(), diag::closure_argument_list_missing,
+ inferredArgCount);
+ StringRef fixText; // We only handle the most common cases.
+ if (inferredArgCount == 1)
+ fixText = " _ in ";
+ else if (inferredArgCount == 2)
+ fixText = " _,_ in ";
+ else if (inferredArgCount == 3)
+ fixText = " _,_,_ in ";
+
+ if (!fixText.empty()) {
+ // Determine if there is already a space after the { in the closure to
+ // make sure we introduce the right whitespace.
+ auto afterBrace = CE->getStartLoc().getAdvancedLoc(1);
+ auto text = CS->TC.Context.SourceMgr.extractText({afterBrace, 1});
+ if (text.size() == 1 && text == " ")
+ fixText = fixText.drop_back();
+ else
+ fixText = fixText.drop_front();
+ diag.fixItInsertAfter(CE->getStartLoc(), fixText);
+ }
+ return true;
+ }
+
+ // Okay, the wrong number of arguments was used, complain about that.
+ // Before doing so, strip attributes off the function type so that they
+ // don't confuse the issue.
+ fnType = FunctionType::get(fnType->getInput(), fnType->getResult());
+ diagnose(params->getStartLoc(), diag::closure_argument_list_tuple,
+ fnType, inferredArgCount, actualArgCount);
+ return true;
+ }
+
+ if (CS->TC.coerceParameterListToType(params, CE, inferredArgType))
return true;
expectedResultType = fnType->getResult();
@@ -4282,6 +4336,16 @@
}
if (!foundConformance) {
+ // If the contextual type conforms to DictionaryLiteralConvertible and
+ // this is an empty array, then they meant "[:]".
+ if (E->getNumElements() == 0 &&
+ isDictionaryLiteralCompatible(contextualType, CS, E->getLoc())) {
+ diagnose(E->getStartLoc(), diag::should_use_empty_dictionary_literal)
+ .fixItInsert(E->getEndLoc(), ":");
+ return true;
+ }
+
+
diagnose(E->getStartLoc(), diag::type_is_not_array, contextualType)
.highlight(E->getSourceRange());
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 5fde0e7..c77266c 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1593,12 +1593,16 @@
// containing a single element if the scalar type is a subtype of
// the type of that tuple's element.
//
- // A scalar type can be converted to a tuple so long as there is at
- // most one non-defaulted element.
+ // A scalar type can be converted to an argument tuple so long as
+ // there is at most one non-defaulted element.
+ // For non-argument tuples, we can do the same conversion but not
+ // to a tuple with varargs.
if ((tuple2->getNumElements() == 1 &&
!tuple2->getElement(0).isVararg()) ||
(kind >= TypeMatchKind::Conversion &&
- tuple2->getElementForScalarInit() >= 0)) {
+ tuple2->getElementForScalarInit() >= 0 &&
+ (isArgumentTupleConversion ||
+ !tuple2->getVarArgsBaseType()))) {
conversionsOrFixes.push_back(
ConversionRestrictionKind::ScalarToTuple);
diff --git a/lib/Sema/ConstraintGraphScope.h b/lib/Sema/ConstraintGraphScope.h
index 7c09a43..213ca89 100644
--- a/lib/Sema/ConstraintGraphScope.h
+++ b/lib/Sema/ConstraintGraphScope.h
@@ -1,4 +1,4 @@
-//===--- ConstraintGraphScope.h - Constraint Graph Scope---------*- C++ -*-===//
+//===--- ConstraintGraphScope.h - Constraint Graph Scope --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Sema/ITCDecl.cpp b/lib/Sema/ITCDecl.cpp
index b7c4354..1371b77 100644
--- a/lib/Sema/ITCDecl.cpp
+++ b/lib/Sema/ITCDecl.cpp
@@ -22,9 +22,9 @@
#include <tuple>
using namespace swift;
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Inheritance clause handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
static std::tuple<TypeResolutionOptions, DeclContext *,
MutableArrayRef<TypeLoc>>
decomposeInheritedClauseDecl(
@@ -116,9 +116,9 @@
return true;
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Superclass handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isTypeCheckSuperclassSatisfied(ClassDecl *payload) {
return payload->LazySemanticInfo.Superclass.getInt();
}
@@ -162,9 +162,9 @@
return true;
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Raw type handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isTypeCheckRawTypeSatisfied(EnumDecl *payload) {
return payload->LazySemanticInfo.RawType.getInt();
}
@@ -205,9 +205,9 @@
return true;
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Inherited protocols
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isInheritedProtocolsSatisfied(ProtocolDecl *payload){
return payload->isInheritedProtocolsValid();
}
@@ -280,9 +280,9 @@
return true;
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Resolve a type declaration
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isResolveTypeDeclSatisfied(TypeDecl *typeDecl) {
if (auto typeAliasDecl = dyn_cast<TypeAliasDecl>(typeDecl)) {
// If the underlying type was validated, we're done.
diff --git a/lib/Sema/ITCNameLookup.cpp b/lib/Sema/ITCNameLookup.cpp
index 894d6b44..87ab725 100644
--- a/lib/Sema/ITCNameLookup.cpp
+++ b/lib/Sema/ITCNameLookup.cpp
@@ -21,9 +21,9 @@
#include <tuple>
using namespace swift;
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Qualified name lookup handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isQualifiedLookupInDeclContextSatisfied(
TypeCheckRequest::DeclContextLookupPayloadType payload) {
auto dc = payload.DC;
@@ -123,9 +123,9 @@
return false;
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Qualified name lookup handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isUnqualifiedLookupInDeclContextSatisfied(
TypeCheckRequest::DeclContextLookupPayloadType payload) {
auto dc = payload.DC;
diff --git a/lib/Sema/ITCType.cpp b/lib/Sema/ITCType.cpp
index 03aae1d..8a8c4bd 100644
--- a/lib/Sema/ITCType.cpp
+++ b/lib/Sema/ITCType.cpp
@@ -22,9 +22,9 @@
#include "swift/AST/Decl.h"
using namespace swift;
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Type resolution.
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isResolveTypeReprSatisfied(
std::tuple<TypeRepr *, DeclContext *, unsigned> payload) {
auto typeRepr = std::get<0>(payload);
diff --git a/lib/Sema/IterativeTypeChecker.cpp b/lib/Sema/IterativeTypeChecker.cpp
index e86281d..0cd26e9 100644
--- a/lib/Sema/IterativeTypeChecker.cpp
+++ b/lib/Sema/IterativeTypeChecker.cpp
@@ -112,9 +112,9 @@
}
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Diagnostics
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
void IterativeTypeChecker::diagnoseCircularReference(
ArrayRef<TypeCheckRequest> requests) {
bool isFirst = true;
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index da35319..a77f619 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -1360,10 +1360,23 @@
// Attempt to solve the constraint system.
SmallVector<Solution, 4> viable;
+ const Type originalType = expr->getType();
+ const bool needClearType = originalType && originalType->is<ErrorType>();
+ const auto recoverOriginalType = [&] () {
+ if (needClearType)
+ expr->setType(originalType);
+ };
+
+ // If the previous checking gives the expr error type, clear the result and
+ // re-check.
+ if (needClearType)
+ expr->setType(Type());
if (solveForExpression(expr, dc, /*convertType*/Type(),
allowFreeTypeVariables, listener, cs, viable,
- TypeCheckExprFlags::SuppressDiagnostics))
+ TypeCheckExprFlags::SuppressDiagnostics)) {
+ recoverOriginalType();
return None;
+ }
// Get the expression's simplified type.
auto &solution = viable[0];
@@ -1373,6 +1386,8 @@
assert(!exprType->hasTypeVariable() &&
"free type variable with FreeTypeVariableBinding::GenericParameters?");
+ // Recover the original type if needed.
+ recoverOriginalType();
return exprType;
}
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 19574e0..8a4e6f5 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -1548,11 +1548,11 @@
///
/// \returns true if an error occurred, false otherwise.
///
-bool TypeChecker::coerceParameterListToType(ClosureExpr *CE,
- AnyFunctionType *closureType) {
- auto paramListType = closureType->getInput();
-
- ParameterList *P = CE->getParameters();
+/// TODO: These diagnostics should be a lot better now that we know this is
+/// all specific to closures.
+///
+bool TypeChecker::coerceParameterListToType(ParameterList *P, DeclContext *DC,
+ Type paramListType) {
bool hadError = paramListType->is<ErrorType>();
// Sometimes a scalar type gets applied to a single-argument parameter list.
@@ -1561,7 +1561,7 @@
// Check that the type, if explicitly spelled, is ok.
if (param->getTypeLoc().getTypeRepr()) {
- hadError |= validateParameterType(param, CE, TypeResolutionOptions(),
+ hadError |= validateParameterType(param, DC, TypeResolutionOptions(),
nullptr, *this);
// Now that we've type checked the explicit argument type, see if it
@@ -1582,74 +1582,29 @@
return hadError;
};
- // If there is one parameter to the closure, then it gets inferred to be the
- // complete type presented.
- if (P->size() == 1)
- return handleParameter(P->get(0), paramListType);
-
- // The context type must be a tuple if we have multiple parameters, and match
- // in element count. If it doesn't, we'll diagnose it and force the
- // parameters to ErrorType.
- TupleType *tupleTy = paramListType->getAs<TupleType>();
- unsigned inferredArgCount = 1;
- if (tupleTy)
- inferredArgCount = tupleTy->getNumElements();
-
- // If we already emitted a diagnostic, or if our argument count matches up,
- // then there is nothing to do.
- if (hadError || P->size() == inferredArgCount) {
- // I just said, nothing to do!
-
- // It is very common for a contextual type to disagree with the closure
- // argument list. This can be because the closure expr had an explicitly
- // specified parameter list, a la:
- // { a,b in ... }
- // or could be because the closure has an implicitly generated one:
- // { $0 + $1 }
- // in either case, we want to produce nice and clear diagnostics.
- // If the closure didn't specify any arguments and it is in a context that
- // needs some, produce a fixit to turn "{...}" into "{ _,_ in ...}".
- } else if (P->size() == 0 && CE->getInLoc().isInvalid()) {
- auto diag =
- diagnose(CE->getStartLoc(), diag::closure_argument_list_missing,
- inferredArgCount);
- StringRef fixText; // We only handle the most common cases.
- if (inferredArgCount == 1)
- fixText = " _ in ";
- else if (inferredArgCount == 2)
- fixText = " _,_ in ";
- else if (inferredArgCount == 3)
- fixText = " _,_,_ in ";
-
- if (!fixText.empty()) {
- // Determine if there is already a space after the { in the closure to
- // make sure we introduce the right whitespace.
- auto afterBrace = CE->getStartLoc().getAdvancedLoc(1);
- auto text = Context.SourceMgr.extractText({afterBrace, 1});
- if (text.size() == 1 && text == " ")
- fixText = fixText.drop_back();
- else
- fixText = fixText.drop_front();
- diag.fixItInsertAfter(CE->getStartLoc(), fixText);
- }
+ // The context type must be a tuple.
+ TupleType *tupleTy = paramListType->getAs<TupleType>();
+ if (!tupleTy && !hadError) {
+ if (P->size() == 1)
+ return handleParameter(P->get(0), paramListType);
+ diagnose(P->getStartLoc(), diag::tuple_pattern_in_non_tuple_context,
+ paramListType);
hadError = true;
- } else {
- // Okay, the wrong number of arguments was used, so complain about that
- // generically. We should try even harder here :-)
- //
- // Before doing so, strip attributes off the function type so that they
- // don't confuse the issue.
- auto fnType = FunctionType::get(closureType->getInput(),
- closureType->getResult());
+ }
+
+ // The number of elements must match exactly.
+ // TODO: incomplete tuple patterns, with some syntax.
+ if (!hadError && tupleTy->getNumElements() != P->size()) {
+ if (P->size() == 1)
+ return handleParameter(P->get(0), paramListType);
- diagnose(P->getStartLoc(), diag::closure_argument_list_tuple,
- fnType, inferredArgCount, P->size());
+ diagnose(P->getStartLoc(), diag::tuple_pattern_length_mismatch,
+ paramListType);
hadError = true;
}
- // Coerce each parameter to the respective type, or ErrorType if we already
- // detected and diagnosed an error.
+ // Coerce each parameter to the respective type.
for (unsigned i = 0, e = P->size(); i != e; ++i) {
auto ¶m = P->get(i);
@@ -1658,10 +1613,9 @@
CoercionType = ErrorType::get(Context);
else
CoercionType = tupleTy->getElement(i).getType();
-
+
// If the tuple pattern had a label for the tuple element, it must match
// the label for the tuple type being matched.
- // FIXME: closure should probably not be allowed to have API/argument names.
auto argName = param->getArgumentName();
if (!hadError && !argName.empty() &&
argName != tupleTy->getElement(i).getName()) {
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 8712a21..a47cd06 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -331,7 +331,7 @@
/// Type-check an entire function body.
bool typeCheckBody(BraceStmt *&S) {
- if (typeCheckStmt(S)) return true;
+ typeCheckStmt(S);
setAutoClosureDiscriminators(DC, S);
return false;
}
@@ -402,7 +402,6 @@
if (hadTypeError) {
tryDiagnoseUnnecessaryCastOverOptionSet(TC.Context, E, ResultTy,
DC->getParentModule());
- return nullptr;
}
return RS;
@@ -415,55 +414,52 @@
Type exnType = TC.getExceptionType(DC, TS->getThrowLoc());
if (!exnType) return TS;
- auto hadTypeError = TC.typeCheckExpression(E, DC, exnType, CTP_ThrowStmt);
+ TC.typeCheckExpression(E, DC, exnType, CTP_ThrowStmt);
TS->setSubExpr(E);
- return hadTypeError ? nullptr : TS;
+ return TS;
}
Stmt *visitDeferStmt(DeferStmt *DS) {
TC.typeCheckDecl(DS->getTempDecl(), /*isFirstPass*/false);
Expr *theCall = DS->getCallExpr();
- auto hadTypeError = TC.typeCheckExpression(theCall, DC);
+ TC.typeCheckExpression(theCall, DC);
DS->setCallExpr(theCall);
- return hadTypeError ? nullptr : DS;
+ return DS;
}
Stmt *visitIfStmt(IfStmt *IS) {
- bool hadTypeError = false;
-
StmtCondition C = IS->getCond();
- hadTypeError |= TC.typeCheckStmtCondition(C, DC, diag::if_always_true);
+ TC.typeCheckStmtCondition(C, DC, diag::if_always_true);
IS->setCond(C);
AddLabeledStmt ifNest(*this, IS);
Stmt *S = IS->getThenStmt();
- hadTypeError |= typeCheckStmt(S);
+ typeCheckStmt(S);
IS->setThenStmt(S);
if ((S = IS->getElseStmt())) {
- hadTypeError |= typeCheckStmt(S);
+ typeCheckStmt(S);
IS->setElseStmt(S);
}
- return hadTypeError ? nullptr : IS;
+ return IS;
}
Stmt *visitGuardStmt(GuardStmt *GS) {
- bool hadTypeError = false;
StmtCondition C = GS->getCond();
- hadTypeError |= TC.typeCheckStmtCondition(C, DC, diag::guard_always_succeeds);
+ TC.typeCheckStmtCondition(C, DC, diag::guard_always_succeeds);
GS->setCond(C);
AddLabeledStmt ifNest(*this, GS);
Stmt *S = GS->getBody();
- hadTypeError |= typeCheckStmt(S);
+ typeCheckStmt(S);
GS->setBody(S);
- return hadTypeError ? nullptr : GS;
+ return GS;
}
Stmt *visitIfConfigStmt(IfConfigStmt *ICS) {
@@ -477,69 +473,66 @@
Stmt *visitDoStmt(DoStmt *DS) {
AddLabeledStmt loopNest(*this, DS);
Stmt *S = DS->getBody();
- bool hadTypeError = typeCheckStmt(S);
+ typeCheckStmt(S);
DS->setBody(S);
- return hadTypeError ? nullptr : DS;
+ return DS;
}
Stmt *visitWhileStmt(WhileStmt *WS) {
- bool hadTypeError = false;
StmtCondition C = WS->getCond();
- hadTypeError |= TC.typeCheckStmtCondition(C, DC, diag::while_always_true);
+ TC.typeCheckStmtCondition(C, DC, diag::while_always_true);
WS->setCond(C);
AddLabeledStmt loopNest(*this, WS);
Stmt *S = WS->getBody();
- hadTypeError |= typeCheckStmt(S);
+ typeCheckStmt(S);
WS->setBody(S);
- return hadTypeError ? nullptr : WS;
+ return WS;
}
Stmt *visitRepeatWhileStmt(RepeatWhileStmt *RWS) {
- bool hadTypeError = false;
{
AddLabeledStmt loopNest(*this, RWS);
Stmt *S = RWS->getBody();
- hadTypeError |= typeCheckStmt(S);
+ typeCheckStmt(S);
RWS->setBody(S);
}
Expr *E = RWS->getCond();
- hadTypeError |= TC.typeCheckCondition(E, DC);
+ TC.typeCheckCondition(E, DC);
RWS->setCond(E);
- return hadTypeError ? nullptr : RWS;
+ return RWS;
}
Stmt *visitForStmt(ForStmt *FS) {
- bool hadTypeError = false;
// Type check any var decls in the initializer.
for (auto D : FS->getInitializerVarDecls())
TC.typeCheckDecl(D, /*isFirstPass*/false);
if (auto *Initializer = FS->getInitializer().getPtrOrNull()) {
- hadTypeError |= TC.typeCheckExpression(Initializer, DC, Type(), CTP_Unused,
- TypeCheckExprFlags::IsDiscarded);
+ TC.typeCheckExpression(Initializer, DC, Type(), CTP_Unused,
+ TypeCheckExprFlags::IsDiscarded);
FS->setInitializer(Initializer);
TC.checkIgnoredExpr(Initializer);
}
if (auto *Cond = FS->getCond().getPtrOrNull()) {
- hadTypeError |= TC.typeCheckCondition(Cond, DC);
+ TC.typeCheckCondition(Cond, DC);
FS->setCond(Cond);
}
if (auto *Increment = FS->getIncrement().getPtrOrNull()) {
- hadTypeError |= TC.typeCheckExpression(Increment, DC, Type(), CTP_Unused,
- TypeCheckExprFlags::IsDiscarded);
+ TC.typeCheckExpression(Increment, DC, Type(), CTP_Unused,
+ TypeCheckExprFlags::IsDiscarded);
FS->setIncrement(Increment);
TC.checkIgnoredExpr(Increment);
}
AddLabeledStmt loopNest(*this, FS);
Stmt *S = FS->getBody();
- hadTypeError |= typeCheckStmt(S);
+ typeCheckStmt(S);
FS->setBody(S);
- return hadTypeError ? nullptr : FS;
+ return FS;
}
Stmt *visitForEachStmt(ForEachStmt *S) {
@@ -689,7 +682,7 @@
// Type-check the body of the loop.
AddLabeledStmt loopNest(*this, S);
BraceStmt *Body = S->getBody();
- if (typeCheckStmt(Body)) return nullptr;
+ typeCheckStmt(Body);
S->setBody(Body);
return S;
@@ -806,14 +799,12 @@
}
Stmt *visitSwitchStmt(SwitchStmt *S) {
- bool hadTypeError = false;
// Type-check the subject expression.
Expr *subjectExpr = S->getSubjectExpr();
- hadTypeError |= TC.typeCheckExpression(subjectExpr, DC);
- subjectExpr = TC.coerceToMaterializable(subjectExpr);
- if (subjectExpr) {
- S->setSubjectExpr(subjectExpr);
- }
+ TC.typeCheckExpression(subjectExpr, DC);
+ if (Expr *newSubjectExpr = TC.coerceToMaterializable(subjectExpr))
+ subjectExpr = newSubjectExpr;
+ S->setSubjectExpr(subjectExpr);
Type subjectType = S->getSubjectExpr()->getType();
// Type-check the case blocks.
@@ -841,27 +832,24 @@
VD->overwriteType(ErrorType::get(TC.Context));
VD->setInvalid();
});
- hadTypeError = true;
}
labelItem.setPattern(pattern);
- } else {
- hadTypeError = true;
}
// Check the guard expression, if present.
if (auto *guard = labelItem.getGuardExpr()) {
- hadTypeError |= TC.typeCheckCondition(guard, DC);
+ TC.typeCheckCondition(guard, DC);
labelItem.setGuardExpr(guard);
}
}
// Type-check the body statements.
Stmt *body = caseBlock->getBody();
- hadTypeError |= typeCheckStmt(body);
+ typeCheckStmt(body);
caseBlock->setBody(body);
}
- return hadTypeError ? nullptr : S;
+ return S;
}
Stmt *visitCaseStmt(CaseStmt *S) {
@@ -874,23 +862,20 @@
llvm_unreachable("catch stmt outside of do-catch?!");
}
- bool checkCatchStmt(CatchStmt *S) {
- bool hadTypeError = false;
+ void checkCatchStmt(CatchStmt *S) {
// Check the catch pattern.
- hadTypeError |= TC.typeCheckCatchPattern(S, DC);
+ TC.typeCheckCatchPattern(S, DC);
// Check the guard expression, if present.
if (Expr *guard = S->getGuardExpr()) {
- hadTypeError |= TC.typeCheckCondition(guard, DC);
+ TC.typeCheckCondition(guard, DC);
S->setGuardExpr(guard);
}
// Type-check the clause body.
Stmt *body = S->getBody();
- hadTypeError |= typeCheckStmt(body);
+ typeCheckStmt(body);
S->setBody(body);
-
- return hadTypeError;
}
Stmt *visitDoCatchStmt(DoCatchStmt *S) {
@@ -899,20 +884,18 @@
// entire construct.
AddLabeledStmt loopNest(*this, S);
- bool hadTypeError = false;
-
// Type-check the 'do' body. Type failures in here will generally
// not cause type failures in the 'catch' clauses.
Stmt *newBody = S->getBody();
- hadTypeError |= typeCheckStmt(newBody);
+ typeCheckStmt(newBody);
S->setBody(newBody);
// Check all the catch clauses independently.
for (auto clause : S->getCatches()) {
- hadTypeError |= checkCatchStmt(clause);
+ checkCatchStmt(clause);
}
- return hadTypeError ? nullptr : S;
+ return S;
}
Stmt *visitFailStmt(FailStmt *S) {
@@ -925,8 +908,6 @@
} // end anonymous namespace
bool TypeChecker::typeCheckCatchPattern(CatchStmt *S, DeclContext *DC) {
- bool hadTypeError = false;
-
// Grab the standard exception type.
Type exnType = getExceptionType(DC, S->getCatchLoc());
@@ -945,15 +926,11 @@
var->overwriteType(ErrorType::get(Context));
var->setInvalid();
});
- hadTypeError = true;
}
S->setErrorPattern(pattern);
- } else {
- hadTypeError = true;
}
-
- return hadTypeError;
+ return false;
}
void TypeChecker::checkIgnoredExpr(Expr *E) {
@@ -1073,14 +1050,10 @@
if (isDiscarded)
options |= TypeCheckExprFlags::IsDiscarded;
- if (TC.typeCheckExpression(SubExpr, DC, Type(), CTP_Unused, options)) {
- elem = SubExpr;
- continue;
- }
-
- if (isDiscarded)
+ bool hadTypeError = TC.typeCheckExpression(SubExpr, DC, Type(),
+ CTP_Unused, options);
+ if (isDiscarded && !hadTypeError)
TC.checkIgnoredExpr(SubExpr);
-
elem = SubExpr;
continue;
}
@@ -1091,8 +1064,8 @@
(Loc == EndTypeCheckLoc || SM.isBeforeInBuffer(EndTypeCheckLoc, Loc)))
break;
- if (!typeCheckStmt(SubStmt))
- elem = SubStmt;
+ typeCheckStmt(SubStmt);
+ elem = SubStmt;
continue;
}
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 2feeef7..5ed768a 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1220,7 +1220,7 @@
// We allow a type to conform to a protocol that is less available than
// the type itself. This enables a type to retroactively model or directly
- // conform to a protocl only available on newer OSes and yet still be used on
+ // conform to a protocol only available on newer OSes and yet still be used on
// older OSes.
// To support this, inside inheritance clauses we allow references to
// protocols that are unavailable in the current type refinement context.
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 94fe210..ea44419 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1225,7 +1225,7 @@
/// contextual type.
///
/// \returns true if an error occurred, false otherwise.
- bool coerceParameterListToType(ClosureExpr *CE, AnyFunctionType *closureType);
+ bool coerceParameterListToType(ParameterList *P, DeclContext *dc, Type type);
/// Type-check an initialized variable pattern declaration.
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index d93738d..e0d9b4e 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2278,6 +2278,8 @@
}
auto *bodyParams0 = readParameterList();
+ bodyParams0->get(0)->setImplicit(); // self is implicit.
+
auto *bodyParams1 = readParameterList();
assert(bodyParams0 && bodyParams1 && "missing parameters for constructor");
ctor->setParameterLists(bodyParams0->get(0), bodyParams1);
@@ -2541,6 +2543,10 @@
for (unsigned i = 0, e = numParamPatterns; i != e; ++i)
paramLists.push_back(readParameterList());
+ // If the first parameter list is (self), mark it implicit.
+ if (numParamPatterns && DC->isTypeContext())
+ paramLists[0]->get(0)->setImplicit();
+
fn->setDeserializedSignature(paramLists,
TypeLoc::withoutLoc(signature->getResult()));
@@ -2967,7 +2973,7 @@
SourceLoc(), TypeLoc(), DC);
declOrOffset = subscript;
- subscript->setIndices(readParameterList());
+ subscript->setIndices(readParameterList());
subscript->getElementTypeLoc() = TypeLoc::withoutLoc(getType(elemTypeID));
configureStorage(subscript, rawStorageKind,
@@ -3095,6 +3101,8 @@
dtor->setAccessibility(cast<ClassDecl>(DC)->getFormalAccess());
auto *selfParams = readParameterList();
+ selfParams->get(0)->setImplicit(); // self is implicit.
+
assert(selfParams && "Didn't get self pattern?");
dtor->setSelfDecl(selfParams->get(0));
diff --git a/stdlib/public/core/FloatingPoint.swift.gyb b/stdlib/public/core/FloatingPoint.swift.gyb
index 545837a..08f5fe7 100644
--- a/stdlib/public/core/FloatingPoint.swift.gyb
+++ b/stdlib/public/core/FloatingPoint.swift.gyb
@@ -181,7 +181,7 @@
@_transparent public
init() {
let zero: Int64 = 0
- self._value = Builtin.uitofp_Int64_FPIEEE${bits}(zero._value)
+ self._value = Builtin.sitofp_Int64_FPIEEE${bits}(zero._value)
}
@_transparent
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 8f1ca5a..a953be7 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -2632,13 +2632,8 @@
swift::swift_conformsToProtocol(const Metadata *type,
const ProtocolDescriptor *protocol) {
auto &C = Conformances.get();
-
- // Install callbacks for tracking when a new dylib is loaded so we can
- // scan it.
auto origType = type;
-
unsigned numSections = 0;
-
ConformanceCacheEntry *foundEntry;
recur:
diff --git a/stdlib/public/stubs/Availability.mm b/stdlib/public/stubs/Availability.mm
index 3bd99b9..3d13741 100644
--- a/stdlib/public/stubs/Availability.mm
+++ b/stdlib/public/stubs/Availability.mm
@@ -1,4 +1,4 @@
-//===--- Availability.mm - Swift Language API Availability Support---------===//
+//===--- Availability.mm - Swift Language API Availability Support --------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/test/1_stdlib/StringTraps.swift b/test/1_stdlib/StringTraps.swift
index be16998..3fb0f04 100644
--- a/test/1_stdlib/StringTraps.swift
+++ b/test/1_stdlib/StringTraps.swift
@@ -7,10 +7,7 @@
// RUN: %target-run %t/a.out_Release
// REQUIRES: executable_test
-// XFAIL: linux
-
import StdlibUnittest
-import Foundation
// Also import modules which are used by StdlibUnittest internally. This
// workaround is needed to link all required libraries in case we compile
diff --git a/test/BuildConfigurations/pound-if-top-level-3.swift b/test/BuildConfigurations/pound-if-top-level-3.swift
index 9d66539..86f21c8 100644
--- a/test/BuildConfigurations/pound-if-top-level-3.swift
+++ b/test/BuildConfigurations/pound-if-top-level-3.swift
@@ -1,6 +1,5 @@
// RUN: %target-parse-verify-swift
-// e xpected-error@+1{{unexpected configuration expression type}}
#if arch(x86_64)
// expected-error@+2{{expected '{' in protocol type}}
// expected-error@+1{{expected #else or #endif at end of configuration block}}
diff --git a/test/Constraints/dictionary_literal.swift b/test/Constraints/dictionary_literal.swift
index 6c3b6c4..579f7ff 100644
--- a/test/Constraints/dictionary_literal.swift
+++ b/test/Constraints/dictionary_literal.swift
@@ -59,3 +59,6 @@
var _: Dictionary<String, Int>? = ["foo" : 1.0] // expected-error {{cannot convert value of type 'Double' to expected dictionary value type 'Int'}}
+// <rdar://problem/24058895> QoI: Should handle [] in dictionary contexts better
+var _: [Int: Int] = [] // expected-error {{use [:] to get an empty dictionary literal}} {{22-22=:}}
+
diff --git a/test/IDE/coloring.swift b/test/IDE/coloring.swift
index 5d8f65a..cff1b68 100644
--- a/test/IDE/coloring.swift
+++ b/test/IDE/coloring.swift
@@ -433,6 +433,10 @@
// CHECK: <doc-comment-block>/**/</doc-comment-block>
// CHECK: <kw>func</kw> malformedBlockComment(f : () <kw>throws</kw> -> ()) <attr-builtin>rethrows</attr-builtin> {}
+//: playground doc comment line
+func playgroundCommentLine(f : () throws -> ()) rethrows {}
+// CHECK: <comment-line>//: playground doc comment line</comment-line>
+
"--\"\(x) --"
// CHECK: <str>"--\"</str>\<anchor>(</anchor>x<anchor>)</anchor><str> --"</str>
diff --git a/test/IDE/coloring_playground.swift b/test/IDE/coloring_playground.swift
new file mode 100644
index 0000000..61c666e
--- /dev/null
+++ b/test/IDE/coloring_playground.swift
@@ -0,0 +1,16 @@
+// RUN: %target-swift-ide-test -syntax-coloring -playground -source-filename %s | FileCheck %s
+// RUN: %target-swift-ide-test -syntax-coloring -playground -typecheck -source-filename %s | FileCheck %s
+
+//: playground doc comment line
+func playgroundCommentLine(f : () throws -> ()) rethrows {}
+// CHECK: <doc-comment-line>//: playground doc comment line
+
+// Keep this as the last test
+/**
+ Trailing off ...
+func unterminatedBlockComment() {}
+// CHECK: <comment-line>// Keep this as the last test</comment-line>
+// CHECK: <doc-comment-block>/**
+// CHECK: Trailing off ...
+// CHECK: func unterminatedBlockComment() {}
+// CHECK: </doc-comment-block>
diff --git a/test/IDE/complete_literal.swift b/test/IDE/complete_literal.swift
index 85b46a5..43a1e4e 100644
--- a/test/IDE/complete_literal.swift
+++ b/test/IDE/complete_literal.swift
@@ -2,6 +2,7 @@
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL2 | FileCheck %s -check-prefix=LITERAL2
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL3 | FileCheck %s -check-prefix=LITERAL3
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL4 | FileCheck %s -check-prefix=LITERAL4
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL5 | FileCheck %s -check-prefix=LITERAL5
{
1.#^LITERAL1^#
@@ -48,3 +49,14 @@
// LITERAL4-DAG: Decl[InstanceMethod]/CurrNominal: insertContentsOf({#(newElements): S#}, {#at: Index#})[#Void#]; name=insertContentsOf(newElements: S, at: Index){{$}}
// LITERAL4-DAG: Decl[InstanceMethod]/CurrNominal: removeAtIndex({#(i): Index#})[#Character#]; name=removeAtIndex(i: Index){{$}}
// LITERAL4-DAG: Decl[InstanceVar]/CurrNominal: lowercaseString[#String#]; name=lowercaseString{{$}}
+
+func giveMeAString() -> Int {
+ // rdar://22637799
+ return "Here's a string".#^LITERAL5^# // try .characters.count here
+}
+
+// LITERAL5-DAG: Decl[InstanceVar]/CurrNominal: characters[#String.CharacterView#]{{; name=.+$}}
+// LITERAL5-DAG: Decl[InstanceVar]/CurrNominal: endIndex[#Index#]{{; name=.+$}}
+// LITERAL5-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: reserveCapacity({#(n): Int#})[#Void#]{{; name=.+$}}
+// LITERAL5-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: append({#(c): Character#})[#Void#]{{; name=.+$}}
+// LITERAL5-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: appendContentsOf({#(newElements): S#})[#Void#]{{; name=.+$}}
diff --git a/test/IDE/print_omit_needless_words.swift b/test/IDE/print_omit_needless_words.swift
index ddf0a56..a4469dc 100644
--- a/test/IDE/print_omit_needless_words.swift
+++ b/test/IDE/print_omit_needless_words.swift
@@ -64,6 +64,9 @@
// Note: Typedefs with a "_t" suffix".
// CHECK-FOUNDATION: func subtract(_: Int32) -> NSNumber
+// Note: Respect the getter name for BOOL properties.
+// CHECK-FOUNDATION: var isMakingHoney: Bool
+
// Note: multi-word enum name matching; "with" splits the first piece.
// CHECK-FOUNDATION: func someMethod(deprecatedOptions _: NSDeprecatedOptions = [])
@@ -138,8 +141,8 @@
// Collection element types.
// CHECK-FOUNDATION: func adding(_: AnyObject) -> Set<NSObject>
-// Boolean properties get an "is" prefix.
-// CHECK-FOUNDATION: var isEmpty: Bool { get }
+// Boolean properties follow the getter.
+// CHECK-FOUNDATION: var empty: Bool { get }
// CHECK-FOUNDATION: func nonEmpty() -> Bool
// CHECK-FOUNDATION: var isStringSet: Bool { get }
// CHECK-FOUNDATION: var wantsAUnion: Bool { get }
@@ -147,6 +150,9 @@
// CHECK-FOUNDATION: var appliesForAJob: Bool { get }
// CHECK-FOUNDATION: var setShouldBeInfinite: Bool { get }
+// "UTF8" initialisms.
+// CHECK-FOUNDATION: init?(utf8String: UnsafePointer<Int8>)
+
// Note: class method name stripping context type.
// CHECK-APPKIT: class func red() -> NSColor
diff --git a/test/IRGen/metadata_dominance.swift b/test/IRGen/metadata_dominance.swift
new file mode 100644
index 0000000..5e07095
--- /dev/null
+++ b/test/IRGen/metadata_dominance.swift
@@ -0,0 +1,51 @@
+// RUN: %target-swift-frontend -emit-ir -primary-file %s | FileCheck %s
+
+func use_metadata<F>(f: F) {}
+
+func voidToVoid() {}
+func intToInt(x: Int) -> Int { return x }
+
+func cond() -> Bool { return true }
+
+// CHECK: define hidden void @_TF18metadata_dominance5test1FT_T_()
+func test1() {
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+ if cond() {
+// CHECK: [[T0:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+ use_metadata(voidToVoid)
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+// CHECK-NOT: @_TMaFT_T_
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+ if cond() {
+ use_metadata(voidToVoid)
+ } else {
+// CHECK-NOT: @_TMaFT_T_
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+ use_metadata(voidToVoid)
+ }
+ }
+// CHECK: [[T1:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T1]])
+ use_metadata(voidToVoid)
+}
+
+// CHECK: define hidden void @_TF18metadata_dominance5test2FT_T_()
+func test2() {
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+ if cond() {
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+// CHECK: [[T0:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+ if cond() {
+ use_metadata(voidToVoid)
+ } else {
+// CHECK: [[T1:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T1]])
+ use_metadata(voidToVoid)
+ }
+ }
+// CHECK: [[T2:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T2]])
+ use_metadata(voidToVoid)
+}
diff --git a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
index ac3d8cd..785dfcb 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
@@ -985,3 +985,7 @@
int variadicFunc1(int A, ...);
int variadicFunc2(int A, ...);
+
+@interface NSString (UTF8)
+-(nullable instancetype)initWithUTF8String:(const char *)bytes;
+@end
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index 2d20044..1201a70 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -318,7 +318,7 @@
// CHECK-NEXT: return %2 : $Int
}
-// Make sure that we generate direct function calls for out struct protocl
+// Make sure that we generate direct function calls for out struct protocol
// witness since structs don't do virtual calls for methods.
//
// *NOTE* Even though at first glance the copy_addr looks like a leak
diff --git a/test/SILOptimizer/devirt_default_case.swift b/test/SILOptimizer/devirt_default_case.swift
index 871e64e..fc0d989 100644
--- a/test/SILOptimizer/devirt_default_case.swift
+++ b/test/SILOptimizer/devirt_default_case.swift
@@ -106,7 +106,7 @@
// B has its own implementation.
@inline(never)
func foo(a: A3) -> Int {
-// Check that call to A3.f() can be devirualized.
+// Check that call to A3.f() can be devirtualized.
//
// CHECK-LABEL: sil{{( hidden)?}} [noinline] @_TF19devirt_default_case3fooFCS_2A3Si
// CHECK: function_ref @{{.*}}TFC19devirt_default_case2B31f
diff --git a/test/SILOptimizer/postdomtree_verification_crash.sil b/test/SILOptimizer/postdomtree_verification_crash.sil
new file mode 100644
index 0000000..96fcd1d
--- /dev/null
+++ b/test/SILOptimizer/postdomtree_verification_crash.sil
@@ -0,0 +1,22 @@
+// RUN: %target-sil-opt -enable-sil-verify-all -sil-verify-without-invalidation %s -stack-promotion
+
+// Check if post-dominator verification does not crash on multiple roots.
+// We run stack promotion because it requests the post-dominator analysis.
+
+sil_stage canonical
+
+import Builtin
+import Swift
+
+sil @testit : $@convention(thin) () -> () {
+bb0:
+ cond_br undef, bb1, bb2
+
+bb1:
+ br bb1
+
+bb2:
+ %r = tuple ()
+ return %r : $()
+}
+
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 662f7fc..0e66985 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -2,7 +2,6 @@
import Builtin
import Swift
-import Foundation
// Test SIL Global variable.
// TODO: Handling of global variables has changed: the globalinit_* symbols are now mangled.
@@ -212,19 +211,6 @@
%7 = return %6 : $()
}
-// CHECK-LABEL: @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
-sil [fragile] @objc_classes : $@convention(thin) (@thick NSObject.Type) -> () {
-bb0(%0 : $@thick NSObject.Type):
- %1 = thick_to_objc_metatype %0 : $@thick NSObject.Type to $@objc_metatype NSObject.Type
- // CHECK: %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
- %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
- %3 = value_metatype $@thick NSObject.Type, %2 : $NSObject
- dealloc_partial_ref %2 : $NSObject, %3 : $@thick NSObject.Type
-
- %void = tuple ()
- return %void : $()
-} // CHECK: {{^}$}}
-
// Generated from:
// func archetype_member_ref<T : Runcible>(x: T) {
// x.free_method()
@@ -610,15 +596,6 @@
return %4 : $Int
}
-class Bas : NSObject {
- var strRealProp : String
- override init()
-}
-sil [fragile] @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
-
-sil [fragile] @swift_StringToNSString : $@convention(thin) (@inout String) -> @owned NSString
-sil [fragile] @_TFSSCfMSSFT_SS : $@convention(thin) (@thin String.Type) -> @owned String
-
// CHECK-LABEL: sil public_external [fragile] @test_builtin_func_ref
sil [fragile] @test_builtin_func_ref : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> Builtin.Int1 {
bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1):
@@ -969,19 +946,6 @@
return %b : $@convention(block) () -> ()
}
-protocol SomeClassProtocol : class {}
-
-// CHECK-LABEL: sil public_external [fragile] @metatype_to_object
-// CHECK: {{%.*}} = objc_metatype_to_object {{%.*}} : $@objc_metatype SomeClass.Type to $AnyObject
-// CHECK: {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype SomeClassProtocol.Type to $AnyObject
-sil [fragile] @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject) {
-entry(%a : $@objc_metatype SomeClass.Type, %b : $@objc_metatype SomeClassProtocol.Type):
- %x = objc_metatype_to_object %a : $@objc_metatype SomeClass.Type to $AnyObject
- %y = objc_existential_metatype_to_object %b : $@objc_metatype SomeClassProtocol.Type to $AnyObject
- %z = tuple (%x : $AnyObject, %y : $AnyObject)
- return %z : $(AnyObject, AnyObject)
-}
-
// CHECK-LABEL: sil public_external [fragile] @bitcasts : $@convention(thin) (@owned Class1) -> @owned (Class2, Int) {
// CHECK: bb0(%0 : $Class1):
// CHECK-NEXT: %1 = unchecked_ref_cast %0 : $Class1 to $Class2
@@ -996,16 +960,6 @@
return %3 : $(Class2, Int)
}
-@objc protocol ObjCProto {}
-
-// CHECK-LABEL: sil public_external [fragile] @protocol_conversion
-sil [fragile] @protocol_conversion : $@convention(thin) () -> @owned Protocol {
-entry:
- // CHECK: {{%.*}} = objc_protocol #ObjCProto : $Protocol
- %p = objc_protocol #ObjCProto : $Protocol
- return %p : $Protocol
-}
-
sil [fragile] @block_invoke : $@convention(c) (@inout_aliasable @block_storage Int) -> ()
@@ -1310,7 +1264,6 @@
%13 = function_ref @return_constant : $@convention(thin) () -> Int
%23 = function_ref @existentials : $@convention(thin) (@in P) -> ()
%25 = function_ref @classes : $@convention(thin) () -> ()
- %26 = function_ref @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
%27 = function_ref @_TF4todo18erasure_from_protoFT1xPS_8RuncibleS_8Bendable__PS0__ : $@convention(thin) (@out Runcible, @in protocol<Bendable, Runcible>) -> ()
%29 = function_ref @_TF4todo18class_bound_methodFT1xPS_10ClassBound__T_ : $@convention(thin) (@owned ClassBound) -> ()
%31 = function_ref @_TFV6struct5AlephCfMS0_FT1aCS_3Ref1bVS_3Val_S0_ : $@convention(thin) (Ref, Val, @thin Aleph.Type) -> Aleph
@@ -1336,7 +1289,6 @@
%73 = function_ref @test_basic_block_arguments : $@convention(thin) (Builtin.Int1) -> Builtin.Word
%75 = function_ref @test_cond_branch_basic_block_args : $@convention(thin) (Int, Builtin.Int1) -> Int
- %79 = function_ref @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
%81 = function_ref @test_builtin_func_ref : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> Builtin.Int1
%83 = function_ref @test_dealloc_ref : $@convention(thin) () -> ()
%84 = function_ref @test_dealloc_partial_ref : $@convention(thin) () -> ()
@@ -1362,9 +1314,7 @@
%118 = function_ref @cond_fail_test : $@convention(thin) Builtin.Int1 -> ()
%124 = function_ref @block_storage_type : $@convention(thin) Int -> @convention(block) () -> ()
- %125 = function_ref @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject)
%127 = function_ref @bitcasts : $@convention(thin) (@owned Class1) -> @owned (Class2, Int)
- %126 = function_ref @protocol_conversion : $@convention(thin) () -> @owned Protocol
%133 = function_ref @test_try_apply : $@convention(thin) (@convention(thin) () -> @error ErrorType) -> @error ErrorType
%135 = function_ref @test_try_nothrow : $@convention(thin) (@convention(thin) () -> @error ErrorType) -> ()
%134 = function_ref @box_type : $@convention(thin) (@box Int, Int) -> ()
diff --git a/test/Serialization/Inputs/def_basic_objc.sil b/test/Serialization/Inputs/def_basic_objc.sil
new file mode 100644
index 0000000..7f20e7d
--- /dev/null
+++ b/test/Serialization/Inputs/def_basic_objc.sil
@@ -0,0 +1,70 @@
+sil_stage raw // CHECK: sil_stage raw
+
+import Builtin
+import Swift
+import Foundation
+
+protocol SomeProtocol { }
+class SomeClass : SomeProtocol { }
+
+// CHECK-LABEL: @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
+sil [fragile] @objc_classes : $@convention(thin) (@thick NSObject.Type) -> () {
+bb0(%0 : $@thick NSObject.Type):
+ %1 = thick_to_objc_metatype %0 : $@thick NSObject.Type to $@objc_metatype NSObject.Type
+ // CHECK: %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
+ %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
+ %3 = value_metatype $@thick NSObject.Type, %2 : $NSObject
+ dealloc_partial_ref %2 : $NSObject, %3 : $@thick NSObject.Type
+
+ %void = tuple ()
+ return %void : $()
+} // CHECK: {{^}$}}
+
+class Bas : NSObject {
+ var strRealProp : String
+ override init()
+}
+
+sil [fragile] @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
+sil [fragile] @swift_StringToNSString : $@convention(thin) (@inout String) -> @owned NSString
+sil [fragile] @_TFSSCfMSSFT_SS : $@convention(thin) (@thin String.Type) -> @owned String
+
+protocol SomeClassProtocol : class {}
+
+// CHECK-LABEL: sil public_external [fragile] @metatype_to_object
+// CHECK: {{%.*}} = objc_metatype_to_object {{%.*}} : $@objc_metatype SomeClass.Type to $AnyObject
+// CHECK: {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype SomeClassProtocol.Type to $AnyObject
+sil [fragile] @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject) {
+entry(%a : $@objc_metatype SomeClass.Type, %b : $@objc_metatype SomeClassProtocol.Type):
+ %x = objc_metatype_to_object %a : $@objc_metatype SomeClass.Type to $AnyObject
+ %y = objc_existential_metatype_to_object %b : $@objc_metatype SomeClassProtocol.Type to $AnyObject
+ %z = tuple (%x : $AnyObject, %y : $AnyObject)
+ return %z : $(AnyObject, AnyObject)
+}
+
+@objc protocol ObjCProto {}
+
+// CHECK-LABEL: sil public_external [fragile] @protocol_conversion
+sil [fragile] @protocol_conversion : $@convention(thin) () -> @owned Protocol {
+entry:
+ // CHECK: {{%.*}} = objc_protocol #ObjCProto : $Protocol
+ %p = objc_protocol #ObjCProto : $Protocol
+ return %p : $Protocol
+}
+
+public func serialize_all() {
+}
+
+sil [fragile] [transparent] @_TF14def_basic_objc13serialize_allFT_T_ : $@convention(thin) () -> () {
+bb0:
+ %26 = function_ref @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
+
+ %79 = function_ref @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
+
+ %125 = function_ref @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject)
+
+ %126 = function_ref @protocol_conversion : $@convention(thin) () -> @owned Protocol
+
+ %119 = tuple ()
+ return %119 : $()
+}
diff --git a/test/Serialization/basic_sil.swift b/test/Serialization/basic_sil.swift
index 731f5ab..3d10937 100644
--- a/test/Serialization/basic_sil.swift
+++ b/test/Serialization/basic_sil.swift
@@ -1,15 +1,13 @@
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -I %S/../Inputs/clang-importer-sdk/swift-modules -emit-module -Xfrontend -disable-diagnostic-passes -Xfrontend -sil-serialize-all -force-single-frontend-invocation -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
+// RUN: %target-build-swift -emit-module -Xfrontend -disable-diagnostic-passes -Xfrontend -sil-serialize-all -force-single-frontend-invocation -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
// RUN: llvm-bcanalyzer %t/def_basic.swiftmodule | FileCheck %s
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck %S/Inputs/def_basic.sil
+// RUN: %target-build-swift -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck %S/Inputs/def_basic.sil
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -Xfrontend -sil-serialize-all -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck -check-prefix=CHECK_DECL %S/Inputs/def_basic.sil
-
-// XFAIL: linux
+// RUN: %target-build-swift -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -Xfrontend -sil-serialize-all -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
+// RUN: %target-build-swift -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck -check-prefix=CHECK_DECL %S/Inputs/def_basic.sil
// This test currently is written such that no optimizations are assumed.
// REQUIRES: swift_test_mode_optimize_none
diff --git a/test/Serialization/basic_sil_objc.swift b/test/Serialization/basic_sil_objc.swift
new file mode 100644
index 0000000..998f110
--- /dev/null
+++ b/test/Serialization/basic_sil_objc.swift
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -I %S/../Inputs/clang-importer-sdk/swift-modules -emit-module -Xfrontend -disable-diagnostic-passes -Xfrontend -sil-serialize-all -force-single-frontend-invocation -o %t/def_basic_objc.swiftmodule %S/Inputs/def_basic_objc.sil
+// RUN: llvm-bcanalyzer %t/def_basic_objc.swiftmodule | FileCheck %s
+// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck %S/Inputs/def_basic_objc.sil
+
+// This test currently is written such that no optimizations are assumed.
+// REQUIRES: swift_test_mode_optimize_none
+// REQUIRES: objc_interop
+
+// CHECK-NOT: UnknownCode
+
+import def_basic_objc
+
+func test_all() {
+ serialize_all()
+}
diff --git a/test/expr/closure/basic.swift b/test/expr/closure/basic.swift
index e68d9d5..800922b 100644
--- a/test/expr/closure/basic.swift
+++ b/test/expr/closure/basic.swift
@@ -37,7 +37,6 @@
// Closures with argument and parameter names.
func argAndParamNames() -> Int {
let f1: (x: Int, y: Int) -> Int = { (a x, b y) in x + y }
- let _: (x: Int, z: Int) -> Int = { (a x, b y) in x + y }
f1(x: 1, y: 2)
return f1(x: 1, y: 2)
}
diff --git a/tools/SourceKit/lib/Support/Tracing.cpp b/tools/SourceKit/lib/Support/Tracing.cpp
index c50f65c..00321e8 100644
--- a/tools/SourceKit/lib/Support/Tracing.cpp
+++ b/tools/SourceKit/lib/Support/Tracing.cpp
@@ -22,16 +22,16 @@
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// General
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
static std::atomic<bool> tracing_enabled(false);
static std::atomic<uint64_t> operation_id(0);
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Consumers
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
struct TraceConsumerListNode {
trace::TraceConsumer *const Consumer;
TraceConsumerListNode *Next;
@@ -39,9 +39,9 @@
static std::atomic<TraceConsumerListNode *> consumers(nullptr);
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Trace commands
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Is tracing enabled
bool trace::enabled() {
diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp
index 214ae46..d5ee3b2 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp
@@ -97,9 +97,9 @@
sourcekitd_interrupted_connection_handler_t handler) {
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// sourcekitd_request_sync
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
sourcekitd_response_t sourcekitd_send_request_sync(sourcekitd_object_t req) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
index 64b9e43..0e4191f 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
@@ -108,9 +108,9 @@
});
}
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// sourcekitd_request_sync
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
static xpc_connection_t getGlobalConnection();
diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp
index 1d518de..e7be374 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp
@@ -38,9 +38,9 @@
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Generic
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
static std::string trace_root_dir;
@@ -150,9 +150,9 @@
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// State
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
class State {
typedef std::map<uint64_t, OperationInfo> OperationsType;
@@ -307,9 +307,9 @@
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Init & trace
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
void initializeTracing() {
const char *EnvOpt = ::getenv("SOURCEKIT_TRACE_ROOT");
diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp
index 2a767e0..d64dba2 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp
@@ -25,9 +25,9 @@
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// General
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
static std::atomic<uint64_t> operation_id(0);
static uint64_t tracing_session = llvm::sys::TimeValue::now().msec();
@@ -92,9 +92,9 @@
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
// Trace consumer
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
class XpcTraceConsumer : public SourceKit::trace::TraceConsumer {
public:
diff --git a/tools/swift-ide-test/KnownObjCMethods.def b/tools/swift-ide-test/KnownObjCMethods.def
index 2cde179..4ecd53e 100644
--- a/tools/swift-ide-test/KnownObjCMethods.def
+++ b/tools/swift-ide-test/KnownObjCMethods.def
@@ -13,7 +13,7 @@
// This file defines the database of known methods for various
// Objective-C classes, along with flags that describe how their
// import into Swift should be altered.
-// ===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// INSTANCE_METHOD(ClassName, Selector, Options)
// CLASS_METHOD(ClassName, Selector, Options)
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index 354af1b..b9f29ef 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -333,6 +333,11 @@
llvm::cl::desc("Type check the AST"),
llvm::cl::init(false));
+static llvm::cl::opt<bool>
+Playground("playground",
+ llvm::cl::desc("Whether coloring in playground"),
+ llvm::cl::init(false));
+
// AST printing options.
static llvm::cl::opt<bool>
@@ -769,7 +774,8 @@
static int doSyntaxColoring(const CompilerInvocation &InitInvok,
StringRef SourceFilename,
bool TerminalOutput,
- bool RunTypeChecker) {
+ bool RunTypeChecker,
+ bool Playground) {
CompilerInvocation Invocation(InitInvok);
Invocation.addInputFilename(SourceFilename);
Invocation.getLangOptions().DisableAvailabilityChecking = false;
@@ -779,6 +785,7 @@
// Display diagnostics to stderr.
PrintingDiagnosticConsumer PrintDiags;
CI.addDiagnosticConsumer(&PrintDiags);
+ Invocation.getLangOptions().Playground = Playground;
if (CI.setup(Invocation))
return 1;
if (!RunTypeChecker)
@@ -2501,7 +2508,8 @@
ExitCode = doSyntaxColoring(InitInvok,
options::SourceFilename,
options::TerminalOutput,
- options::Typecheck);
+ options::Typecheck,
+ options::Playground);
break;
case ActionType::DumpImporterLookupTable:
diff --git a/utils/GYBUnicodeDataUtils.py b/utils/GYBUnicodeDataUtils.py
index 8f2fdff..2007e37 100644
--- a/utils/GYBUnicodeDataUtils.py
+++ b/utils/GYBUnicodeDataUtils.py
@@ -70,7 +70,7 @@
self.symbolic_values[v] = k
# Load the data file.
- with codecs.open(grapheme_break_property_file_name, encoding=sys.getfilesystemencoding(), errors='strict') as f:
+ with codecs.open(grapheme_break_property_file_name, encoding='utf-8', errors='strict') as f:
for line in f:
# Strip comments.
line = re.sub('#.*', '', line)
@@ -548,7 +548,7 @@
result = []
- with codecs.open(grapheme_break_test_file_name, encoding=sys.getfilesystemencoding(), errors='strict') as f:
+ with codecs.open(grapheme_break_test_file_name, encoding='utf-8', errors='strict') as f:
for line in f:
test = _convert_line(line)
if test:
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 89180b7..e19af46 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -783,7 +783,7 @@
)
;;
*)
- echo "Unknown deployment target"
+ echo "Unknown deployment target: ${t}"
exit 1
;;
esac
diff --git a/utils/name-compression/CBCGen.py b/utils/name-compression/CBCGen.py
index 763ad5d..eb1b36f 100644
--- a/utils/name-compression/CBCGen.py
+++ b/utils/name-compression/CBCGen.py
@@ -82,7 +82,7 @@
first_letter = word[0]
# Create a new entry in the Trie node if needed.
- if not first_letter in self.children:
+ if first_letter not in self.children:
self.children[first_letter] = Trie()
# Insert the rest of the string recursively.
diff --git a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift b/validation-test/IDE/crashers/067-swift-constraints-constraintsystem-resolveoverload.swift
similarity index 69%
copy from validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
copy to validation-test/IDE/crashers/067-swift-constraints-constraintsystem-resolveoverload.swift
index addcef7..cd0e8f9 100644
--- a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
+++ b/validation-test/IDE/crashers/067-swift-constraints-constraintsystem-resolveoverload.swift
@@ -1,3 +1,4 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts
-t=0.#^A^#
\ No newline at end of file
+struct d{func b
+let g=b<a let a=enum b<j where g:p:#^A^#
\ No newline at end of file
diff --git a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift b/validation-test/IDE/crashers/068-swift-typechecker-resolvetypewitness.swift
similarity index 71%
rename from validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
rename to validation-test/IDE/crashers/068-swift-typechecker-resolvetypewitness.swift
index addcef7..9e9c07d 100644
--- a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
+++ b/validation-test/IDE/crashers/068-swift-typechecker-resolvetypewitness.swift
@@ -1,3 +1,5 @@
// RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
// REQUIRES: asserts
-t=0.#^A^#
\ No newline at end of file
+:#^A^#func a
+protocol a{class A:a
+typealias e:A.e
\ No newline at end of file
diff --git a/validation-test/IDE/crashers_fixed/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift b/validation-test/IDE/crashers_fixed/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
new file mode 100644
index 0000000..d5ca599
--- /dev/null
+++ b/validation-test/IDE/crashers_fixed/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+// REQUIRES: asserts
+t=0.#^A^#
\ No newline at end of file
diff --git a/validation-test/SIL/crashers/023-swift-parser-parseexpridentifier.sil b/validation-test/SIL/crashers/023-swift-parser-parseexpridentifier.sil
new file mode 100644
index 0000000..c760397
--- /dev/null
+++ b/validation-test/SIL/crashers/023-swift-parser-parseexpridentifier.sil
@@ -0,0 +1,3 @@
+// RUN: not --crash %target-sil-opt %s
+// REQUIRES: asserts
+enum n{func p<p{p<@convention()>
\ No newline at end of file
diff --git a/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift b/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift
index 67185b2..0262c4b 100644
--- a/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift
+++ b/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift
@@ -4,4 +4,5 @@
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
// Test case found by fuzzing
+// Crash type: memory error ("Invalid read of size 4")
var a{class d{var b=B{}let c=(x:d<T{{}}class B<T where h=d>:a
diff --git a/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift b/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift
index 3c022a1..37c7eae 100644
--- a/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift
+++ b/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift
@@ -4,6 +4,7 @@
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
// Test case found by fuzzing
+// Crash type: memory error ("Invalid read of size 8")
[Void{}}struct A
protocol A{typealias b:A func b
class A<S:e
diff --git a/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift b/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift
index 31c97a9..f235a07 100644
--- a/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift
+++ b/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift
@@ -4,6 +4,7 @@
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
// Test case found by fuzzing
+// Crash type: memory error ("Invalid read of size 8")
class a{
class c
class B:A
diff --git a/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift b/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift
index 2c9a97b..b336d90 100644
--- a/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift
+++ b/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift
@@ -4,4 +4,5 @@
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
// Test case found by fuzzing
+// Crash type: memory error ("Invalid read of size 4")
class n{protocol a:d var d={class b:a
diff --git a/validation-test/compiler_crashers/27443-matchwitness.swift b/validation-test/compiler_crashers/27443-matchwitness.swift
index 667040c..e3abefd 100644
--- a/validation-test/compiler_crashers/27443-matchwitness.swift
+++ b/validation-test/compiler_crashers/27443-matchwitness.swift
@@ -4,6 +4,7 @@
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
// Test case found by fuzzing
+// Crash type: memory error ("Invalid read of size 8")
{e
struct B:a{let t:a}
protocol a{let t:a
diff --git a/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift b/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift
index 4d6f6e5..af1a117 100644
--- a/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift
+++ b/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift
@@ -4,4 +4,5 @@
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
// Test case found by fuzzing
+// Crash type: memory error ("Invalid read of size 8")
class d{let f=a< class a{extension{struct Q<h:a{protocol P{func<
diff --git a/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift b/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift
index 82709da..fe042ce 100644
--- a/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift
+++ b/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift
@@ -4,4 +4,5 @@
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
// Test case found by fuzzing
+// Crash type: memory error ("Invalid read of size 2")
class A{func b->Self{{{}}class B<n{let a=self
diff --git a/validation-test/compiler_crashers/28189-swift-valuedecl-settype.swift b/validation-test/compiler_crashers/28189-swift-valuedecl-settype.swift
new file mode 100644
index 0000000..d444fa9
--- /dev/null
+++ b/validation-test/compiler_crashers/28189-swift-valuedecl-settype.swift
@@ -0,0 +1,8 @@
+// RUN: not --crash %target-swift-frontend %s -parse
+// REQUIRES: asserts
+
+// Distributed under the terms of the MIT license
+// Test case submitted to project by https://github.com/practicalswift (practicalswift)
+// Test case found by fuzzing
+
+func f{{for b{}{String($0
diff --git a/validation-test/compiler_crashers/28190-swift-conformancelookuptable-expandimpliedconformances.swift b/validation-test/compiler_crashers/28190-swift-conformancelookuptable-expandimpliedconformances.swift
new file mode 100644
index 0000000..b8c5465
--- /dev/null
+++ b/validation-test/compiler_crashers/28190-swift-conformancelookuptable-expandimpliedconformances.swift
@@ -0,0 +1,11 @@
+// RUN: not --crash %target-swift-frontend %s -parse
+// REQUIRES: asserts
+
+// Distributed under the terms of the MIT license
+// Test case submitted to project by https://github.com/practicalswift (practicalswift)
+// Test case found by fuzzing
+
+protocol A:A
+protocol a:A
+struct c:a{
+let h=D
diff --git a/validation-test/compiler_crashers/26298-llvm-densemapbase.swift b/validation-test/compiler_crashers_fixed/26298-llvm-densemapbase.swift
similarity index 73%
rename from validation-test/compiler_crashers/26298-llvm-densemapbase.swift
rename to validation-test/compiler_crashers_fixed/26298-llvm-densemapbase.swift
index 5e97bbb..ee2f70a 100644
--- a/validation-test/compiler_crashers/26298-llvm-densemapbase.swift
+++ b/validation-test/compiler_crashers_fixed/26298-llvm-densemapbase.swift
@@ -1,4 +1,4 @@
-// RUN: not --crash %target-swift-frontend %s -emit-silgen
+// RUN: %target-swift-frontend %s -emit-silgen
// Distributed under the terms of the MIT license
// Test case submitted to project by https://github.com/airspeedswift (airspeedswift)