Skip to content

Commit 869e579

Browse files
Merge pull request #30076 from aschwaighofer/silgen_fix_dynamic_replacement_before_original
SILGen: Fix dynamic replacement before original function
2 parents 242e0bb + cae695e commit 869e579

File tree

4 files changed

+47
-21
lines changed

4 files changed

+47
-21
lines changed

include/swift/SIL/SILFunctionBuilder.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,16 @@ class SILFunctionBuilder {
8080
SubclassScope subclassScope = SubclassScope::NotApplicable);
8181

8282
/// Return the declaration of a function, or create it if it doesn't exist.
83-
SILFunction *
84-
getOrCreateFunction(SILLocation loc, SILDeclRef constant,
85-
ForDefinition_t forDefinition,
86-
ProfileCounter entryCount = ProfileCounter());
83+
/// Creating a function that references another function (a dynamic
84+
/// replacement) requires getting/creating a SIL function for this reference.
85+
/// In this case the function will call the \p getOrCreateDeclaration
86+
/// callback.
87+
SILFunction *getOrCreateFunction(
88+
SILLocation loc, SILDeclRef constant, ForDefinition_t forDefinition,
89+
llvm::function_ref<SILFunction *(SILLocation loc, SILDeclRef constant)>
90+
getOrCreateDeclaration = [](SILLocation loc, SILDeclRef constant)
91+
-> SILFunction * { return nullptr; },
92+
ProfileCounter entryCount = ProfileCounter());
8793

8894
/// Create a function declaration.
8995
///
@@ -104,8 +110,11 @@ class SILFunctionBuilder {
104110
SILFunction *InsertBefore = nullptr,
105111
const SILDebugScope *DebugScope = nullptr);
106112

107-
void addFunctionAttributes(SILFunction *F, DeclAttributes &Attrs,
108-
SILModule &M, SILDeclRef constant = SILDeclRef());
113+
void addFunctionAttributes(
114+
SILFunction *F, DeclAttributes &Attrs, SILModule &M,
115+
llvm::function_ref<SILFunction *(SILLocation loc, SILDeclRef constant)>
116+
getOrCreateDeclaration,
117+
SILDeclRef constant = SILDeclRef());
109118

110119
/// We do not expose this to everyone, instead we allow for our users to opt
111120
/// into this if they need to. Please do not do this in general! We only want

lib/SIL/SILFunctionBuilder.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction(
3737
return fn;
3838
}
3939

40-
void SILFunctionBuilder::addFunctionAttributes(SILFunction *F,
41-
DeclAttributes &Attrs,
42-
SILModule &M,
43-
SILDeclRef constant) {
40+
void SILFunctionBuilder::addFunctionAttributes(
41+
SILFunction *F, DeclAttributes &Attrs, SILModule &M,
42+
llvm::function_ref<SILFunction *(SILLocation loc, SILDeclRef constant)>
43+
getOrCreateDeclaration,
44+
SILDeclRef constant) {
4445

4546
for (auto *A : Attrs.getAttributes<SemanticsAttr>())
4647
F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
@@ -92,8 +93,7 @@ void SILFunctionBuilder::addFunctionAttributes(SILFunction *F,
9293
return;
9394

9495
SILDeclRef declRef(replacedDecl, constant.kind, false);
95-
auto *replacedFunc =
96-
getOrCreateFunction(replacedDecl, declRef, NotForDefinition);
96+
auto *replacedFunc = getOrCreateDeclaration(replacedDecl, declRef);
9797

9898
assert(replacedFunc->getLoweredFunctionType() ==
9999
F->getLoweredFunctionType() ||
@@ -102,10 +102,11 @@ void SILFunctionBuilder::addFunctionAttributes(SILFunction *F,
102102
F->setDynamicallyReplacedFunction(replacedFunc);
103103
}
104104

105-
SILFunction *
106-
SILFunctionBuilder::getOrCreateFunction(SILLocation loc, SILDeclRef constant,
107-
ForDefinition_t forDefinition,
108-
ProfileCounter entryCount) {
105+
SILFunction *SILFunctionBuilder::getOrCreateFunction(
106+
SILLocation loc, SILDeclRef constant, ForDefinition_t forDefinition,
107+
llvm::function_ref<SILFunction *(SILLocation loc, SILDeclRef constant)>
108+
getOrCreateDeclaration,
109+
ProfileCounter entryCount) {
109110
auto nameTmp = constant.mangle();
110111
auto constantType = mod.Types.getConstantFunctionType(
111112
TypeExpansionContext::minimal(), constant);
@@ -169,9 +170,11 @@ SILFunctionBuilder::getOrCreateFunction(SILLocation loc, SILDeclRef constant,
169170
if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
170171
auto *storage = accessor->getStorage();
171172
// Add attributes for e.g. computed properties.
172-
addFunctionAttributes(F, storage->getAttrs(), mod);
173+
addFunctionAttributes(F, storage->getAttrs(), mod,
174+
getOrCreateDeclaration);
173175
}
174-
addFunctionAttributes(F, decl->getAttrs(), mod, constant);
176+
addFunctionAttributes(F, decl->getAttrs(), mod, getOrCreateDeclaration,
177+
constant);
175178
}
176179

177180
return F;

lib/SILGen/SILGen.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,9 +612,13 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,
612612

613613
// Note: Do not provide any SILLocation. You can set it afterwards.
614614
SILGenFunctionBuilder builder(*this);
615-
auto *F = builder.getOrCreateFunction(constant.hasDecl() ? constant.getDecl()
616-
: (Decl *)nullptr,
617-
constant, forDefinition);
615+
auto &IGM = *this;
616+
auto *F = builder.getOrCreateFunction(
617+
constant.hasDecl() ? constant.getDecl() : (Decl *)nullptr, constant,
618+
forDefinition,
619+
[&IGM](SILLocation loc, SILDeclRef constant) -> SILFunction * {
620+
return IGM.getFunction(constant, NotForDefinition);
621+
});
618622
setUpForProfiling(constant, F, forDefinition);
619623

620624
assert(F && "SILFunction should have been defined");

test/SILGen/dynamically_replaceable.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,13 @@ struct WrapperWithInitialValue<T> {
418418
public struct SomeStruct {
419419
@WrapperWithInitialValue var t = false
420420
}
421+
422+
// Make sure that declaring the replacement before the original does not assert.
423+
@_dynamicReplacement(for: orig)
424+
func opaqueReplacement() -> Int {
425+
return 2
426+
}
427+
428+
dynamic func orig() -> Int {
429+
return 1
430+
}

0 commit comments

Comments
 (0)