Skip to content

Commit 6b8c341

Browse files
authored
Merge pull request #78464 from eeckstein/sil-linker-error
SILLinker: convert an assert to a compiler error message
2 parents aa49808 + 67b8c08 commit 6b8c341

File tree

5 files changed

+51
-9
lines changed

5 files changed

+51
-9
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ ERROR(embedded_swift_allocating,none,
408408
"cannot use allocating operation in -no-allocations mode", ())
409409
ERROR(embedded_capture_of_generic_value_with_deinit,none,
410410
"capturing generic non-copyable type with deinit in escaping closure not supported in embedded Swift", ())
411+
ERROR(wrong_linkage_for_serialized_function,none,
412+
"function has wrong linkage to be called from %0", (StringRef))
411413
NOTE(performance_called_from,none,
412414
"called from here", ())
413415

lib/SIL/IR/Linker.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "llvm/ADT/SmallString.h"
5858
#include "llvm/ADT/StringSwitch.h"
5959
#include "llvm/Support/Debug.h"
60+
#include "swift/AST/DiagnosticsSIL.h"
6061
#include "swift/AST/ProtocolConformance.h"
6162
#include "swift/AST/SubstitutionMap.h"
6263
#include "swift/Basic/Assertions.h"
@@ -100,12 +101,32 @@ void SILLinkerVisitor::deserializeAndPushToWorklist(SILFunction *F) {
100101

101102
/// Deserialize a function and add it to the worklist for processing.
102103
void SILLinkerVisitor::maybeAddFunctionToWorklist(
103-
SILFunction *F, SerializedKind_t callerSerializedKind) {
104+
SILFunction *F, SerializedKind_t callerSerializedKind, SILFunction *caller) {
104105
SILLinkage linkage = F->getLinkage();
105-
ASSERT((callerSerializedKind == IsNotSerialized ||
106+
107+
// Originally this was an assert. But it can happen if the user "re-defines"
108+
// an existing function with a wrong linkage, e.g. using `@_cdecl`.
109+
if(!(callerSerializedKind == IsNotSerialized ||
106110
F->hasValidLinkageForFragileRef(callerSerializedKind) ||
107-
hasSharedVisibility(linkage) || F->isExternForwardDeclaration()) &&
108-
"called function has wrong linkage for serialized function");
111+
hasSharedVisibility(linkage) || F->isExternForwardDeclaration())) {
112+
StringRef name = "a serialized function";
113+
llvm::SmallVector<char> scratch;
114+
115+
if (caller) {
116+
name = caller->getName();
117+
if (SILDeclRef declRef = caller->getDeclRef()) {
118+
if (auto *decl = declRef.getDecl()) {
119+
name = decl->getName().getString(scratch);
120+
}
121+
}
122+
}
123+
F->getModule().getASTContext().Diags.diagnose(
124+
F->getLocation().getSourceLoc(),
125+
diag::wrong_linkage_for_serialized_function, name);
126+
hasError = true;
127+
return;
128+
}
129+
109130
if (!F->isExternalDeclaration()) {
110131
// The function is already in the module, so no need to de-serialized it.
111132
// But check if we need to set the IsSerialized flag.
@@ -218,19 +239,22 @@ void SILLinkerVisitor::visitPartialApplyInst(PartialApplyInst *PAI) {
218239

219240
void SILLinkerVisitor::visitFunctionRefInst(FunctionRefInst *FRI) {
220241
maybeAddFunctionToWorklist(FRI->getReferencedFunction(),
221-
FRI->getFunction()->getSerializedKind());
242+
FRI->getFunction()->getSerializedKind(),
243+
FRI->getFunction());
222244
}
223245

224246
void SILLinkerVisitor::visitDynamicFunctionRefInst(
225247
DynamicFunctionRefInst *FRI) {
226248
maybeAddFunctionToWorklist(FRI->getInitiallyReferencedFunction(),
227-
FRI->getFunction()->getSerializedKind());
249+
FRI->getFunction()->getSerializedKind(),
250+
FRI->getFunction());
228251
}
229252

230253
void SILLinkerVisitor::visitPreviousDynamicFunctionRefInst(
231254
PreviousDynamicFunctionRefInst *FRI) {
232255
maybeAddFunctionToWorklist(FRI->getInitiallyReferencedFunction(),
233-
FRI->getFunction()->getSerializedKind());
256+
FRI->getFunction()->getSerializedKind(),
257+
FRI->getFunction());
234258
}
235259

236260
// Eagerly visiting all used conformances leads to a large blowup
@@ -470,6 +494,9 @@ void SILLinkerVisitor::process() {
470494
for (auto &BB : *Fn) {
471495
for (auto &I : BB) {
472496
visit(&I);
497+
498+
if (hasError)
499+
return;
473500
}
474501
}
475502
}

lib/SIL/IR/Linker.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, void> {
9191
/// Whether any functions were deserialized.
9292
bool Changed;
9393

94+
bool hasError = false;
95+
9496
public:
9597
SILLinkerVisitor(SILModule &M, SILModule::LinkingMode LinkingMode)
9698
: Mod(M), Worklist(), Mode(LinkingMode), Changed(false) {}
@@ -143,7 +145,8 @@ class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, void> {
143145
/// If `callerSerializedKind` is IsSerialized, then all shared
144146
/// functions which are referenced from `F` are set to be serialized.
145147
void maybeAddFunctionToWorklist(SILFunction *F,
146-
SerializedKind_t callerSerializedKind);
148+
SerializedKind_t callerSerializedKind,
149+
SILFunction *caller = nullptr);
147150

148151
/// Is the current mode link all? Link all implies we should try and link
149152
/// everything, not just transparent/shared functions.

lib/SILOptimizer/UtilityPasses/Link.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class SILLinker : public SILModuleTransform {
5151
using namespace RuntimeConstants;
5252
#define FUNCTION(ID, NAME, CC, AVAILABILITY, RETURNS, ARGS, ATTRS, EFFECT, \
5353
MEMORY_EFFECTS) \
54-
linkEmbeddedRuntimeFunctionByName(#NAME, EFFECT);
54+
linkEmbeddedRuntimeFunctionByName(#NAME, EFFECT); \
55+
if (getModule()->getASTContext().hadError()) \
56+
return;
5557

5658
#define RETURNS(...)
5759
#define ARGS(...)

test/embedded/wrong-linkage.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-swift-emit-ir %s -enable-experimental-feature Embedded -verify -wmo
2+
3+
// REQUIRES: swift_feature_Embedded
4+
5+
@_cdecl("posix_memalign")
6+
func posix_memalign(_ resultPtr:UnsafeMutablePointer<UnsafeMutableRawPointer?>, _ :Int, _ :Int) -> Int32 { // expected-error {{function has wrong linkage to be called from}}
7+
return 0
8+
}

0 commit comments

Comments
 (0)