diff --git a/docs/HowToGuides/FAQ.md b/docs/HowToGuides/FAQ.md index e9dce12deca53..4670a199470b2 100644 --- a/docs/HowToGuides/FAQ.md +++ b/docs/HowToGuides/FAQ.md @@ -133,5 +133,49 @@ git rebase --continue ### How do I clean up my git history? -TODO: Link to a beginner-friendly external resource, or (less preferably) -describe basic usage of rebase here. +Git's history can sometimes become cluttered with many small commits. +Fortunately, Git has a feature called `rebase` that allows you to clean up your commit history. +If you want to learn more, +[GitHub - About Git rebase](https://docs.github.com/en/get-started/using-git/about-git-rebase) +provides a comprehensive overview of `rebase`. + +> **Warning** +We suggest considering to `rebase` only those commits that haven't been pushed to a public branch. +Rebasing existing commits would block merging because we don't allow force pushes to the repository. +If you need to tidy up commits that have already been pushed, +it's generally better to use `git revert` for the sake of avoid causing confusion for other developers. + + +Here's a small gist that goes through the basics on how to use it: + +1. Begin an interactive rebase: Use `git rebase -i HEAD~N`, where `N` is the number of commits + from the latest one you want to edit. This will open a text editor, + listing the last `N` commits with the word "pick" next to each one. + + ```sh + git rebase -i HEAD~N + ``` + +2. Edit the commits: Replace "pick" with the operation you want to perform on the commit: + + - `reword`: Change the commit message. + - `edit`: Amend the commit. + - `squash`: Combine the commit with the previous one. + - `fixup`: Similar to `squash`, but discard this commit's log message. + - `drop`: Remove the commit. + +3. Save and exit: After saving and closing the file, git will execute each operation. + If you selected `reword`, `edit`, or `squash`, git will pause and give you a chance + to alter the commit message or the commit itself. + + ```sh + git commit --amend + ``` + +4. Continue the rebase: Once you're done with each commit, you can continue the rebase + using `git rebase --continue`. If you want to abort the rebase at any point, + you can use `git rebase --abort`. + + ```sh + git rebase --continue + ``` diff --git a/docs/HowToGuides/GettingStarted.md b/docs/HowToGuides/GettingStarted.md index 1c60f3c384091..e4c3c18b7e28b 100644 --- a/docs/HowToGuides/GettingStarted.md +++ b/docs/HowToGuides/GettingStarted.md @@ -66,6 +66,11 @@ toolchain as a one-off, there are a couple of differences: mkdir swift-project cd swift-project ``` + + > **Warning** + > Make sure the absolute path to your `swift-project` directory **does not** contain spaces, + since that might cause issues during the build step. + 2. Clone the sources: - Via SSH (recommended): If you plan on contributing regularly, cloning over SSH provides a better @@ -121,9 +126,6 @@ toolchain as a one-off, there are a couple of differences: - If `update-checkout` failed, double-check that the absolute path to your working directory does not have non-ASCII characters. -- If `update-checkout` failed and the absolute path to your working directory - had spaces in it, please [file a bug report][Swift Issues] and change the path - to work around it. - Before running `update-checkout`, double-check that `swift` is the only repository inside the `swift-project` directory. Otherwise, `update-checkout` may not clone the necessary dependencies. diff --git a/docs/SIL.rst b/docs/SIL.rst index 61ba52a31fa65..9ca6a73018624 100644 --- a/docs/SIL.rst +++ b/docs/SIL.rst @@ -3475,8 +3475,6 @@ A value ``%1`` is said to be *value-dependent* on a value ``%0`` if: with ``tuple_extract``, ``struct_extract``, ``unchecked_enum_data``, ``select_enum``, or ``select_enum_addr``. -- ``%1`` is the result of ``select_value`` and ``%0`` is one of the cases. - - ``%1`` is a basic block parameter and ``%0`` is the corresponding argument from a branch to that block. @@ -7949,45 +7947,6 @@ block. If there is a ``default`` basic block, control is transferred to it if the value does not match any of the ``case`` values. It is undefined behavior if the value does not match any cases and no ``default`` branch is provided. -select_value -```````````` -:: - - sil-instruction ::= 'select_value' sil-operand sil-select-value-case* - (',' 'default' sil-value)? - ':' sil-type - sil-select-value-case ::= 'case' sil-value ':' sil-value - - - %n = select_value %0 : $U, \ - case %c1: %r1, \ - case %c2: %r2, /* ... */ \ - default %r3 : $T - - // $U must be a builtin type. Only integers types are supported currently. - // c1, c2, etc must be of type $U - // %r1, %r2, %r3, etc. must have type $T - // %n has type $T - -Selects one of the "case" or "default" operands based on the case of a -value. This is equivalent to a trivial `switch_value`_ branch sequence:: - - entry: - switch_value %0 : $U, \ - case %c1: bb1, \ - case %c2: bb2, /* ... */ \ - default bb_default - bb1: - br cont(%r1 : $T) // value for %c1 - bb2: - br cont(%r2 : $T) // value for %c2 - bb_default: - br cont(%r3 : $T) // value for default - cont(%n : $T): - // use argument %n - -but turns the control flow dependency into a data flow dependency. - switch_enum ``````````` :: diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 98a58ce0f3f02..bf40a861dcc70 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1709,6 +1709,11 @@ ERROR(objc_implementation_type_mismatch,none, "header", (DescriptiveDeclKind, ValueDecl *, Type, Type)) +ERROR(objc_implementation_required_attr_mismatch,none, + "%0 %1 %select{should not|should}2 be 'required' to match %0 declared by " + "the header", + (DescriptiveDeclKind, ValueDecl *, bool)) + ERROR(objc_implementation_wrong_objc_name,none, "selector %0 for %1 %2 not found in header; did you mean %3?", (ObjCSelector, DescriptiveDeclKind, ValueDecl *, ObjCSelector)) diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 07094ef23e7bc..b31a31c2e7f66 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -666,9 +666,6 @@ void swift_initStructMetadataWithLayoutString(StructMetadata *self, const uint8_t *fieldTags, uint32_t *fieldOffsets); -SWIFT_RUNTIME_STDLIB_INTERNAL -size_t _swift_refCountBytesForMetatype(const Metadata *type); - enum LayoutStringFlags : uint64_t { Empty = 0, // TODO: Track other useful information tha can be used to optimize layout @@ -688,6 +685,9 @@ inline LayoutStringFlags &operator|=(LayoutStringFlags &a, LayoutStringFlags b) return a = (a | b); } +SWIFT_RUNTIME_STDLIB_INTERNAL +size_t _swift_refCountBytesForMetatype(const Metadata *type); + SWIFT_RUNTIME_STDLIB_INTERNAL void _swift_addRefCountStringForMetatype(uint8_t *layoutStr, size_t &layoutStrOffset, diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index 50dad6f9889c2..9190bdcf1802a 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -1730,14 +1730,6 @@ class SILBuilder { getModule(), CaseCounts, DefaultCount)); } - SelectValueInst *createSelectValue( - SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultResult, - ArrayRef> CaseValuesAndResult) { - return insert(SelectValueInst::create(getSILDebugLocation(Loc), Operand, Ty, - DefaultResult, CaseValuesAndResult, - getModule())); - } - TupleExtractInst *createTupleExtract(SILLocation Loc, SILValue Operand, unsigned FieldNo, SILType ResultTy) { return createTupleExtract(Loc, Operand, FieldNo, ResultTy, diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 08ee52619e548..4fd1633fc64be 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -3251,24 +3251,6 @@ SILCloner::visitSelectEnumAddrInst(SelectEnumAddrInst *Inst) { CaseResults)); } -template -void -SILCloner::visitSelectValueInst(SelectValueInst *Inst) { - SILValue DefaultResult; - if (Inst->hasDefault()) - DefaultResult = getOpValue(Inst->getDefaultResult()); - SmallVector, 8> CaseResults; - for (unsigned i = 0, e = Inst->getNumCases(); i != e; ++i) - CaseResults.push_back(std::make_pair(getOpValue(Inst->getCase(i).first), - getOpValue(Inst->getCase(i).second))); - - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - recordClonedInstruction( - Inst, getBuilder().createSelectValue( - getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), - getOpType(Inst->getType()), DefaultResult, CaseResults)); -} - template void SILCloner::visitDynamicMethodBranchInst( DynamicMethodBranchInst *Inst) { diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 8ded5a9ba68aa..4f598c66fc629 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -1392,7 +1392,6 @@ FirstArgOwnershipForwardingSingleValueInst::classof(SILInstructionKind kind) { case SILInstructionKind::ObjectInst: case SILInstructionKind::EnumInst: case SILInstructionKind::UncheckedEnumDataInst: - case SILInstructionKind::SelectValueInst: case SILInstructionKind::OpenExistentialRefInst: case SILInstructionKind::InitExistentialRefInst: case SILInstructionKind::MarkDependenceInst: @@ -6659,8 +6658,8 @@ class UncheckedTakeEnumDataAddrInst } }; -// Abstract base class of all select instructions like select_enum, -// select_value, etc. The template parameter represents a type of case values +// Abstract base class of all select instructions like select_enum. +// The template parameter represents a type of case values // to be compared with the operand of a select instruction. // // Subclasses must provide tail allocated storage. @@ -6878,50 +6877,6 @@ class SelectEnumAddrInst final ProfileCounter DefaultCount); }; -/// Select on a value of a builtin integer type. -/// -/// There is 'the' operand, followed by pairs of operands for each case, -/// followed by an optional default operand. -class SelectValueInst final - : public InstructionBaseWithTrailingOperands< - SILInstructionKind::SelectValueInst, SelectValueInst, - SelectInstBase> { - friend SILBuilder; - - SelectValueInst(SILDebugLocation DebugLoc, SILValue Operand, SILType Type, - SILValue DefaultResult, - ArrayRef CaseValuesAndResults); - - static SelectValueInst * - create(SILDebugLocation DebugLoc, SILValue Operand, SILType Type, - SILValue DefaultValue, - ArrayRef> CaseValues, SILModule &M); - -public: - std::pair - getCase(unsigned i) const { - auto cases = getAllOperands().slice(1); - return {cases[i*2].get(), cases[i*2+1].get()}; - } - - unsigned getNumCases() const { - // Ignore the first non-case operand. - auto count = getAllOperands().size() - 1; - // This implicitly ignore the optional default operand. - return count / 2; - } - - bool hasDefault() const { - // If the operand count is even, then we have a default value. - return (getAllOperands().size() & 1) == 0; - } - - SILValue getDefaultResult() const { - assert(hasDefault() && "doesn't have a default"); - return getAllOperands().back().get(); - } -}; - /// MetatypeInst - Represents the production of an instance of a given metatype /// named statically. class MetatypeInst final diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def index 31eec73a10239..6b7a76ad47dd0 100644 --- a/include/swift/SIL/SILNodes.def +++ b/include/swift/SIL/SILNodes.def @@ -609,8 +609,6 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction) SingleValueInstruction, None, DoesNotRelease) SINGLE_VALUE_INST(SelectEnumAddrInst, select_enum_addr, SingleValueInstruction, MayRead, DoesNotRelease) - SINGLE_VALUE_INST(SelectValueInst, select_value, - SingleValueInstruction, None, DoesNotRelease) // Protocol and Protocol Composition Types SINGLE_VALUE_INST(InitExistentialAddrInst, init_existential_addr, diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index dad6ac28e28e0..f927540fadc98 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -1300,7 +1300,6 @@ class IRGenSILFunction : void visitInitEnumDataAddrInst(InitEnumDataAddrInst *i); void visitSelectEnumInst(SelectEnumInst *i); void visitSelectEnumAddrInst(SelectEnumAddrInst *i); - void visitSelectValueInst(SelectValueInst *i); void visitUncheckedEnumDataInst(UncheckedEnumDataInst *i); void visitUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *i); void visitInjectEnumAddrInst(InjectEnumAddrInst *i); @@ -4658,27 +4657,6 @@ void IRGenSILFunction::visitSelectEnumAddrInst(SelectEnumAddrInst *inst) { // emitBBMapForSelectEnum set up a phi node to receive the result. Builder.SetInsertPoint(contBB); } - - setLoweredValue(inst, - getLoweredValueForSelect(*this, result, inst)); -} - -void IRGenSILFunction::visitSelectValueInst(SelectValueInst *inst) { - Explosion value = getLoweredExplosion(inst->getOperand()); - - // Map the SIL dest bbs to their LLVM bbs. - SmallVector, 4> dests; - llvm::BasicBlock *defaultDest; - Explosion result; - auto *contBB = emitBBMapForSelect(*this, result, dests, defaultDest, inst); - - // Emit the dispatch. - emitSwitchValueDispatch(*this, inst->getOperand()->getType(), value, dests, - defaultDest); - - // emitBBMapForSelectEnum set up a continuation block and phi nodes to - // receive the result. - Builder.SetInsertPoint(contBB); setLoweredValue(inst, getLoweredValueForSelect(*this, result, inst)); diff --git a/lib/SIL/IR/OperandOwnership.cpp b/lib/SIL/IR/OperandOwnership.cpp index 8689457c3085d..4e9f5269ed8a1 100644 --- a/lib/SIL/IR/OperandOwnership.cpp +++ b/lib/SIL/IR/OperandOwnership.cpp @@ -188,8 +188,6 @@ OPERAND_OWNERSHIP(TrivialUse, PointerToAddress) OPERAND_OWNERSHIP(TrivialUse, ProjectBlockStorage) OPERAND_OWNERSHIP(TrivialUse, RawPointerToRef) OPERAND_OWNERSHIP(TrivialUse, SelectEnumAddr) -// select_value is only supported for integer types currently. -OPERAND_OWNERSHIP(TrivialUse, SelectValue) OPERAND_OWNERSHIP(TrivialUse, StructElementAddr) OPERAND_OWNERSHIP(TrivialUse, SwitchEnumAddr) OPERAND_OWNERSHIP(TrivialUse, SwitchValue) diff --git a/lib/SIL/IR/SILInstruction.cpp b/lib/SIL/IR/SILInstruction.cpp index 3667858acc13e..2c21e4876497a 100644 --- a/lib/SIL/IR/SILInstruction.cpp +++ b/lib/SIL/IR/SILInstruction.cpp @@ -688,25 +688,6 @@ namespace { return visitSelectEnumInstBase(RHS); } - bool visitSelectValueInst(const SelectValueInst *RHS) { - // Check that the instructions match cases in the same order. - auto *X = cast(LHS); - - if (X->getNumCases() != RHS->getNumCases()) - return false; - if (X->hasDefault() != RHS->hasDefault()) - return false; - - for (unsigned i = 0, e = X->getNumCases(); i < e; ++i) { - if (X->getCase(i).first != RHS->getCase(i).first) - return false; - if (X->getCase(i).second != RHS->getCase(i).second) - return false; - } - - return true; - } - // Conversion instructions. // All of these just return true as they have already had their // operands and types checked diff --git a/lib/SIL/IR/SILInstructions.cpp b/lib/SIL/IR/SILInstructions.cpp index e42d9e4ae1658..75f2911e9c79c 100644 --- a/lib/SIL/IR/SILInstructions.cpp +++ b/lib/SIL/IR/SILInstructions.cpp @@ -1975,35 +1975,6 @@ SwitchValueInst *SwitchValueInst::create( return ::new (buf) SwitchValueInst(Loc, Operand, DefaultBB, Cases, BBs); } -SelectValueInst::SelectValueInst(SILDebugLocation DebugLoc, SILValue Operand, - SILType Type, SILValue DefaultResult, - ArrayRef CaseValuesAndResults) - : InstructionBaseWithTrailingOperands(Operand, CaseValuesAndResults, - DebugLoc, Type) {} - -SelectValueInst * -SelectValueInst::create(SILDebugLocation Loc, SILValue Operand, SILType Type, - SILValue DefaultResult, - ArrayRef> CaseValues, - SILModule &M) { - // Allocate enough room for the instruction with tail-allocated data for all - // the case values and the SILSuccessor arrays. There are `CaseBBs.size()` - // SILValues and `CaseBBs.size() + (DefaultBB ? 1 : 0)` successors. - SmallVector CaseValuesAndResults; - for (auto pair : CaseValues) { - CaseValuesAndResults.push_back(pair.first); - CaseValuesAndResults.push_back(pair.second); - } - - if ((bool)DefaultResult) - CaseValuesAndResults.push_back(DefaultResult); - - auto Size = totalSizeToAlloc(CaseValuesAndResults.size() + 1); - auto Buf = M.allocateInst(Size, alignof(SelectValueInst)); - return ::new (Buf) - SelectValueInst(Loc, Operand, Type, DefaultResult, CaseValuesAndResults); -} - template SELECT_ENUM_INST *SelectEnumInstBase::createSelectEnum( SILDebugLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultValue, diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index 1ccf6a64051f1..b8b49b32bb6ea 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -2712,21 +2712,6 @@ class SILPrinter : public SILInstructionVisitor { printSelectEnumInst(SEI); } - void visitSelectValueInst(SelectValueInst *SVI) { - *this << getIDAndType(SVI->getOperand()); - - for (unsigned i = 0, e = SVI->getNumCases(); i < e; ++i) { - SILValue casevalue; - SILValue result; - std::tie(casevalue, result) = SVI->getCase(i); - *this << ", case " << Ctx.getID(casevalue) << ": " << Ctx.getID(result); - } - if (SVI->hasDefault()) - *this << ", default " << Ctx.getID(SVI->getDefaultResult()); - - *this << " : " << SVI->getType(); - } - void visitDynamicMethodBranchInst(DynamicMethodBranchInst *DMBI) { *this << getIDAndType(DMBI->getOperand()) << ", " << DMBI->getMember() << ", " << Ctx.getID(DMBI->getHasMethodBB()) << ", " diff --git a/lib/SIL/IR/ValueOwnership.cpp b/lib/SIL/IR/ValueOwnership.cpp index d19d1e970a4b0..55050a00d54a2 100644 --- a/lib/SIL/IR/ValueOwnership.cpp +++ b/lib/SIL/IR/ValueOwnership.cpp @@ -134,7 +134,6 @@ CONSTANT_OWNERSHIP_INST(None, RefElementAddr) CONSTANT_OWNERSHIP_INST(None, RefTailAddr) CONSTANT_OWNERSHIP_INST(None, RefToRawPointer) CONSTANT_OWNERSHIP_INST(None, SelectEnumAddr) -CONSTANT_OWNERSHIP_INST(None, SelectValue) CONSTANT_OWNERSHIP_INST(None, StringLiteral) CONSTANT_OWNERSHIP_INST(None, StructElementAddr) CONSTANT_OWNERSHIP_INST(None, SuperMethod) diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index c2d9693356487..778607a71fdfd 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -6098,66 +6098,6 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B, ResultVal = B.createSwitchValue(InstLoc, Val, DefaultBB, CaseBBs); break; } - case SILInstructionKind::SelectValueInst: { - if (parseTypedValueRef(Val, B)) - return true; - - SmallVector, 4> - CaseValueAndResultNames; - Optional DefaultResultName; - while (P.consumeIf(tok::comma)) { - Identifier BBName; - SourceLoc BBLoc; - // Parse 'default' sil-value. - UnresolvedValueName tmp; - if (P.consumeIf(tok::kw_default)) { - if (parseValueName(tmp)) - return true; - DefaultResultName = tmp; - break; - } - - // Parse 'case' sil-decl-ref ':' sil-value. - if (P.consumeIf(tok::kw_case)) { - UnresolvedValueName casevalue; - parseValueName(casevalue); - P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":"); - parseValueName(tmp); - CaseValueAndResultNames.push_back(std::make_pair(casevalue, tmp)); - continue; - } - - P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "case or default"); - return true; - } - - if (!DefaultResultName) { - P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "default"); - return true; - } - - // Parse the type of the result operands. - SILType ResultType; - if (P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") || - parseSILType(ResultType) || parseSILDebugLocation(InstLoc, B)) - return true; - - // Resolve the results. - SmallVector, 4> CaseValues; - SILValue DefaultValue; - if (DefaultResultName) - DefaultValue = - getLocalValue(*DefaultResultName, ResultType, InstLoc, B); - SILType ValType = Val->getType(); - for (auto &caseName : CaseValueAndResultNames) - CaseValues.push_back(std::make_pair( - getLocalValue(caseName.first, ValType, InstLoc, B), - getLocalValue(caseName.second, ResultType, InstLoc, B))); - - ResultVal = B.createSelectValue(InstLoc, Val, ResultType, DefaultValue, - CaseValues); - break; - } case SILInstructionKind::DeinitExistentialAddrInst: { if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B)) return true; diff --git a/lib/SIL/Utils/InstructionUtils.cpp b/lib/SIL/Utils/InstructionUtils.cpp index e1c1ba61b4b35..ed7c176f241f9 100644 --- a/lib/SIL/Utils/InstructionUtils.cpp +++ b/lib/SIL/Utils/InstructionUtils.cpp @@ -512,7 +512,6 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::UncheckedTakeEnumDataAddrInst: case SILInstructionKind::SelectEnumInst: case SILInstructionKind::SelectEnumAddrInst: - case SILInstructionKind::SelectValueInst: case SILInstructionKind::OpenExistentialMetatypeInst: case SILInstructionKind::OpenExistentialBoxInst: case SILInstructionKind::OpenExistentialValueInst: diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 919535d744857..4cedea8007dce 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -4933,55 +4933,6 @@ class SILVerifier : public SILVerifierBase { "switch_value default destination cannot take arguments"); } - void checkSelectValueCases(SelectValueInst *I) { - struct APIntCmp { - bool operator()(const APInt &a, const APInt &b) const { - return a.ult(b); - }; - }; - - llvm::SmallSet seenCaseValues; - - // Verify the set of cases we dispatch on. - for (unsigned i = 0, e = I->getNumCases(); i < e; ++i) { - SILValue casevalue; - SILValue result; - std::tie(casevalue, result) = I->getCase(i); - - if (!isa(casevalue)) { - auto *il = dyn_cast(casevalue); - require(il, - "select_value case operands should refer to integer literals"); - APInt elt = il->getValue(); - - require(!seenCaseValues.count(elt), - "select_value dispatches on same case value more than once"); - - seenCaseValues.insert(elt); - } - - requireSameType(I->getOperand()->getType(), casevalue->getType(), - "select_value case value must match type of operand"); - - // The result value must match the type of the instruction. - requireSameType(result->getType(), I->getType(), - "select_value case result must match type of instruction"); - } - - require(I->hasDefault(), - "select_value should always have a default"); - requireSameType(I->getDefaultResult()->getType(), - I->getType(), - "select_value default operand must match type of instruction"); - } - - void checkSelectValueInst(SelectValueInst *SVI) { - require(SVI->getOperand()->getType().isObject(), - "select_value operand must be an object"); - - checkSelectValueCases(SVI); - } - void checkSwitchEnumInst(SwitchEnumInst *switchEnum) { require(switchEnum->getOperand()->getType().isObject(), "switch_enum operand must be an object"); diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp index 248901f9b6cf7..e8585b7766637 100644 --- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp +++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp @@ -3130,11 +3130,6 @@ class UseRewriter : SILInstructionVisitor { // opaque value rewriting. } - void visitSelectValueInst(SelectValueInst *selectInst) { - // FIXME: Unimplemented - llvm::report_fatal_error("Unimplemented SelectValue use."); - } - void visitStoreBorrowInst(StoreBorrowInst *sbi) { auto addr = addrMat.materializeAddress(use->get()); SmallVector uses(sbi->getUses()); diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 12cb54a377583..a3728472809cd 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -2312,6 +2312,19 @@ void LifetimeChecker::handleSelfInitUse(unsigned UseID) { } } +// In case of `var` initializations, SILGen creates a dynamic begin/end_access +// pair around the initialization store. If it's an initialization (and not +// a re-assign) it's guaranteed that it's an exclusive access and we can +// convert the access to an `[init] [static]` access. +static void setStaticInitAccess(SILValue memoryAddress) { + if (auto *ba = dyn_cast(memoryAddress)) { + if (ba->getEnforcement() == SILAccessEnforcement::Dynamic) { + ba->setEnforcement(SILAccessEnforcement::Static); + if (ba->getAccessKind() == SILAccessKind::Modify) + ba->setAccessKind(SILAccessKind::Init); + } + } +} /// updateInstructionForInitState - When an instruction being analyzed moves /// from being InitOrAssign to some concrete state, update it for that state. @@ -2336,6 +2349,8 @@ void LifetimeChecker::updateInstructionForInitState(unsigned UseID) { assert(!CA->isInitializationOfDest() && "should not modify copy_addr that already knows it is initialized"); CA->setIsInitializationOfDest(InitKind); + if (InitKind == IsInitialization) + setStaticInitAccess(CA->getDest()); return; } @@ -2382,6 +2397,7 @@ void LifetimeChecker::updateInstructionForInitState(unsigned UseID) { MarkMustCheckInst::CheckKind::InitableButNotConsumable); } } + setStaticInitAccess(AI->getDest()); } return; diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp index 92b594f1bcf63..23022c3c54ea2 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyWrappedTypeEliminator.cpp @@ -183,7 +183,6 @@ struct SILMoveOnlyWrappedTypeEliminatorVisitor NO_UPDATE_NEEDED(DestructureTuple) NO_UPDATE_NEEDED(DestructureStruct) NO_UPDATE_NEEDED(SelectEnum) - NO_UPDATE_NEEDED(SelectValue) NO_UPDATE_NEEDED(MarkDependence) NO_UPDATE_NEEDED(DestroyAddr) NO_UPDATE_NEEDED(DeallocStack) diff --git a/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp b/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp index 166bb585b7caf..19de7a5a7df00 100644 --- a/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp +++ b/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp @@ -190,9 +190,6 @@ struct OwnershipModelEliminatorVisitor #define HANDLE_FORWARDING_INST(Cls) \ bool visit##Cls##Inst(Cls##Inst *i) { \ - if (isa(i)) { \ - return true; \ - } \ OwnershipForwardingMixin::get(i)->setForwardingOwnershipKind( \ OwnershipKind::None); \ return true; \ @@ -212,7 +209,6 @@ struct OwnershipModelEliminatorVisitor HANDLE_FORWARDING_INST(Enum) HANDLE_FORWARDING_INST(UncheckedEnumData) HANDLE_FORWARDING_INST(SelectEnum) - HANDLE_FORWARDING_INST(SelectValue) HANDLE_FORWARDING_INST(OpenExistentialRef) HANDLE_FORWARDING_INST(InitExistentialRef) HANDLE_FORWARDING_INST(MarkDependence) diff --git a/lib/SILOptimizer/SemanticARC/SemanticARCOptVisitor.h b/lib/SILOptimizer/SemanticARC/SemanticARCOptVisitor.h index 469ea26b90878..fc6fa0d47d6ee 100644 --- a/lib/SILOptimizer/SemanticARC/SemanticARCOptVisitor.h +++ b/lib/SILOptimizer/SemanticARC/SemanticARCOptVisitor.h @@ -183,7 +183,6 @@ struct LLVM_LIBRARY_VISIBILITY SemanticARCOptVisitor FORWARDING_INST(UncheckedEnumData) FORWARDING_INST(MarkUninitialized) FORWARDING_INST(SelectEnum) - FORWARDING_INST(SelectValue) FORWARDING_INST(DestructureStruct) FORWARDING_INST(DestructureTuple) FORWARDING_INST(TupleExtract) diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp index 36bd2c12756f1..b436a52e17591 100644 --- a/lib/SILOptimizer/Transforms/CSE.cpp +++ b/lib/SILOptimizer/Transforms/CSE.cpp @@ -457,22 +457,6 @@ class HashVisitor : public SILInstructionVisitor { return visitSelectEnumInstBase(X); } - hash_code visitSelectValueInst(SelectValueInst *X) { - auto hash = llvm::hash_combine( - X->getKind(), tryLookThroughOwnershipInsts(&X->getAllOperands()[0]), - X->getType(), X->hasDefault()); - - for (unsigned i = 0, e = X->getNumCases(); i < e; ++i) { - hash = llvm::hash_combine(hash, X->getCase(i).first, - X->getCase(i).second); - } - - if (X->hasDefault()) - hash = llvm::hash_combine(hash, X->getDefaultResult()); - - return hash; - } - hash_code visitWitnessMethodInst(WitnessMethodInst *X) { if (X->getFunction()->hasOwnership()) { auto TransformedOpValues = @@ -1241,7 +1225,6 @@ bool CSE::canHandle(SILInstruction *Inst) { case SILInstructionKind::ObjCMetatypeToObjectInst: case SILInstructionKind::ObjCExistentialMetatypeToObjectInst: case SILInstructionKind::SelectEnumInst: - case SILInstructionKind::SelectValueInst: case SILInstructionKind::RefToBridgeObjectInst: case SILInstructionKind::BridgeObjectToRefInst: case SILInstructionKind::BridgeObjectToWordInst: diff --git a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp index ce64569b4247d..03f3c88746186 100644 --- a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp @@ -280,6 +280,9 @@ static bool canZapInstruction(SILInstruction *Inst, bool acceptRefCountInsts, if (isa(Inst)) return true; + if (isa(Inst) || isa(Inst)) + return true; + // If Inst does not read or write to memory, have side effects, and is not a // terminator, we can zap it. if (!Inst->mayHaveSideEffects() && !Inst->mayReadFromMemory() && diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp index 03747a93adfc4..1fb46e3ee42c0 100644 --- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp +++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp @@ -3534,238 +3534,6 @@ static bool simplifySwitchEnumToSelectEnum(SILBasicBlock *BB, unsigned ArgNum, } /// Collected information for a select_value case or default case. -struct CaseInfo { - /// The input value or null if it is the default case. - IntegerLiteralInst *Literal = nullptr; - - /// The result value. - SingleValueInstruction *Result = nullptr; - - /// The block which contains the cond_br of the input value comparison - /// or the block which assigns the default value. - SILBasicBlock *CmpOrDefault = nullptr; -}; - -/// Get information about a potential select_value case (or default). -/// \p Input is set to the common input value. -/// \p Pred is the predecessor block of the last merge block of the CFG pattern. -/// \p ArgNum is the index of the argument passed to the merge block. -CaseInfo getCaseInfo(SILValue &Input, SILBasicBlock *Pred, unsigned ArgNum) { - - CaseInfo CaseInfo; - - auto *TI = Pred->getTerminator(); - if (!isa(TI)) - return CaseInfo; - - // Find the Nth argument passed to BB. - auto Arg = TI->getOperand(ArgNum); - - // Currently we only accept enums as result values. - auto *EI2 = dyn_cast(Arg); - if (!EI2) - return CaseInfo; - - if (EI2->hasOperand()) { - // ... or enums with enum data. This is exactly the pattern for an enum - // with integer raw value initialization. - auto *EI1 = dyn_cast(EI2->getOperand()); - if (!EI1) - return CaseInfo; - - // But not enums with enums with data. - if (EI1->hasOperand()) - return CaseInfo; - } - - // Check if we come to the Pred block by comparing the input value to a - // constant. - SILBasicBlock *CmpBlock = Pred->getSinglePredecessorBlock(); - if (!CmpBlock) - return CaseInfo; - - auto *CmpInst = dyn_cast(CmpBlock->getTerminator()); - if (!CmpInst) - return CaseInfo; - - auto *CondInst = dyn_cast(CmpInst->getCondition()); - if (!CondInst) - return CaseInfo; - - if (!CondInst->getName().str().startswith("cmp_eq")) - return CaseInfo; - - auto CondArgs = CondInst->getArguments(); - assert(CondArgs.size() == 2); - - SILValue Arg1 = CondArgs[0]; - SILValue Arg2 = CondArgs[1]; - - if (isa(Arg1)) - std::swap(Arg1, Arg2); - - auto *CmpVal = dyn_cast(Arg2); - if (!CmpVal) - return CaseInfo; - - SILBasicBlock *FalseBB = CmpInst->getFalseBB(); - if (!FalseBB) - return CaseInfo; - - // Check for a common input value. - if (Input && Input != Arg1) - return CaseInfo; - - Input = Arg1; - CaseInfo.Result = EI2; - if (CmpInst->getTrueBB() == Pred) { - // This is a case for the select_value. - CaseInfo.Literal = CmpVal; - CaseInfo.CmpOrDefault = CmpBlock; - } else { - // This is the default for the select_value. - CaseInfo.CmpOrDefault = Pred; - } - - return CaseInfo; -} - -/// Move an instruction which is an operand to the new SelectValueInst to its -/// correct place. -/// Either the instruction is somewhere inside the CFG pattern, then we move it -/// up, immediately before the SelectValueInst in the pattern's dominating -/// entry block. Or it is somewhere above the entry block, then we can leave the -/// instruction there. -void moveIfNotDominating(SILInstruction *I, SILInstruction *InsertPos, - DominanceInfo *DT) { - SILBasicBlock *InstBlock = I->getParent(); - SILBasicBlock *InsertBlock = InsertPos->getParent(); - if (!DT->dominates(InstBlock, InsertBlock)) { - assert(DT->dominates(InsertBlock, InstBlock)); - LLVM_DEBUG(llvm::dbgs() << " move " << *I); - I->moveBefore(InsertPos); - } -} - -/// Simplify a pattern of integer compares to a select_value. -/// \code -/// if input == 1 { -/// result = Enum.A -/// } else if input == 2 { -/// result = Enum.B -/// ... -/// } else { -/// result = Enum.X -/// } -/// \endcode -/// Currently this only works if the input value is an integer and the result -/// value is an enum. -/// \p MergeBlock The "last" block which contains an argument in which all -/// result values are merged. -/// \p ArgNum The index of the block argument which is the result value. -/// \p DT The dominance info. -/// \return Returns true if a select_value is generated. -bool simplifyToSelectValue(SILBasicBlock *MergeBlock, unsigned ArgNum, - DominanceInfo *DT) { - if (!DT) - return false; - - // Collect all case infos from the merge block's predecessors. - BasicBlockSet FoundCmpBlocks(MergeBlock->getParent()); - SmallVector CaseInfos; - SILValue Input; - for (auto *Pred : MergeBlock->getPredecessorBlocks()) { - CaseInfo CaseInfo = getCaseInfo(Input, Pred, ArgNum); - if (!CaseInfo.Result) - return false; - - FoundCmpBlocks.insert(CaseInfo.CmpOrDefault); - CaseInfos.push_back(CaseInfo); - } - - SmallVector, 8> Cases; - llvm::SmallDenseMap CaseLiteralsToResultMap; - SILValue defaultResult; - - // The block of the first input value compare. It dominates all other blocks - // in this CFG pattern. - SILBasicBlock *dominatingBlock = nullptr; - - // Build the cases for the SelectValueInst and find the first dominatingBlock. - for (auto &CaseInfo : CaseInfos) { - if (CaseInfo.Literal) { - auto *BrInst = cast(CaseInfo.CmpOrDefault->getTerminator()); - if (!FoundCmpBlocks.contains(BrInst->getFalseBB())) - return false; - // Ignore duplicate cases - if (CaseLiteralsToResultMap.find(CaseInfo.Literal) == - CaseLiteralsToResultMap.end()) { - CaseLiteralsToResultMap.insert({CaseInfo.Literal, CaseInfo.Result}); - Cases.push_back({CaseInfo.Literal, CaseInfo.Result}); - } else { - // Check if the result value matches - EnumInst *PrevResult = - dyn_cast(CaseLiteralsToResultMap[CaseInfo.Literal]); - assert(PrevResult && "Prev. case result is not an EnumInst"); - auto *CurrResult = dyn_cast(CaseInfo.Result); - assert(CurrResult && "Curr. case result is not an EnumInst"); - if (PrevResult->getElement() != CurrResult->getElement()) { - // result value does not match - bail - return false; - } - } - SILBasicBlock *Pred = CaseInfo.CmpOrDefault->getSinglePredecessorBlock(); - if (!Pred || !FoundCmpBlocks.contains(Pred)) { - // There may be only a single block whose predecessor we didn't see. And - // this is the entry block to the CFG pattern. - if (dominatingBlock) - return false; - dominatingBlock = CaseInfo.CmpOrDefault; - } - } else { - if (defaultResult) - return false; - defaultResult = CaseInfo.Result; - } - } - if (!defaultResult) - return false; - - if (!dominatingBlock) - return false; - - // Generate the select_value right before the first cond_br of the pattern. - SILInstruction *insertPos = dominatingBlock->getTerminator(); - SILBuilder B(insertPos); - - // Move all needed operands to a place where they dominate the select_value. - for (auto &CaseInfo : CaseInfos) { - if (CaseInfo.Literal) - moveIfNotDominating(CaseInfo.Literal, insertPos, DT); - auto *EI2 = dyn_cast(CaseInfo.Result); - assert(EI2); - - if (EI2->hasOperand()) { - auto *EI1 = dyn_cast(EI2->getOperand()); - assert(EI1); - assert(!EI1->hasOperand()); - - moveIfNotDominating(EI1, insertPos, DT); - } - moveIfNotDominating(EI2, insertPos, DT); - } - - SILArgument *bbArg = MergeBlock->getArgument(ArgNum); - auto SelectInst = B.createSelectValue(dominatingBlock->getTerminator()->getLoc(), - Input, bbArg->getType(), - defaultResult, Cases); - - bbArg->replaceAllUsesWith(SelectInst); - LLVM_DEBUG(llvm::dbgs() << "convert if-structure to " << *SelectInst); - - return true; -} - bool SimplifyCFG::simplifyBlockArgs() { auto *DA = PM->getAnalysis(); @@ -3785,10 +3553,6 @@ bool SimplifyCFG::simplifyBlockArgs() { bool SimplifyCFG::simplifyArgument(SILBasicBlock *BB, unsigned i) { auto *A = BB->getArgument(i); - // Try to create a select_value. - if (simplifyToSelectValue(BB, i, DT)) - return true; - // If we are reading an i1, then check to see if it comes from // a switch_enum. If so, we may be able to lower this sequence to // a select_enum. diff --git a/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp b/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp index c3df1681f59ba..c269fd2955fb5 100644 --- a/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp +++ b/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp @@ -255,7 +255,6 @@ static bool hasOpaqueArchetype(TypeExpansionContext context, case SILInstructionKind::UncheckedTakeEnumDataAddrInst: case SILInstructionKind::SelectEnumInst: case SILInstructionKind::SelectEnumAddrInst: - case SILInstructionKind::SelectValueInst: case SILInstructionKind::InitExistentialAddrInst: case SILInstructionKind::InitExistentialValueInst: case SILInstructionKind::OpenExistentialAddrInst: diff --git a/lib/SILOptimizer/Utils/CanonicalizeBorrowScope.cpp b/lib/SILOptimizer/Utils/CanonicalizeBorrowScope.cpp index 59251e49fd968..1d38744d5c91e 100644 --- a/lib/SILOptimizer/Utils/CanonicalizeBorrowScope.cpp +++ b/lib/SILOptimizer/Utils/CanonicalizeBorrowScope.cpp @@ -81,11 +81,11 @@ static void deleteCopyAndMoveChain(SILValue v, InstructionDeleter &deleter) { /// AllArgOwnershipForwardingSingleValueInst /// (Struct, Tuple) /// FirstArgOwnershipForwardingSingleValueInst -/// (Object, Enum, UncheckedEnumData, SelectValue, Open/InitExistentialRef, +/// (Object, Enum, UncheckedEnumData, Open/InitExistentialRef, /// MarkDependence) /// /// TODO: -/// Enum, SelectValue, InitExistential, MarkDependence +/// Enum, InitExistential, MarkDependence /// Struct, Tuple /// SelectEnum, SwitchEnum, CheckCastBranch bool CanonicalizeBorrowScope::isRewritableOSSAForward(SILInstruction *inst) { diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp index c9008d1388410..ee0974a440570 100644 --- a/lib/SILOptimizer/Utils/SILInliner.cpp +++ b/lib/SILOptimizer/Utils/SILInliner.cpp @@ -1110,7 +1110,6 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) { case SILInstructionKind::InitBlockStorageHeaderInst: case SILInstructionKind::SelectEnumAddrInst: case SILInstructionKind::SelectEnumInst: - case SILInstructionKind::SelectValueInst: case SILInstructionKind::KeyPathInst: case SILInstructionKind::GlobalValueInst: case SILInstructionKind::DifferentiableFunctionInst: diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 9d1d99b2b2114..4c81fe8540fae 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2699,7 +2699,7 @@ void AttributeChecker::visitRequiredAttr(RequiredAttr *attr) { // The constructor must be declared within the class itself. // FIXME: Allow an SDK overlay to add a required initializer to a class // defined in Objective-C - if (!isa(ctor->getDeclContext()) && + if (!isa(ctor->getDeclContext()->getImplementedObjCContext()) && !isObjCClassExtensionInOverlay(ctor->getDeclContext())) { diagnose(ctor, diag::required_initializer_in_extension, parentTy) .highlight(attr->getLocation()); diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 2a0972ab954d7..d70314b5a1055 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -3023,6 +3023,7 @@ class ObjCImplementationChecker { WrongDeclKind, WrongType, WrongWritability, + WrongRequiredAttr, Match, MatchWithExplicitObjCName, @@ -3320,6 +3321,10 @@ class ObjCImplementationChecker { !cast(cand)->isSettable(nullptr)) return MatchOutcome::WrongWritability; + if (auto reqCtor = dyn_cast(req)) + if (reqCtor->isRequired() != cast(cand)->isRequired()) + return MatchOutcome::WrongRequiredAttr; + // If we got here, everything matched. But at what quality? if (explicitObjCName) return MatchOutcome::MatchWithExplicitObjCName; @@ -3407,6 +3412,22 @@ class ObjCImplementationChecker { diagnose(cand, diag::objc_implementation_must_be_settable, cand->getDescriptiveKind(), cand, req->getDescriptiveKind()); return; + + case MatchOutcome::WrongRequiredAttr: { + bool shouldBeRequired = cast(req)->isRequired(); + + auto diag = + diagnose(cand, diag::objc_implementation_required_attr_mismatch, + cand->getDescriptiveKind(), cand, shouldBeRequired); + + if (shouldBeRequired) + diag.fixItInsert(cand->getAttributeInsertionLoc(/*forModifier=*/true), + "required "); + else + diag.fixItRemove(cand->getAttrs().getAttribute() + ->getLocation()); + return; + } } llvm_unreachable("Unknown MatchOutcome"); diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 5308c97b99e37..0e315fa6731df 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -2699,35 +2699,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, ResultInst = Builder.createSwitchValue(Loc, Cond, DefaultBB, CaseBBs); break; } - case SILInstructionKind::SelectValueInst: { - // Format: condition, a list of cases (ValueID + Value ID), - // default value ID. Use SILOneTypeValuesLayout: the type is - // for condition, the list has value for condition, result type, - // hasDefault, default, - // basic block ID, a list of (Value ID, Value ID). - SILValue Cond = getLocalValue( - ListOfValues[0], - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); - - Type ResultLoweredTy = MF->getType(ListOfValues[1]); - SILValueCategory ResultCategory = (SILValueCategory)ListOfValues[2]; - SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory, Fn); - - SILValue DefaultVal = nullptr; - if (ListOfValues[3]) - DefaultVal = getLocalValue(ListOfValues[4], ResultTy); - - SmallVector, 4> CaseValuesAndResults; - for (unsigned I = 5, E = ListOfValues.size(); I < E; I += 2) { - auto CaseValue = getLocalValue(ListOfValues[I], Cond->getType()); - auto Result = getLocalValue(ListOfValues[I+1], ResultTy); - CaseValuesAndResults.push_back({CaseValue, Result}); - } - - ResultInst = Builder.createSelectValue(Loc, Cond, ResultTy, DefaultVal, - CaseValuesAndResults); - break; - } case SILInstructionKind::EnumInst: { // Format: a type, an operand and a decl ID. Use SILTwoOperandsLayout: type, // (DeclID + hasOperand), and an operand. diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 885790790ccd7..12beebdf5f15a 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 791; // HasCxxInteroperability +const uint16_t SWIFTMODULE_VERSION_MINOR = 792; // removed select_value /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 841942ea9afe5..1688270caf2a5 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -1436,38 +1436,6 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) { ListOfValues); break; } - case SILInstructionKind::SelectValueInst: { - // Format: condition, a list of cases (Value ID + Value ID), - // default value ID. Use SILOneTypeValuesLayout: the type is - // for condition, the list has value for condition, result type, - // hasDefault, default - // basic block ID, a list of (Value ID, Value ID). - const SelectValueInst *SVI = cast(&SI); - SmallVector ListOfValues; - ListOfValues.push_back(addValueRef(SVI->getOperand())); - ListOfValues.push_back(S.addTypeRef(SVI->getType().getRawASTType())); - ListOfValues.push_back((unsigned)SVI->getType().getCategory()); - ListOfValues.push_back((unsigned)SVI->hasDefault()); - if (SVI->hasDefault()) { - ListOfValues.push_back(addValueRef(SVI->getDefaultResult())); - } else { - ListOfValues.push_back(0); - } - for (unsigned i = 0, e = SVI->getNumCases(); i < e; ++i) { - SILValue casevalue; - SILValue result; - std::tie(casevalue, result) = SVI->getCase(i); - ListOfValues.push_back(addValueRef(casevalue)); - ListOfValues.push_back(addValueRef(result)); - } - SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord, - SILAbbrCodes[SILOneTypeValuesLayout::Code], - (unsigned)SI.getKind(), - S.addTypeRef(SVI->getOperand()->getType().getRawASTType()), - (unsigned)SVI->getOperand()->getType().getCategory(), - ListOfValues); - break; - } #define UNCHECKED_REF_STORAGE(Name, ...) \ case SILInstructionKind::StrongCopy##Name##ValueInst: #define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ diff --git a/stdlib/public/Cxx/CxxSet.swift b/stdlib/public/Cxx/CxxSet.swift index e3f143da45b60..d468f6deed52e 100644 --- a/stdlib/public/Cxx/CxxSet.swift +++ b/stdlib/public/Cxx/CxxSet.swift @@ -31,7 +31,7 @@ extension CxxSet { /// - Complexity: O(*n*), where *n* is the number of elements in the Swift /// sequence @inlinable - public init(_ sequence: S) where S.Element == Element { + public init(_ sequence: __shared S) where S.Element == Element { self.init() for item in sequence { self.__insertUnsafe(item) diff --git a/stdlib/public/runtime/BytecodeLayouts.cpp b/stdlib/public/runtime/BytecodeLayouts.cpp index a40cab1eb34f5..5e45145f10d0a 100644 --- a/stdlib/public/runtime/BytecodeLayouts.cpp +++ b/stdlib/public/runtime/BytecodeLayouts.cpp @@ -37,26 +37,6 @@ using namespace swift; -static const size_t layoutStringHeaderSize = sizeof(uint64_t) + sizeof(size_t); - -/// Given a pointer and an offset, read the requested data and increment the -/// offset -template -static T readBytes(const uint8_t *typeLayout, size_t &i) { - T returnVal; - memcpy(&returnVal, typeLayout + i, sizeof(T)); - i += sizeof(T); - return returnVal; -} - -/// Given a pointer, a value, and an offset, write the value at the given -/// offset and increment offset by the size of T -template -static void writeBytes(uint8_t *typeLayout, size_t &i, T value) { - memcpy(typeLayout + i, &value, sizeof(T)); - i += sizeof(T); -} - static Metadata *getExistentialTypeMetadata(OpaqueValue *object) { return reinterpret_cast(object)[NumWords_ValueBuffer]; } diff --git a/stdlib/public/runtime/BytecodeLayouts.h b/stdlib/public/runtime/BytecodeLayouts.h index f589352c25a17..f5e487428927b 100644 --- a/stdlib/public/runtime/BytecodeLayouts.h +++ b/stdlib/public/runtime/BytecodeLayouts.h @@ -73,6 +73,23 @@ void swift_resolve_resilientAccessors(uint8_t *layoutStr, size_t layoutStrOffset, const uint8_t *fieldLayoutStr, const Metadata *fieldType); + +template +inline T readBytes(const uint8_t *layoutStr, size_t &i) { + T returnVal; + memcpy(&returnVal, layoutStr + i, sizeof(T)); + i += sizeof(T); + return returnVal; +} + +template +inline void writeBytes(uint8_t *layoutStr, size_t &i, T value) { + memcpy(layoutStr + i, &value, sizeof(T)); + i += sizeof(T); +} + +constexpr size_t layoutStringHeaderSize = sizeof(uint64_t) + sizeof(size_t); + } // namespace swift #endif // SWIFT_BYTECODE_LAYOUTS_H diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index cae6faac16b74..9a91f5a23874d 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -2641,41 +2641,6 @@ void swift::swift_initStructMetadata(StructMetadata *structType, vwtable->publishLayout(layout); } -namespace { - enum LayoutStringFlags : uint64_t { - Empty = 0, - // TODO: Track other useful information tha can be used to optimize layout - // strings, like different reference kinds contained in the string - // number of ref counting operations (maybe up to 4), so we can - // use witness functions optimized for these cases. - HasRelativePointers = (1ULL << 63), - }; - - inline bool operator&(LayoutStringFlags a, LayoutStringFlags b) { - return (uint64_t(a) & uint64_t(b)) != 0; - } - inline LayoutStringFlags operator|(LayoutStringFlags a, LayoutStringFlags b) { - return LayoutStringFlags(uint64_t(a) | uint64_t(b)); - } - inline LayoutStringFlags &operator|=(LayoutStringFlags &a, LayoutStringFlags b) { - return a = (a | b); - } - - template - inline T readBytes(const uint8_t *layoutStr, size_t &i) { - T returnVal; - memcpy(&returnVal, layoutStr + i, sizeof(T)); - i += sizeof(T); - return returnVal; - } - - template - inline void writeBytes(uint8_t *layoutStr, size_t &i, T value) { - memcpy(layoutStr + i, &value, sizeof(T)); - i += sizeof(T); - } -} // end anonymous namespace - void swift::swift_initStructMetadataWithLayoutString( StructMetadata *structType, StructLayoutFlags layoutFlags, size_t numFields, const uint8_t *const *fieldTypes, const uint8_t *fieldTags, @@ -2727,21 +2692,9 @@ void swift::swift_initStructMetadataWithLayoutString( extraInhabitantCount = fieldExtraInhabitantCount; } - if (fieldType->vw_size() == 0) { - continue; - } else if (fieldType->getValueWitnesses()->isPOD()) { - // no extra space required for POD - } else if (fieldType->hasLayoutString()) { - refCountBytes += *(const size_t *)(fieldType->getLayoutString() + - sizeof(uint64_t)); - } else if (fieldType->isClassObject() || fieldType->isAnyExistentialType()) { - refCountBytes += sizeof(uint64_t); - } else { - refCountBytes += sizeof(uint64_t) + sizeof(uintptr_t); - } + refCountBytes += _swift_refCountBytesForMetatype(fieldType); } - const size_t layoutStringHeaderSize = sizeof(uint64_t) + sizeof(size_t); const size_t fixedLayoutStringSize = layoutStringHeaderSize + sizeof(uint64_t) * 2; @@ -2781,93 +2734,9 @@ void swift::swift_initStructMetadataWithLayoutString( const Metadata *fieldType = (const Metadata*)fieldTypes[i]; - fullOffset = roundUpToAlignMask(fullOffset, fieldType->vw_alignment() - 1); - size_t offset = fullOffset - unalignedOffset + previousFieldOffset; - - if (fieldType->vw_size() == 0) { - continue; - } else if (fieldType->getValueWitnesses()->isPOD()) { - // No need to handle PODs - previousFieldOffset = offset + fieldType->vw_size(); - fullOffset += fieldType->vw_size(); - } else if (fieldType->hasLayoutString()) { - const uint8_t *fieldLayoutStr = fieldType->getLayoutString(); - const LayoutStringFlags fieldFlags = - *(const LayoutStringFlags *)fieldLayoutStr; - const size_t fieldRefCountBytes = - *(const size_t *)(fieldLayoutStr + sizeof(uint64_t)); - if (fieldRefCountBytes > 0) { - flags |= fieldFlags; - memcpy(layoutStr + layoutStrOffset, fieldLayoutStr + layoutStringHeaderSize, - fieldRefCountBytes); - - if (fieldFlags & LayoutStringFlags::HasRelativePointers) { - swift_resolve_resilientAccessors(layoutStr, layoutStrOffset, - fieldLayoutStr, fieldType); - } - - if (offset) { - auto layoutStrOffsetCopy = layoutStrOffset; - auto firstTagAndOffset = - readBytes(layoutStr, layoutStrOffsetCopy); - layoutStrOffsetCopy = layoutStrOffset; - firstTagAndOffset += offset; - writeBytes(layoutStr, layoutStrOffsetCopy, firstTagAndOffset); - } - - auto previousFieldOffsetOffset = - layoutStringHeaderSize + fieldRefCountBytes; - previousFieldOffset = readBytes(fieldLayoutStr, - previousFieldOffsetOffset); - layoutStrOffset += fieldRefCountBytes; - } else { - previousFieldOffset += fieldType->vw_size(); - } - fullOffset += fieldType->vw_size(); - } else if (auto *cls = fieldType->getClassObject()) { - RefCountingKind tag; - if (!cls->isTypeMetadata()) { - #if SWIFT_OBJC_INTEROP - tag = RefCountingKind::ObjC; - #else - tag = RefCountingKind::Unknown; - #endif - } else { - auto *vwt = cls->getValueWitnesses(); - if (vwt == &VALUE_WITNESS_SYM(Bo)) { - tag = RefCountingKind::NativeStrong; - } else if (vwt == &VALUE_WITNESS_SYM(BO)) { - #if SWIFT_OBJC_INTEROP - tag = RefCountingKind::ObjC; - #else - tag = RefCountingKind::Unknown; - #endif - } else if (vwt == &VALUE_WITNESS_SYM(Bb)) { - tag = RefCountingKind::Bridge; - } else { - goto metadata; - }; - } - - writeBytes(layoutStr, layoutStrOffset, ((uint64_t)tag << 56) | offset); - previousFieldOffset = fieldType->vw_size(); - fullOffset += previousFieldOffset; - } else if (fieldType->isAnyExistentialType()) { - auto *existential = dyn_cast(fieldType); - assert(existential); - auto tag = existential->isClassBounded() ? RefCountingKind::Unknown - : RefCountingKind::Existential; - writeBytes(layoutStr, layoutStrOffset, ((uint64_t)tag << 56) | offset); - previousFieldOffset = fieldType->vw_size(); - fullOffset += previousFieldOffset; - } else { -metadata: - writeBytes(layoutStr, layoutStrOffset, - ((uint64_t)RefCountingKind::Metatype << 56) | offset); - writeBytes(layoutStr, layoutStrOffset, fieldType); - previousFieldOffset = fieldType->vw_size(); - fullOffset += previousFieldOffset; - } + _swift_addRefCountStringForMetatype(layoutStr, layoutStrOffset, flags, + fieldType, fullOffset, + previousFieldOffset); } writeBytes(layoutStr, layoutStrOffset, previousFieldOffset); @@ -2896,6 +2765,128 @@ void swift::swift_initStructMetadataWithLayoutString( vwtable->publishLayout(layout); } +size_t swift::_swift_refCountBytesForMetatype(const Metadata *type) { + if (type->vw_size() == 0 || type->getValueWitnesses()->isPOD()) { + return 0; + } else if (type->hasLayoutString()) { + size_t offset = sizeof(uint64_t); + return readBytes(type->getLayoutString(), offset); + } else if (type->isClassObject() || type->isAnyExistentialType()) { + return sizeof(uint64_t); + } else if (auto *tuple = dyn_cast(type)) { + size_t res = 0; + for (InProcess::StoredSize i = 0; i < tuple->NumElements; i++) { + res += _swift_refCountBytesForMetatype(tuple->getElement(i).Type); + } + return res; + } else { + return sizeof(uint64_t) + sizeof(uintptr_t); + } +} + +void swift::_swift_addRefCountStringForMetatype(uint8_t *layoutStr, + size_t &layoutStrOffset, + LayoutStringFlags &flags, + const Metadata *fieldType, + size_t &fullOffset, + size_t &previousFieldOffset) { + size_t unalignedOffset = fullOffset; + fullOffset = roundUpToAlignMask(fullOffset, fieldType->vw_alignment() - 1); + size_t offset = fullOffset - unalignedOffset + previousFieldOffset; + if (fieldType->vw_size() == 0) { + return; + } else if (fieldType->getValueWitnesses()->isPOD()) { + // No need to handle PODs + previousFieldOffset = offset + fieldType->vw_size(); + fullOffset += fieldType->vw_size(); + } else if (fieldType->hasLayoutString()) { + const uint8_t *fieldLayoutStr = fieldType->getLayoutString(); + const LayoutStringFlags fieldFlags = + *(const LayoutStringFlags *)fieldLayoutStr; + size_t refCountBytesOffset = sizeof(uint64_t); + const size_t fieldRefCountBytes = readBytes(fieldLayoutStr, + refCountBytesOffset); + if (fieldRefCountBytes > 0) { + flags |= fieldFlags; + memcpy(layoutStr + layoutStrOffset, + fieldLayoutStr + layoutStringHeaderSize, + fieldRefCountBytes); + + if (fieldFlags & LayoutStringFlags::HasRelativePointers) { + swift_resolve_resilientAccessors(layoutStr, layoutStrOffset, + fieldLayoutStr, fieldType); + } + + if (offset) { + auto layoutStrOffsetCopy = layoutStrOffset; + auto firstTagAndOffset = + readBytes(layoutStr, layoutStrOffsetCopy); + layoutStrOffsetCopy = layoutStrOffset; + firstTagAndOffset += offset; + writeBytes(layoutStr, layoutStrOffsetCopy, firstTagAndOffset); + } + + auto previousFieldOffsetOffset = + layoutStringHeaderSize + fieldRefCountBytes; + previousFieldOffset = readBytes(fieldLayoutStr, + previousFieldOffsetOffset); + layoutStrOffset += fieldRefCountBytes; + } else { + previousFieldOffset += fieldType->vw_size(); + } + fullOffset += fieldType->vw_size(); + } else if (auto *tuple = dyn_cast(fieldType)) { + for (InProcess::StoredSize i = 0; i < tuple->NumElements; i++) { + _swift_addRefCountStringForMetatype(layoutStr, layoutStrOffset, flags, + tuple->getElement(i).Type, fullOffset, + previousFieldOffset); + } + } else if (auto *cls = fieldType->getClassObject()) { + RefCountingKind tag; + if (!cls->isTypeMetadata()) { + #if SWIFT_OBJC_INTEROP + tag = RefCountingKind::ObjC; + #else + tag = RefCountingKind::Unknown; + #endif + } else { + auto *vwt = cls->getValueWitnesses(); + if (vwt == &VALUE_WITNESS_SYM(Bo)) { + tag = RefCountingKind::NativeStrong; + } else if (vwt == &VALUE_WITNESS_SYM(BO)) { + #if SWIFT_OBJC_INTEROP + tag = RefCountingKind::ObjC; + #else + tag = RefCountingKind::Unknown; + #endif + } else if (vwt == &VALUE_WITNESS_SYM(Bb)) { + tag = RefCountingKind::Bridge; + } else { + goto metadata; + }; + } + + writeBytes(layoutStr, layoutStrOffset, ((uint64_t)tag << 56) | offset); + previousFieldOffset = fieldType->vw_size(); + fullOffset += previousFieldOffset; + } else if (fieldType->isAnyExistentialType()) { + auto *existential = dyn_cast(fieldType); + assert(existential); + auto tag = existential->isClassBounded() ? RefCountingKind::Unknown + : RefCountingKind::Existential; + writeBytes(layoutStr, layoutStrOffset, ((uint64_t)tag << 56) | offset); + previousFieldOffset = fieldType->vw_size(); + fullOffset += previousFieldOffset; + } else { +metadata: + writeBytes(layoutStr, layoutStrOffset, + ((uint64_t)RefCountingKind::Metatype << 56) | offset); + writeBytes(layoutStr, layoutStrOffset, fieldType); + previousFieldOffset = fieldType->vw_size(); + fullOffset += previousFieldOffset; + } +} + /***************************************************************************/ /*** Classes ***************************************************************/ /***************************************************************************/ diff --git a/test/Concurrency/default_actor_definit.swift b/test/Concurrency/default_actor_definit.swift index 229c7db8e52e8..e97966abfb395 100644 --- a/test/Concurrency/default_actor_definit.swift +++ b/test/Concurrency/default_actor_definit.swift @@ -40,7 +40,7 @@ actor C { // CHECK-LABEL: sil hidden @$s21default_actor_definit1CC1yACSgSi_tcfc // CHECK: builtin "initializeDefaultActor"(%1 : $C) // CHECK: [[X:%.*]] = ref_element_addr %1 : $C, #C.x -// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[X]] : $*String +// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [init] [static] [[X]] : $*String // CHECK-NEXT: store {{.*}} to [[ACCESS]] : $*String // CHECK-NEXT: end_access [[ACCESS]] : $*String // CHECK: cond_br {{%.*}}, bb1, bb2 diff --git a/test/Interop/Cxx/stdlib/Inputs/module.modulemap b/test/Interop/Cxx/stdlib/Inputs/module.modulemap index fdd243c2f0281..ada070f360add 100644 --- a/test/Interop/Cxx/stdlib/Inputs/module.modulemap +++ b/test/Interop/Cxx/stdlib/Inputs/module.modulemap @@ -3,11 +3,6 @@ module StdVector { requires cplusplus } -module StdString { - header "std-string.h" - requires cplusplus -} - module StdMap { header "std-map.h" requires cplusplus diff --git a/test/Interop/Cxx/stdlib/Inputs/std-string.h b/test/Interop/Cxx/stdlib/Inputs/std-string.h deleted file mode 100644 index 730aaa5cc3e4d..0000000000000 --- a/test/Interop/Cxx/stdlib/Inputs/std-string.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef TEST_INTEROP_CXX_STDLIB_INPUTS_STD_STRING_H -#define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_STRING_H - -#include - -using CxxString = std::string; - -#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_STRING_H \ No newline at end of file diff --git a/test/Interop/Cxx/stdlib/use-std-string.swift b/test/Interop/Cxx/stdlib/use-std-string.swift index 1222b22aaa2a9..5ecdad53fab8e 100644 --- a/test/Interop/Cxx/stdlib/use-std-string.swift +++ b/test/Interop/Cxx/stdlib/use-std-string.swift @@ -3,19 +3,18 @@ // REQUIRES: executable_test import StdlibUnittest -import StdString import CxxStdlib var StdStringTestSuite = TestSuite("StdString") StdStringTestSuite.test("init") { - let s = CxxString() + let s = std.string() expectEqual(s.size(), 0) expectTrue(s.empty()) } StdStringTestSuite.test("push back") { - var s = CxxString() + var s = std.string() s.push_back(42) expectEqual(s.size(), 1) expectFalse(s.empty()) diff --git a/test/SIL/OwnershipVerifier/use_verifier.sil b/test/SIL/OwnershipVerifier/use_verifier.sil index eca06f90f683c..8afa7edbe9438 100644 --- a/test/SIL/OwnershipVerifier/use_verifier.sil +++ b/test/SIL/OwnershipVerifier/use_verifier.sil @@ -1433,23 +1433,3 @@ bb0(%0 : @unowned $ThreeDifferingPayloadEnum): return %1 : $Builtin.Int32 } -sil [ossa] @test_select_value : $@convention(thin) (Builtin.Word) -> Builtin.Word { -bb0(%0 : $Builtin.Word): - - %1 = integer_literal $Builtin.Word, 1 - %2 = integer_literal $Builtin.Word, 2 - %3 = integer_literal $Builtin.Word, 3 - %4 = integer_literal $Builtin.Word, 4 - %5 = integer_literal $Builtin.Word, 5 - %6 = integer_literal $Builtin.Word, 6 - %11 = integer_literal $Builtin.Word, 11 - %22 = integer_literal $Builtin.Word, 22 - %33 = integer_literal $Builtin.Word, 33 - %44 = integer_literal $Builtin.Word, 44 - %55 = integer_literal $Builtin.Word, 55 - %66 = integer_literal $Builtin.Word, 66 - - %10 = select_value %1: $Builtin.Word, case %1: %11, case %2: %22, case %4: %44, case %5: %55, case %6: %66, default %33 : $Builtin.Word - - return %10 : $Builtin.Word -} diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil index de8f8621a2f7b..379a4b3e96918 100644 --- a/test/SIL/Parser/basic.sil +++ b/test/SIL/Parser/basic.sil @@ -977,57 +977,6 @@ bb6: return %18 : $() } -// CHECK-LABEL: sil @test_select_value : $@convention(thin) (Builtin.Word) -> Builtin.Word -sil @test_select_value : $@convention(thin) (Builtin.Word) -> Builtin.Word { -bb0(%0 : $Builtin.Word): - - %1 = integer_literal $Builtin.Word, 1 - %2 = integer_literal $Builtin.Word, 2 - %3 = integer_literal $Builtin.Word, 3 - %4 = integer_literal $Builtin.Word, 4 - %5 = integer_literal $Builtin.Word, 5 - %6 = integer_literal $Builtin.Word, 6 - %11 = integer_literal $Builtin.Word, 11 - %22 = integer_literal $Builtin.Word, 22 - %33 = integer_literal $Builtin.Word, 33 - %44 = integer_literal $Builtin.Word, 44 - %55 = integer_literal $Builtin.Word, 55 - %66 = integer_literal $Builtin.Word, 66 - - // CHECK: select_value %{{.*}} : $Builtin.Word, case %{{.*}}: %{{.*}}, case %{{.*}}: %{{.*}}, case %{{.*}}: %{{.*}}, case %{{.*}}: %{{.*}}, case %{{.*}}: %{{.*}}, default %{{.*}} : $Builtin.Word - %10 = select_value %0: $Builtin.Word, case %1: %11, case %2: %22, case %4: %44, case %5: %55, case %6: %66, default %33 : $Builtin.Word - - // CHECK: return - return %10 : $Builtin.Word -} - -enum IntEnum : Int { - case E0 - case E1 - case E2 -} - -// CHECK-LABEL: sil @test_select_value_with_enum : $@convention(thin) (Builtin.Word) -> Optional -sil @test_select_value_with_enum : $@convention(thin) (Builtin.Word) -> Optional { -bb0(%0 : $Builtin.Word): - %1 = integer_literal $Builtin.Word, 0 - %2 = integer_literal $Builtin.Word, 1 - %3 = enum $IntEnum, #IntEnum.E1!enumelt - %4 = enum $Optional, #Optional.some!enumelt, %3 : $IntEnum - %5 = integer_literal $Builtin.Word, 2 - %6 = enum $IntEnum, #IntEnum.E2!enumelt - %7 = enum $Optional, #Optional.some!enumelt, %6 : $IntEnum - %8 = enum $IntEnum, #IntEnum.E0!enumelt - %9 = enum $Optional, #Optional.some!enumelt, %8 : $IntEnum - %10 = enum $Optional, #Optional.none!enumelt - - // CHECK: select_value %{{.*}} : $Builtin.Word, case %{{.*}}: %{{.*}}, case %{{.*}}: %{{.*}}, case %{{.*}}: %{{.*}}, default %{{.*}} : $Optional - %11 = select_value %0 : $Builtin.Word, case %2: %4, case %5: %7, case %1: %9, default %10 : $Optional - - // CHECK: return - return %11 : $Optional -} - class ConcreteClass : ClassP { } struct Spoon : Bendable { diff --git a/test/SIL/Parser/undef.sil b/test/SIL/Parser/undef.sil index 08f430f53b03f..ded922b53699e 100644 --- a/test/SIL/Parser/undef.sil +++ b/test/SIL/Parser/undef.sil @@ -298,13 +298,6 @@ bb2: return undef : $() } -sil @select_value_test : $() -> () { -bb0: - // CHECK: select_value undef : $Builtin.Int1, case undef: undef, default undef : $Builtin.Int1 - select_value undef : $Builtin.Int1, case undef: undef, default undef : $Builtin.Int1 - return undef : $() -} - sil @switch_enum_test : $() -> () { bb0: // CHECK: switch_enum undef : $E, case #E.Case!enumelt: bb1, default bb2 diff --git a/test/SIL/clone_select_switch_value.sil b/test/SIL/clone_select_switch_value.sil deleted file mode 100644 index 6cb64f56e3408..0000000000000 --- a/test/SIL/clone_select_switch_value.sil +++ /dev/null @@ -1,41 +0,0 @@ -// RUN: %target-sil-opt -enable-sil-verify-all -inline %s | %FileCheck %s - -// Check if cloning of select_value and switch_value works correctly without -// producing illegal SIL. - -sil_stage canonical - -import Builtin - -sil [always_inline] @callee : $@convention(thin) () -> () { -bb0: - %1 = integer_literal $Builtin.Word, 1 - %2 = integer_literal $Builtin.Word, 2 - %3 = integer_literal $Builtin.Word, 3 - - %4 = select_value %1: $Builtin.Word, case %1: %2, case %2: %1, default %3 : $Builtin.Word - - switch_value %1 : $Builtin.Word, case %1: bb1, case %2: bb2 - -bb1: - br bb3 - -bb2: - br bb3 - -bb3: - %5 = tuple () - return %5 : $() -} - -// CHECK-LABEL: sil @caller : $@convention(thin) () -> () -// CHECK: select_value -// CHECK: switch_value -sil @caller : $@convention(thin) () -> () { -bb0: - %0 = function_ref @callee : $@convention(thin) () -> () - %1 = apply %0() : $@convention(thin) () -> () - %2 = tuple () - return %2 : $() -} - diff --git a/test/SILOptimizer/dead_alloc_elim.sil b/test/SILOptimizer/dead_alloc_elim.sil index ef79c5fb69715..de4f3d66a8cff 100644 --- a/test/SILOptimizer/dead_alloc_elim.sil +++ b/test/SILOptimizer/dead_alloc_elim.sil @@ -127,7 +127,9 @@ sil @store_to_trivial_property : $@convention(thin) (Int) -> () { bb0(%0 : $Int): %20 = alloc_ref [stack] $NontrivialDestructor %21 = ref_element_addr %20 : $NontrivialDestructor, #NontrivialDestructor.i - store %0 to %21 : $*Int + %22 = begin_access [modify] [dynamic] %21 : $*Int + store %0 to %22 : $*Int + end_access %22 : $*Int set_deallocating %20 : $NontrivialDestructor dealloc_ref %20 : $NontrivialDestructor dealloc_stack_ref %20 : $NontrivialDestructor diff --git a/test/SILOptimizer/default-cmo.swift b/test/SILOptimizer/default-cmo.swift index 9f5f6301cc57a..bc603778696b8 100644 --- a/test/SILOptimizer/default-cmo.swift +++ b/test/SILOptimizer/default-cmo.swift @@ -80,9 +80,8 @@ public func getSubmoduleKlassMember() -> Int { } // CHECK-LABEL: sil @$s4Main26getSubmoduleKlassMemberTBDSiyF -// CHECK: [[F:%[0-9]+]] = function_ref @$s9ModuleTBD20submoduleKlassMemberSiyF -// CHECK: [[I:%[0-9]+]] = apply [[F]] -// CHECK: return [[I]] +// CHECK-NOT: function_ref +// CHECK-NOT: apply // CHECK: } // end sil function '$s4Main26getSubmoduleKlassMemberTBDSiyF' public func getSubmoduleKlassMemberTBD() -> Int { return ModuleTBD.submoduleKlassMember() diff --git a/test/SILOptimizer/definite_init_actor.swift b/test/SILOptimizer/definite_init_actor.swift index 1bd896baf5d96..c38418192749c 100644 --- a/test/SILOptimizer/definite_init_actor.swift +++ b/test/SILOptimizer/definite_init_actor.swift @@ -83,7 +83,7 @@ actor BoringActor { // CHECK-LABEL: sil hidden @$s4test14SingleVarActorC10iterationsACSi_tYacfc : $@convention(method) @async (Int, @owned SingleVarActor) -> @owned SingleVarActor { // CHECK: bb0({{%[0-9]+}} : $Int, [[SELF:%[0-9]+]] : $SingleVarActor): // CHECK: [[MYVAR_REF:%[0-9]+]] = ref_element_addr [[SELF]] : $SingleVarActor, #SingleVarActor.myVar - // CHECK: [[MYVAR:%[0-9]+]] = begin_access [modify] [dynamic] [[MYVAR_REF]] : $*Int + // CHECK: [[MYVAR:%[0-9]+]] = begin_access [init] [static] [[MYVAR_REF]] : $*Int // CHECK: store {{%[0-9]+}} to [[MYVAR]] : $*Int // CHECK-NEXT: end_access [[MYVAR]] // CHECK-NEXT: hop_to_executor [[SELF]] : $SingleVarActor @@ -196,7 +196,7 @@ actor MultiVarActor { // CHECK-LABEL: sil hidden @$s4test13MultiVarActorC10doNotThrowACSb_tYaKcfc : $@convention(method) @async (Bool, @owned MultiVarActor) -> (@owned MultiVarActor, @error any Error) { // CHECK: bb0({{%[0-9]+}} : $Bool, [[SELF:%[0-9]+]] : $MultiVarActor): // CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MultiVarActor, #MultiVarActor.firstVar - // CHECK: [[VAR:%[0-9]+]] = begin_access [modify] [dynamic] [[REF]] : $*Int + // CHECK: [[VAR:%[0-9]+]] = begin_access [init] [static] [[REF]] : $*Int // CHECK: store {{%[0-9]+}} to [[VAR]] : $*Int // CHECK-NEXT: end_access [[VAR]] // CHECK-NEXT: hop_to_executor %1 : $MultiVarActor diff --git a/test/SILOptimizer/definite_init_failable_initializers.swift b/test/SILOptimizer/definite_init_failable_initializers.swift index c67337128bcf4..f46bedebb8626 100644 --- a/test/SILOptimizer/definite_init_failable_initializers.swift +++ b/test/SILOptimizer/definite_init_failable_initializers.swift @@ -735,7 +735,7 @@ class FailableBaseClass { // CHECK: bb0(%0 : $FailableBaseClass): // CHECK: [[CANARY:%.*]] = apply // CHECK-NEXT: [[MEMBER_ADDR:%.*]] = ref_element_addr %0 -// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[MEMBER_ADDR]] : $*Canary +// CHECK-NEXT: [[WRITE:%.*]] = begin_access [init] [static] [[MEMBER_ADDR]] : $*Canary // CHECK-NEXT: store [[CANARY]] to [[WRITE]] // CHECK-NEXT: end_access [[WRITE]] : $*Canary // CHECK-NEXT: strong_release %0 @@ -849,7 +849,7 @@ class FailableDerivedClass : FailableBaseClass { // CHECK: [[CANARY_FUN:%.*]] = function_ref @$s35definite_init_failable_initializers6CanaryCACycfC : // CHECK: [[CANARY:%.*]] = apply [[CANARY_FUN]]( // CHECK-NEXT: [[MEMBER_ADDR:%.*]] = ref_element_addr [[SELF]] -// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[MEMBER_ADDR]] : $*Canary +// CHECK-NEXT: [[WRITE:%.*]] = begin_access [init] [static] [[MEMBER_ADDR]] : $*Canary // CHECK-NEXT: store [[CANARY]] to [[WRITE]] // CHECK-NEXT: end_access [[WRITE]] : $*Canary // CHECK-NEXT: strong_release [[SELF]] diff --git a/test/SILOptimizer/definite_init_markuninitialized_rootself.sil b/test/SILOptimizer/definite_init_markuninitialized_rootself.sil index 59b0497c3df12..887ee879647f5 100644 --- a/test/SILOptimizer/definite_init_markuninitialized_rootself.sil +++ b/test/SILOptimizer/definite_init_markuninitialized_rootself.sil @@ -21,6 +21,17 @@ class RootClassWithNontrivialStoredProperties { } class SomeClass {} + +final class IntClass { + var i: Int + init(_ i: Int) +} + +final class GenericClass { + var t: T + init(_ t: T) +} + sil @getSomeClass : $@convention(thin) () -> @owned SomeClass sil @getSomeOptionalClass : $@convention(thin) () -> Optional @@ -131,3 +142,45 @@ bb0(%0 : @owned $RootClassWithNontrivialStoredProperties): %13 = tuple () return %13 : $() } + +// CHECK-LABEL: sil [ossa] @init_IntClass : +// CHECK: [[ACCESS:%.*]] = begin_access [init] [static] +// CHECK: store %0 to [trivial] [[ACCESS]] +// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [dynamic] +// CHECK: store %0 to [trivial] [[ACCESS2]] +// CHECK: } // end sil function 'init_IntClass' +sil [ossa] @init_IntClass : $@convention(method) (Int, @owned IntClass) -> @owned IntClass { +bb0(%0 : $Int, %1 : @owned $IntClass): + %4 = mark_uninitialized [rootself] %1 : $IntClass + %5 = begin_borrow %4 : $IntClass + %6 = ref_element_addr %5 : $IntClass, #IntClass.i + %7 = begin_access [modify] [dynamic] %6 : $*Int + assign %0 to %7 : $*Int + end_access %7 : $*Int + %10 = begin_access [modify] [dynamic] %6 : $*Int + assign %0 to %10 : $*Int + end_access %10 : $*Int + end_borrow %5 : $IntClass + return %4 : $IntClass +} + +// CHECK-LABEL: sil [ossa] @init_GenericClass : +// CHECK: [[ACCESS:%.*]] = begin_access [init] [static] +// CHECK: copy_addr %0 to [init] [[ACCESS]] +// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [dynamic] +// CHECK: copy_addr [take] %0 to [[ACCESS2]] +// CHECK: } // end sil function 'init_GenericClass' +sil [ossa] @init_GenericClass : $@convention(method) (@in T, @owned GenericClass) -> @owned GenericClass { +bb0(%0 : $*T, %1 : @owned $GenericClass): + %4 = mark_uninitialized [rootself] %1 : $GenericClass + %5 = begin_borrow %4 : $GenericClass + %8 = ref_element_addr %5 : $GenericClass, #GenericClass.t + %9 = begin_access [modify] [dynamic] %8 : $*T + copy_addr %0 to %9 : $*T + end_access %9 : $*T + %12 = begin_access [modify] [dynamic] %8 : $*T + copy_addr [take] %0 to %12 : $*T + end_access %12 : $*T + end_borrow %5 : $GenericClass + return %4 : $GenericClass +} diff --git a/test/SILOptimizer/definite_init_root_class.swift b/test/SILOptimizer/definite_init_root_class.swift index 0e19405bd7868..75132ca6811ac 100644 --- a/test/SILOptimizer/definite_init_root_class.swift +++ b/test/SILOptimizer/definite_init_root_class.swift @@ -31,7 +31,7 @@ class FirstClass { // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $FirstClass, #FirstClass.x - // CHECK: [[X_ACCESS:%.*]] = begin_access [modify] [dynamic] %15 : $*OtherClass + // CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] %15 : $*OtherClass // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int1, -1 // CHECK: store [[ONE]] to [[CONTROL]] : $*Builtin.Int1 // CHECK: store [[OTHER]] to [[X_ACCESS]] : $*OtherClass @@ -115,7 +115,7 @@ class SecondClass { // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.x - // CHECK: [[X_ACCESS:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*OtherClass + // CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] [[X_ADDR]] : $*OtherClass // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int2, 1 // CHECK: store [[ONE]] to [[CONTROL]] : $*Builtin.Int2 // CHECK: store [[OTHER]] to [[X_ACCESS]] : $*OtherClass @@ -138,7 +138,7 @@ class SecondClass { // CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass // CHECK: [[Y_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.y - // CHECK: [[Y_ACCESS:%.*]] = begin_access [modify] [dynamic] [[Y_ADDR]] : $*OtherClass + // CHECK: [[Y_ACCESS:%.*]] = begin_access [init] [static] [[Y_ADDR]] : $*OtherClass // CHECK: [[THREE:%.*]] = integer_literal $Builtin.Int2, -1 // CHECK: store [[THREE]] to [[CONTROL]] : $*Builtin.Int2 // CHECK: store [[OTHER]] to [[Y_ACCESS]] : $*OtherClass diff --git a/test/SILOptimizer/devirt_speculative_init.swift b/test/SILOptimizer/devirt_speculative_init.swift index bf5034f37c843..f607a81a92251 100644 --- a/test/SILOptimizer/devirt_speculative_init.swift +++ b/test/SILOptimizer/devirt_speculative_init.swift @@ -20,17 +20,17 @@ public class BigCat : Cat { } } -public func make(type: Cat.Type, cats: Int) { - type.init(cats: cats) +public func make(type: Cat.Type, cats: Int) -> Cat { + return type.init(cats: cats) } -// CHECK-LABEL: sil @$s23devirt_speculative_init4make4type4catsyAA3CatCm_SitF : $@convention(thin) (@thick Cat.Type, Int) -> () +// CHECK-LABEL: sil @$s23devirt_speculative_init4make4type4catsAA3CatCAFm_SitF : $@convention(thin) (@thick Cat.Type, Int) -> @owned Cat { // CHECK: checked_cast_br [exact] %0 : $@thick Cat.Type to @thick Cat.Type, bb2, bb3 -// CHECK: bb1: +// CHECK: bb1{{.*}}: // CHECK: return // CHECK: bb2({{%.*}} : $@thick Cat.Type): -// CHECK: alloc_ref [stack] $Cat +// CHECK: alloc_ref $Cat // CHECK: br bb1 // CHECK: bb3: -// CHECK: alloc_ref [stack] $BigCat +// CHECK: alloc_ref $BigCat // CHECK: br bb1 diff --git a/test/SILOptimizer/merge_exclusivity.swift b/test/SILOptimizer/merge_exclusivity.swift index 2dbbaa50d31cc..95442cd3c6fa0 100644 --- a/test/SILOptimizer/merge_exclusivity.swift +++ b/test/SILOptimizer/merge_exclusivity.swift @@ -377,8 +377,7 @@ private struct EscapedTransform: WriteProt { // TESTSIL-LABEL: sil [noinline] @$s17merge_exclusivity14run_MergeTest9yySiF : $@convention(thin) // TESTSIL: [[REFADDR:%.*]] = ref_element_addr {{.*}} : $StreamClass, #StreamClass.buffer -// TESTSIL-NEXT: [[B1:%.*]] = begin_access [modify] [{{.*}}] [no_nested_conflict] [[REFADDR]] -// TESTSIL: end_access [[B1]] +// TESTSIL-NEXT: store {{.*}} to [[REFADDR]] // TESTSIL: [[BCONF:%.*]] = begin_access [modify] [{{.*}}] [[REFADDR]] // TESTSIL: end_access [[BCONF]] // TESTSIL: [[BCONF:%.*]] = begin_access [modify] [{{.*}}] [[REFADDR]] diff --git a/test/SILOptimizer/simplify_cfg.sil b/test/SILOptimizer/simplify_cfg.sil index 77d250e703a4f..d6181a5338da9 100644 --- a/test/SILOptimizer/simplify_cfg.sil +++ b/test/SILOptimizer/simplify_cfg.sil @@ -1707,65 +1707,6 @@ bb7: } -enum IntEnum : Int32 { - case E0 - case E1 - case E2 -} - -// CHECK-LABEL: sil @create_select_value : $@convention(thin) (Builtin.Int32) -> Optional { -// CHECK-DAG: [[X2:%[0-9]+]] = integer_literal $Builtin.Int32, 0 -// CHECK-DAG: [[X5:%[0-9]+]] = enum $Optional, #Optional.none!enumelt -// CHECK-DAG: [[X6:%[0-9]+]] = integer_literal $Builtin.Int32, 2 -// CHECK-DAG: [[X7:%[0-9]+]] = enum $IntEnum, #IntEnum.E2!enumelt -// CHECK-DAG: [[X8:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[X7]] : $IntEnum -// CHECK-DAG: [[X9:%[0-9]+]] = integer_literal $Builtin.Int32, 1 -// CHECK-DAG: [[X10:%[0-9]+]] = enum $IntEnum, #IntEnum.E1!enumelt -// CHECK-DAG: [[X11:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[X10]] : $IntEnum -// CHECK-DAG: [[X12:%[0-9]+]] = enum $IntEnum, #IntEnum.E0!enumelt -// CHECK-DAG: [[X13:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[X12]] : $IntEnum -// CHECK-DAG: [[X14:%[0-9]+]] = select_value %0 : $Builtin.Int32, case [[X6]]: [[X8]], case [[X9]]: [[X11]], case [[X2]]: [[X13]], default [[X5]] : $Optional -// CHECK-DAG: return [[X14]] : $Optional -sil @create_select_value : $@convention(thin) (Builtin.Int32) -> Optional { -bb0(%0 : $Builtin.Int32): - %2 = integer_literal $Builtin.Int32, 0 - %4 = builtin "cmp_eq_Int32"(%2 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 - cond_br %4, bb1, bb2 - -bb1: - %6 = enum $IntEnum, #IntEnum.E0!enumelt - %7 = enum $Optional, #Optional.some!enumelt, %6 : $IntEnum - br bb7(%7 : $Optional) - -bb2: - %9 = integer_literal $Builtin.Int32, 1 - %10 = builtin "cmp_eq_Int32"(%9 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 - cond_br %10, bb3, bb4 - -bb3: - %12 = enum $IntEnum, #IntEnum.E1!enumelt - %13 = enum $Optional, #Optional.some!enumelt, %12 : $IntEnum - br bb7(%13 : $Optional) - -bb4: - %15 = integer_literal $Builtin.Int32, 2 - %16 = builtin "cmp_eq_Int32"(%15 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 - cond_br %16, bb5, bb6 - -bb5: - %18 = enum $IntEnum, #IntEnum.E2!enumelt - %19 = enum $Optional, #Optional.some!enumelt, %18 : $IntEnum - br bb7(%19 : $Optional) - -bb6: - %21 = enum $Optional, #Optional.none!enumelt - br bb7(%21 : $Optional) - -bb7(%23 : $Optional): - return %23 : $Optional -} - - class B {} class E : B {} diff --git a/test/SILOptimizer/simplify_cfg_dominators.sil b/test/SILOptimizer/simplify_cfg_dominators.sil deleted file mode 100644 index 1c69a469550d5..0000000000000 --- a/test/SILOptimizer/simplify_cfg_dominators.sil +++ /dev/null @@ -1,92 +0,0 @@ -// RUN: %target-sil-opt -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s - -// Tests dominator-based simplification with OSSA. This does not -// require -jumpthread-simplify-cfg, which enabled jump-threading -// within dominator-based simplification. - -// Includes the OSSA form of tests from simplify_cfg_unique_values.sil. -// REQUIRES: EnableOSSASimplifyCFG - -sil_stage canonical - -import Builtin -import Swift - -enum DupCaseEnum { - case firstCase - case secondCase -} - -// CHECK-LABEL: sil [ossa] @performSwitch : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -// CHECK: bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): -// CHECK: select_value -// CHECK-NEXT: return -sil [ossa] @performSwitch : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): - %4 = integer_literal $Builtin.Int64, 0 - %5 = struct_extract %0 : $Int64, #Int64._value - %6 = builtin "cmp_eq_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1 - cond_br %6, bb6, bb1 - -bb1: - br bb2 - -bb2: - cond_br %6, bb5, bb3 - -bb3: - br bb4 - -bb4: - %12 = enum $DupCaseEnum, #DupCaseEnum.secondCase!enumelt - br bb7(%12 : $DupCaseEnum) - -bb5: - %14 = enum $DupCaseEnum, #DupCaseEnum.firstCase!enumelt - br bb7(%14 : $DupCaseEnum) - -bb6: - %16 = enum $DupCaseEnum, #DupCaseEnum.firstCase!enumelt - br bb7(%16 : $DupCaseEnum) - -bb7(%18 : $DupCaseEnum): - return %18 : $DupCaseEnum -} - -// CHECK-LABEL: sil [ossa] @performSwitch_bail_out : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -// CHECK: bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): -// CHECK-NOT: select_value -// CHECK-NOT: br bb1 -// CHECK: cond_br -sil [ossa] @performSwitch_bail_out : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): - %4 = integer_literal $Builtin.Int64, 0 - %5 = struct_extract %0 : $Int64, #Int64._value - %6 = builtin "cmp_eq_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1 - cond_br %6, bb6, bb1 - -bb1: - br bb2 - -bb2: - cond_br %6, bb5, bb3 - -bb3: - br bb4 - -bb4: - %12 = enum $DupCaseEnum, #DupCaseEnum.secondCase!enumelt - br bb7(%12 : $DupCaseEnum) - -bb5: - %14 = enum $DupCaseEnum, #DupCaseEnum.secondCase!enumelt - br bb7(%14 : $DupCaseEnum) - -bb6: - %16 = enum $DupCaseEnum, #DupCaseEnum.firstCase!enumelt - br bb7(%16 : $DupCaseEnum) - -bb7(%18 : $DupCaseEnum): - return %18 : $DupCaseEnum -} - diff --git a/test/SILOptimizer/simplify_cfg_ossa.sil b/test/SILOptimizer/simplify_cfg_ossa.sil index 0ae09f26f09b8..7ff741d20f3b2 100644 --- a/test/SILOptimizer/simplify_cfg_ossa.sil +++ b/test/SILOptimizer/simplify_cfg_ossa.sil @@ -884,58 +884,6 @@ enum IntEnum : Int32 { case E2 } -// CHECK-LABEL: sil [ossa] @create_select_value : $@convention(thin) (Builtin.Int32) -> Optional { -// CHECK-DAG: [[X2:%[0-9]+]] = integer_literal $Builtin.Int32, 0 -// CHECK-DAG: [[X5:%[0-9]+]] = enum $Optional, #Optional.none!enumelt -// CHECK-DAG: [[X6:%[0-9]+]] = integer_literal $Builtin.Int32, 2 -// CHECK-DAG: [[X7:%[0-9]+]] = enum $IntEnum, #IntEnum.E2!enumelt -// CHECK-DAG: [[X8:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[X7]] : $IntEnum -// CHECK-DAG: [[X9:%[0-9]+]] = integer_literal $Builtin.Int32, 1 -// CHECK-DAG: [[X10:%[0-9]+]] = enum $IntEnum, #IntEnum.E1!enumelt -// CHECK-DAG: [[X11:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[X10]] : $IntEnum -// CHECK-DAG: [[X12:%[0-9]+]] = enum $IntEnum, #IntEnum.E0!enumelt -// CHECK-DAG: [[X13:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, [[X12]] : $IntEnum -// CHECK-DAG: [[X14:%[0-9]+]] = select_value %0 : $Builtin.Int32, case [[X6]]: [[X8]], case [[X9]]: [[X11]], case [[X2]]: [[X13]], default [[X5]] : $Optional -// CHECK-DAG: return [[X14]] : $Optional -sil [ossa] @create_select_value : $@convention(thin) (Builtin.Int32) -> Optional { -bb0(%0 : $Builtin.Int32): - %2 = integer_literal $Builtin.Int32, 0 - %4 = builtin "cmp_eq_Int32"(%2 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 - cond_br %4, bb1, bb2 - -bb1: - %6 = enum $IntEnum, #IntEnum.E0!enumelt - %7 = enum $Optional, #Optional.some!enumelt, %6 : $IntEnum - br bb7(%7 : $Optional) - -bb2: - %9 = integer_literal $Builtin.Int32, 1 - %10 = builtin "cmp_eq_Int32"(%9 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 - cond_br %10, bb3, bb4 - -bb3: - %12 = enum $IntEnum, #IntEnum.E1!enumelt - %13 = enum $Optional, #Optional.some!enumelt, %12 : $IntEnum - br bb7(%13 : $Optional) - -bb4: - %15 = integer_literal $Builtin.Int32, 2 - %16 = builtin "cmp_eq_Int32"(%15 : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1 - cond_br %16, bb5, bb6 - -bb5: - %18 = enum $IntEnum, #IntEnum.E2!enumelt - %19 = enum $Optional, #Optional.some!enumelt, %18 : $IntEnum - br bb7(%19 : $Optional) - -bb6: - %21 = enum $Optional, #Optional.none!enumelt - br bb7(%21 : $Optional) - -bb7(%23 : $Optional): - return %23 : $Optional -} - // CHECK-LABEL: sil [ossa] @checked_cast_anyobject_metatypeinst_to_class // CHECK: bb0 // CHECK-NOT: checked_cast diff --git a/test/SILOptimizer/simplify_cfg_unique_values.sil b/test/SILOptimizer/simplify_cfg_unique_values.sil deleted file mode 100644 index 43cf10d344d1d..0000000000000 --- a/test/SILOptimizer/simplify_cfg_unique_values.sil +++ /dev/null @@ -1,88 +0,0 @@ -// RUN: %target-sil-opt -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s - -sil_stage canonical - -import Builtin -import Swift - -enum DupCaseEnum { - case firstCase - case secondCase -} - -// CHECK-LABEL: sil @performSwitch : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -// CHECK: bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): -// CHECK: select_value -// CHECK-NEXT: return -sil @performSwitch : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -// %0 -bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): - %4 = integer_literal $Builtin.Int64, 0 - %5 = struct_extract %0 : $Int64, #Int64._value - %6 = builtin "cmp_eq_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1 - cond_br %6, bb6, bb1 - -bb1: - br bb2 - -bb2: - cond_br %6, bb5, bb3 - -bb3: - br bb4 - -bb4: - %12 = enum $DupCaseEnum, #DupCaseEnum.secondCase!enumelt - br bb7(%12 : $DupCaseEnum) - -bb5: - %14 = enum $DupCaseEnum, #DupCaseEnum.firstCase!enumelt - br bb7(%14 : $DupCaseEnum) - -bb6: - %16 = enum $DupCaseEnum, #DupCaseEnum.firstCase!enumelt - br bb7(%16 : $DupCaseEnum) - -// %18 -bb7(%18 : $DupCaseEnum): - return %18 : $DupCaseEnum -} - -// CHECK-LABEL: sil @performSwitch_bail_out : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -// CHECK: bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): -// CHECK-NOT: select_value -// CHECK-NOT: br bb1 -// CHECK: cond_br -sil @performSwitch_bail_out : $@convention(thin) (Int64, @thin DupCaseEnum.Type) -> DupCaseEnum { -// %0 -bb0(%0 : $Int64, %1 : $@thin DupCaseEnum.Type): - %4 = integer_literal $Builtin.Int64, 0 - %5 = struct_extract %0 : $Int64, #Int64._value - %6 = builtin "cmp_eq_Int64"(%4 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1 - cond_br %6, bb6, bb1 - -bb1: - br bb2 - -bb2: - cond_br %6, bb5, bb3 - -bb3: - br bb4 - -bb4: - %12 = enum $DupCaseEnum, #DupCaseEnum.secondCase!enumelt - br bb7(%12 : $DupCaseEnum) - -bb5: - %14 = enum $DupCaseEnum, #DupCaseEnum.secondCase!enumelt - br bb7(%14 : $DupCaseEnum) - -bb6: - %16 = enum $DupCaseEnum, #DupCaseEnum.firstCase!enumelt - br bb7(%16 : $DupCaseEnum) - -// %18 -bb7(%18 : $DupCaseEnum): - return %18 : $DupCaseEnum -} diff --git a/test/decl/ext/Inputs/objc_implementation.h b/test/decl/ext/Inputs/objc_implementation.h index f6fc4856df29f..dac9bf6ad6ebe 100644 --- a/test/decl/ext/Inputs/objc_implementation.h +++ b/test/decl/ext/Inputs/objc_implementation.h @@ -12,7 +12,16 @@ @end -@interface ObjCClass : ObjCBaseClass +@protocol ObjCProto + +- (instancetype)initFromProtocol1:(int)param; +- (instancetype)initFromProtocol2:(int)param; + +@end + +@interface ObjCClass : ObjCBaseClass + +- (instancetype)initNotFromProtocol:(int)param; - (void)methodFromHeader1:(int)param; - (void)methodFromHeader2:(int)param; diff --git a/test/decl/ext/objc_implementation.swift b/test/decl/ext/objc_implementation.swift index ba0cba881b161..9c27e5a502a55 100644 --- a/test/decl/ext/objc_implementation.swift +++ b/test/decl/ext/objc_implementation.swift @@ -145,6 +145,21 @@ // OK } + @objc(initFromProtocol1:) + required public init?(fromProtocol1: CInt) { + // OK + } + + @objc(initFromProtocol2:) + public init?(fromProtocol2: CInt) { + // expected-error@-1 {{initializer 'init(fromProtocol2:)' should be 'required' to match initializer declared by the header}} {{3-3=required }} + } + + @objc(initNotFromProtocol:) + required public init?(notFromProtocol: CInt) { + // expected-error@-1 {{initializer 'init(notFromProtocol:)' should not be 'required' to match initializer declared by the header}} {{3-12=}} + } + class func classMethod1(_: CInt) { // OK } diff --git a/test/decl/ext/objc_implementation_conflicts.swift b/test/decl/ext/objc_implementation_conflicts.swift index 3fbd480d8c78c..c17348e6f47f3 100644 --- a/test/decl/ext/objc_implementation_conflicts.swift +++ b/test/decl/ext/objc_implementation_conflicts.swift @@ -146,6 +146,24 @@ import objc_implementation_private super.init(fromSuperclass2: v) } + @objc(initFromProtocol1:) + required public init?(fromProtocol1 v: CInt) { + // OK + super.init(fromSuperclass: v) + } + + @objc(initFromProtocol2:) + required public init?(fromProtocol2 v: CInt) { + // OK + super.init(fromSuperclass: v) + } + + @objc(initNotFromProtocol:) + public init?(notFromProtocol v: CInt) { + // OK + super.init(fromSuperclass: v) + } + class func classMethod1(_: CInt) {} class func classMethod2(_: CInt) {} class func classMethod3(_: CInt) {} diff --git a/test/sil-func-extractor/basic.swift b/test/sil-func-extractor/basic.swift index e60a995da7b73..536a61cc0c13b 100644 --- a/test/sil-func-extractor/basic.swift +++ b/test/sil-func-extractor/basic.swift @@ -46,7 +46,7 @@ // EXTRACT-INIT-LABEL: sil @$s5basic7VehicleC1nACSi_tcfc : $@convention(method) (Int, @owned Vehicle) -> @owned Vehicle { // EXTRACT-INIT: bb0 // EXTRACT-INIT-NEXT: ref_element_addr -// EXTRACT-INIT-NEXT: begin_access [modify] [dynamic] +// EXTRACT-INIT-NEXT: begin_access [init] [static] // EXTRACT-INIT-NEXT: store // EXTRACT-INIT-NEXT: end_access // EXTRACT-INIT-NEXT: return diff --git a/utils/sil-mode.el b/utils/sil-mode.el index 2961efed1f36a..c349be82f7843 100644 --- a/utils/sil-mode.el +++ b/utils/sil-mode.el @@ -130,7 +130,7 @@ ;; swift declaration as well handled at the top. `(,(regexp-opt '("init_enum_data_addr" "unchecked_enum_data" "unchecked_take_enum_data_addr" "inject_enum_addr" - "select_enum" "select_value" "select_enum_addr") + "select_enum" "select_enum_addr") 'words) . font-lock-keyword-face) ;; Protocol and Protocol Composition Types `(,(regexp-opt '("init_existential_addr" "deinit_existential_addr" diff --git a/utils/vim/syntax/sil.vim b/utils/vim/syntax/sil.vim index 9c9acd363a430..132aa4031144b 100644 --- a/utils/vim/syntax/sil.vim +++ b/utils/vim/syntax/sil.vim @@ -103,7 +103,7 @@ syn keyword swiftKeyword convert_function thick_to_objc_metatype objc_to_thick_m syn keyword swiftKeyword objc_existential_metatype_to_object objc_metatype_to_object objc_protocol skipwhite syn keyword swiftKeyword unconditional_checked_cast unconditional_checked_cast_addr unconditional_checked_cast_value skipwhite syn keyword swiftKeyword cond_fail skipwhite -syn keyword swiftKeyword unreachable return throw br cond_br switch_value select_enum select_enum_addr select_value switch_enum switch_enum_addr dynamic_method_br checked_cast_br checked_cast_value_br checked_cast_addr_br skipwhite +syn keyword swiftKeyword unreachable return throw br cond_br switch_value select_enum select_enum_addr switch_enum switch_enum_addr dynamic_method_br checked_cast_br checked_cast_value_br checked_cast_addr_br skipwhite syn keyword swiftKeyword project_box project_existential_box project_block_storage init_block_storage_header copy_block mark_dependence skipwhite syn keyword swiftTypeDefinition class extension protocol struct typealias enum skipwhite nextgroup=swiftTypeName