Skip to content

[AddressLowering] Handle try_apply with enum'd return. #61963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/Android.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ $ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libBlo
In addition, you'll also need to copy the Android NDK's libc++:

```
$ adb push /path/to/android-ndk-r25b/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so /data/local/tmp
$ adb push /path/to/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so /data/local/tmp
```

Finally, you'll need to copy the `hello` executable you built in the
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/ModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ struct InterfaceSubContextDelegate {
StringRef interfacePath,
StringRef outputPath,
SourceLoc diagLoc,
bool silenceErrors,
llvm::function_ref<std::error_code(SubCompilerInstanceInfo&)> action) = 0;

virtual ~InterfaceSubContextDelegate() = default;
Expand Down
1 change: 1 addition & 0 deletions include/swift/Frontend/ModuleInterfaceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
StringRef interfacePath,
StringRef outputPath,
SourceLoc diagLoc,
bool silenceErrors,
llvm::function_ref<std::error_code(SubCompilerInstanceInfo&)> action) override;

~InterfaceSubContextDelegateImpl() = default;
Expand Down
1 change: 1 addition & 0 deletions lib/Frontend/ModuleInterfaceBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ bool ImplicitModuleInterfaceBuilder::buildSwiftModuleInternal(

SubError = (bool)subASTDelegate.runInSubCompilerInstance(
moduleName, interfacePath, OutPath, diagnosticLoc,
silenceInterfaceDiagnostics,
[&](SubCompilerInstanceInfo &info) {
auto EBuilder = ExplicitModuleInterfaceBuilder(
*info.Instance, rebuildDiags, sourceMgr, moduleCachePath, backupInterfaceDir,
Expand Down
7 changes: 5 additions & 2 deletions lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1725,7 +1725,8 @@ InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName,
SourceLoc diagLoc,
llvm::function_ref<std::error_code(ASTContext&, ModuleDecl*, ArrayRef<StringRef>,
ArrayRef<StringRef>, StringRef)> action) {
return runInSubCompilerInstance(moduleName, interfacePath, outputPath, diagLoc,
return runInSubCompilerInstance(moduleName, interfacePath, outputPath,
diagLoc, /*silenceErrors=*/false,
[&](SubCompilerInstanceInfo &info){
return action(info.Instance->getASTContext(),
info.Instance->getMainModule(),
Expand All @@ -1740,6 +1741,7 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
StringRef interfacePath,
StringRef outputPath,
SourceLoc diagLoc,
bool silenceErrors,
llvm::function_ref<std::error_code(SubCompilerInstanceInfo&)> action) {
// We are about to mess up the compiler invocation by using the compiler
// arguments in the textual interface file. So copy to use a new compiler
Expand Down Expand Up @@ -1834,7 +1836,8 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
subInstance.getSourceMgr().setFileSystem(SM.getFileSystem());

ForwardingDiagnosticConsumer FDC(*Diags);
subInstance.addDiagnosticConsumer(&FDC);
if (!silenceErrors)
subInstance.addDiagnosticConsumer(&FDC);
std::string InstanceSetupError;
if (subInstance.setup(subInvocation, InstanceSetupError)) {
return std::make_error_code(std::errc::not_supported);
Expand Down
68 changes: 49 additions & 19 deletions lib/SILOptimizer/IPO/ClosureSpecializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,8 @@ static bool canSpecializeFullApplySite(FullApplySiteKind kind) {
llvm_unreachable("covered switch");
}

const int SpecializationLevelLimit = 2;

static int getSpecializationLevelRecursive(StringRef funcName, Demangler &parent) {
using namespace Demangle;

Expand All @@ -1098,23 +1100,44 @@ static int getSpecializationLevelRecursive(StringRef funcName, Demangler &parent
return 0;
if (funcSpec->getKind() != Node::Kind::FunctionSignatureSpecialization)
return 0;
Node *param = funcSpec->getChild(1);
if (param->getKind() != Node::Kind::FunctionSignatureSpecializationParam)
return 0;
if (param->getNumChildren() < 2)
return 0;
Node *kindNd = param->getChild(0);
if (kindNd->getKind() != Node::Kind::FunctionSignatureSpecializationParamKind)
return 0;
auto kind = FunctionSigSpecializationParamKind(kindNd->getIndex());
if (kind != FunctionSigSpecializationParamKind::ConstantPropFunction)
return 0;

Node *payload = param->getChild(1);
if (payload->getKind() != Node::Kind::FunctionSignatureSpecializationParamPayload)
return 1;
// Check if the specialized function is a specialization itself.
return 1 + getSpecializationLevelRecursive(payload->getText(), demangler);

// Match any function specialization. We check for constant propagation at the
// parameter level.
Node *param = funcSpec->getChild(0);
if (param->getKind() != Node::Kind::SpecializationPassID)
return SpecializationLevelLimit + 1; // unrecognized format

unsigned maxParamLevel = 0;
for (unsigned paramIdx = 1; paramIdx < funcSpec->getNumChildren();
++paramIdx) {
Node *param = funcSpec->getChild(paramIdx);
if (param->getKind() != Node::Kind::FunctionSignatureSpecializationParam)
return SpecializationLevelLimit + 1; // unrecognized format

// A parameter is recursive if it has a kind with index and type payload
if (param->getNumChildren() < 2)
continue;

Node *kindNd = param->getChild(0);
if (kindNd->getKind()
!= Node::Kind::FunctionSignatureSpecializationParamKind) {
return SpecializationLevelLimit + 1; // unrecognized format
}
auto kind = FunctionSigSpecializationParamKind(kindNd->getIndex());
if (kind != FunctionSigSpecializationParamKind::ConstantPropFunction)
continue;
Node *payload = param->getChild(1);
if (payload->getKind()
!= Node::Kind::FunctionSignatureSpecializationParamPayload) {
return SpecializationLevelLimit + 1; // unrecognized format
}
// Check if the specialized function is a specialization itself.
unsigned paramLevel =
1 + getSpecializationLevelRecursive(payload->getText(), demangler);
if (paramLevel > maxParamLevel)
maxParamLevel = paramLevel;
}
return maxParamLevel;
}

/// If \p function is a function-signature specialization for a constant-
Expand Down Expand Up @@ -1328,9 +1351,10 @@ bool SILClosureSpecializerTransform::gatherCallSites(
//
// A limit of 2 is good enough and will not be exceed in "regular"
// optimization scenarios.
if (getSpecializationLevel(getClosureCallee(ClosureInst)) > 2)
if (getSpecializationLevel(getClosureCallee(ClosureInst))
> SpecializationLevelLimit) {
continue;

}
// Compute the final release points of the closure. We will insert
// release of the captured arguments here.
if (!CInfo)
Expand Down Expand Up @@ -1395,6 +1419,8 @@ bool SILClosureSpecializerTransform::specialize(SILFunction *Caller,
if (!NewF) {
NewF = ClosureSpecCloner::cloneFunction(FuncBuilder, CSDesc, NewFName);
addFunctionToPassManagerWorklist(NewF, CSDesc.getApplyCallee());
LLVM_DEBUG(llvm::dbgs() << "\nThe rewritten callee is:\n";
NewF->dump());
}

// Rewrite the call
Expand All @@ -1404,6 +1430,10 @@ bool SILClosureSpecializerTransform::specialize(SILFunction *Caller,
Changed = true;
}
}
LLVM_DEBUG(if (Changed) {
llvm::dbgs() << "\nThe rewritten caller is:\n";
Caller->dump();
});
return Changed;
}

Expand Down
44 changes: 40 additions & 4 deletions lib/SILOptimizer/Mandatory/AddressLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ void OpaqueStorageAllocation::allocatePhi(PhiValue phi) {
coalescedPhi.coalesce(phi, pass.valueStorageMap);

SmallVector<SILValue, 4> coalescedValues;
coalescedValues.resize(coalescedPhi.getCoalescedOperands().size());
coalescedValues.reserve(coalescedPhi.getCoalescedOperands().size());
for (SILValue value : coalescedPhi.getCoalescedValues())
coalescedValues.push_back(value);

Expand Down Expand Up @@ -3011,7 +3011,7 @@ void UseRewriter::visitSwitchEnumInst(SwitchEnumInst * switchEnum) {
return;

assert(caseBB->getArguments().size() == 1);
SILArgument *caseArg = caseBB->getArguments()[0];
SILArgument *caseArg = caseBB->getArgument(0);

assert(&switchEnum->getOperandRef(0) == getReusedStorageOperand(caseArg));
assert(caseDecl->hasAssociatedValues() && "caseBB has a payload argument");
Expand Down Expand Up @@ -3053,6 +3053,20 @@ void UseRewriter::visitSwitchEnumInst(SwitchEnumInst * switchEnum) {
defaultCounter = switchEnum->getDefaultCount();
if (auto defaultDecl = switchEnum->getUniqueCaseForDefault()) {
rewriteCase(defaultDecl.get(), defaultBB);
} else {
assert(defaultBB->getArguments().size() == 1);
SILArgument *arg = defaultBB->getArgument(0);
assert(arg->getType().isAddressOnly(*pass.function));
auto builder = pass.getBuilder(defaultBB->begin());
auto addr = enumAddr;
auto *load = builder.createTrivialLoadOr(switchEnum->getLoc(), addr,
LoadOwnershipQualifier::Take);
// Remap arg to the new dummy load which will be deleted during
// deleteRewrittenInstructions.
arg->replaceAllUsesWith(load);
pass.valueStorageMap.replaceValue(arg, load);
markRewritten(load, addr);
defaultBB->eraseArgument(0);
}
}
auto builder = pass.getTermBuilder(switchEnum);
Expand Down Expand Up @@ -3158,6 +3172,12 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
protected:
// Set the storage address for an opaque block arg and mark it rewritten.
void rewriteArg(SILPhiArgument *arg) {
if (auto *tai =
dyn_cast_or_null<TryApplyInst>(arg->getTerminatorForResult())) {
CallArgRewriter(tai, pass).rewriteArguments();
ApplyRewriter(tai, pass).convertApplyWithIndirectResults();
return;
}
LLVM_DEBUG(llvm::dbgs() << "REWRITE ARG "; arg->dump());
if (storage.storageAddress)
LLVM_DEBUG(llvm::dbgs() << " STORAGE "; storage.storageAddress->dump());
Expand Down Expand Up @@ -3357,13 +3377,29 @@ static void rewriteFunction(AddressLoweringState &pass) {
DefRewriter::rewriteValue(valueDef, pass);
valueAndStorage.storage.markRewritten();
}
// The def of interest may have been changed by rewriteValue. Get that
// redefinition back out of the ValueStoragePair.
valueDef = valueAndStorage.value;
// Rewrite a use of any non-address value mapped to storage (does not
// include the already rewritten uses of indirect arguments).
if (valueDef->getType().isAddress())
continue;

SmallPtrSet<Operand *, 8> originalUses;
SmallVector<Operand *, 8> uses(valueDef->getUses());
for (Operand *oper : uses) {
for (auto *oper : uses) {
originalUses.insert(oper);
UseRewriter::rewriteUse(oper, pass);
}
// Rewrite every new uses that was added.
uses.clear();
for (auto *use : valueDef->getUses()) {
if (originalUses.contains(use))
continue;
uses.push_back(use);
}
for (auto *oper : uses) {
assert(isa<DebugValueInst>(oper->getUser()));
UseRewriter::rewriteUse(oper, pass);
}
}
Expand Down Expand Up @@ -3396,7 +3432,7 @@ static void filterDeadArgs(OperandValueArrayRef origArgs,
SmallVectorImpl<SILValue> &newArgs) {
auto nextDeadArgI = deadArgIndices.begin();
for (unsigned i : indices(origArgs)) {
if (i == *nextDeadArgI) {
if (i == *nextDeadArgI && nextDeadArgI != deadArgIndices.end()) {
++nextDeadArgI;
continue;
}
Expand Down
2 changes: 2 additions & 0 deletions test/ASTGen/verify-parse.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %target-run-simple-swift(-enable-experimental-feature SwiftParser -enable-experimental-feature ParserASTGen)

// REQUIRES: executable_test

func test1(x: Int, fn: (Int) -> Int) -> Int {
let xx = fn(42)
return fn(x)
Expand Down
2 changes: 1 addition & 1 deletion test/Index/index_system_modules_swiftinterfaces.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@
// RUN: 2>&1 | %FileCheck -check-prefix=BROKEN-BUILD %s

/// We don't expect so see the swiftinterface error for indexing
// BROKEN-BUILD: indexing system module {{.*}} skipping
// BROKEN-BUILD-NOT: error
// BROKEN-BUILD-NOT: breaking_the_swifinterface
// BROKEN-BUILD: indexing system module {{.*}} skipping

/// We don't expect SystemModule to be indexed with a broken swiftinterface
// RUN: c-index-test core -print-unit %t/idx | %FileCheck -check-prefix=BROKEN-UNIT %s
Expand Down
14 changes: 6 additions & 8 deletions test/Interop/Cxx/class/constructors-copy-irgen-android.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
// Target-specific tests for C++ copy constructor code generation.

// RUN: %swift -module-name MySwift -target armv7-none-linux-androideabi -dump-clang-diagnostics -I %S/Inputs -enable-experimental-cxx-interop -emit-ir %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=ITANIUM_ARM
// RUN: %swift -module-name MySwift -target aarch64-unknown-linux-android -dump-clang-diagnostics -I %S/Inputs -enable-experimental-cxx-interop -emit-ir %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=ITANIUM_ARM

// REQUIRES: OS=linux-android || OS=linux-androideabi

// REQUIRES: CODEGENERATOR=X86
// REQUIRES: CODEGENERATOR=ARM
// REQUIRES: OS=linux-android
// REQUIRES: CPU=aarch64

import Constructors
import TypeClassification

// ITANIUM_ARM-LABEL: define protected swiftcc void @"$s7MySwift35copyWithUserProvidedCopyConstructorySo03HascdeF0V_ACtACF"
// ITANIUM_ARM-LABEL: define protected swiftcc void @"$s7MySwift35copyWithUserProvidedCopyConstructorySo03Has{{cdeF0V_ACtACF|efgH0V_ADtADF}}"
// ITANIUM_ARM-SAME: (%TSo30HasUserProvidedCopyConstructorV* {{.*}}[[ARG0:%.*]], %TSo30HasUserProvidedCopyConstructorV* {{.*}}[[ARG1:%.*]], %TSo30HasUserProvidedCopyConstructorV* {{.*}}[[ARG2:%.*]])
// ITANIUM_ARM: [[ARG0_AS_STRUCT:%.*]] = bitcast %TSo30HasUserProvidedCopyConstructorV* [[ARG0]] to %struct.HasUserProvidedCopyConstructor*
// ITANIUM_ARM: [[ARG2_AS_STRUCT:%.*]] = bitcast %TSo30HasUserProvidedCopyConstructorV* [[ARG2]] to %struct.HasUserProvidedCopyConstructor*
// ITANIUM_ARM: call %struct.HasUserProvidedCopyConstructor* @_ZN30HasUserProvidedCopyConstructorC2ERKS_(%struct.HasUserProvidedCopyConstructor* [[ARG0_AS_STRUCT]], %struct.HasUserProvidedCopyConstructor* [[ARG2_AS_STRUCT]])
// ITANIUM_ARM: call void @_ZN30HasUserProvidedCopyConstructorC2ERKS_(%struct.HasUserProvidedCopyConstructor* [[ARG0_AS_STRUCT]], %struct.HasUserProvidedCopyConstructor* [[ARG2_AS_STRUCT]])
// ITANIUM_ARM: [[ARG1_AS_STRUCT:%.*]] = bitcast %TSo30HasUserProvidedCopyConstructorV* [[ARG1]] to %struct.HasUserProvidedCopyConstructor*
// ITANIUM_ARM: [[ARG2_AS_STRUCT:%.*]] = bitcast %TSo30HasUserProvidedCopyConstructorV* [[ARG2]] to %struct.HasUserProvidedCopyConstructor*
// ITANIUM_ARM: call %struct.HasUserProvidedCopyConstructor* @_ZN30HasUserProvidedCopyConstructorC2ERKS_(%struct.HasUserProvidedCopyConstructor* [[ARG1_AS_STRUCT]], %struct.HasUserProvidedCopyConstructor* [[ARG2_AS_STRUCT]])
// ITANIUM_ARM: call void @_ZN30HasUserProvidedCopyConstructorC2ERKS_(%struct.HasUserProvidedCopyConstructor* [[ARG1_AS_STRUCT]], %struct.HasUserProvidedCopyConstructor* [[ARG2_AS_STRUCT]])
// ITANIUM_ARM: ret void

public func copyWithUserProvidedCopyConstructor(_ x: HasUserProvidedCopyConstructor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
// RUN: %swift -module-name MySwift -target x86_64-unknown-windows-msvc -dump-clang-diagnostics -I %S/Inputs -enable-experimental-cxx-interop -emit-ir %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=MICROSOFT_X64

// REQUIRES: OS=windows-msvc

// REQUIRES: CODEGENERATOR=X86
// REQUIRES: CODEGENERATOR=ARM

// REQUIRES: CPU=x86_64

import Constructors
import TypeClassification
Expand Down
Loading