|
57 | 57 | #include "llvm/ADT/SmallString.h" |
58 | 58 | #include "llvm/ADT/StringSwitch.h" |
59 | 59 | #include "llvm/Support/Debug.h" |
| 60 | +#include "swift/AST/DiagnosticsSIL.h" |
60 | 61 | #include "swift/AST/ProtocolConformance.h" |
61 | 62 | #include "swift/AST/SubstitutionMap.h" |
62 | 63 | #include "swift/Basic/Assertions.h" |
@@ -100,12 +101,32 @@ void SILLinkerVisitor::deserializeAndPushToWorklist(SILFunction *F) { |
100 | 101 |
|
101 | 102 | /// Deserialize a function and add it to the worklist for processing. |
102 | 103 | void SILLinkerVisitor::maybeAddFunctionToWorklist( |
103 | | - SILFunction *F, SerializedKind_t callerSerializedKind) { |
| 104 | + SILFunction *F, SerializedKind_t callerSerializedKind, SILFunction *caller) { |
104 | 105 | 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 || |
106 | 110 | 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 | + |
109 | 130 | if (!F->isExternalDeclaration()) { |
110 | 131 | // The function is already in the module, so no need to de-serialized it. |
111 | 132 | // But check if we need to set the IsSerialized flag. |
@@ -218,19 +239,22 @@ void SILLinkerVisitor::visitPartialApplyInst(PartialApplyInst *PAI) { |
218 | 239 |
|
219 | 240 | void SILLinkerVisitor::visitFunctionRefInst(FunctionRefInst *FRI) { |
220 | 241 | maybeAddFunctionToWorklist(FRI->getReferencedFunction(), |
221 | | - FRI->getFunction()->getSerializedKind()); |
| 242 | + FRI->getFunction()->getSerializedKind(), |
| 243 | + FRI->getFunction()); |
222 | 244 | } |
223 | 245 |
|
224 | 246 | void SILLinkerVisitor::visitDynamicFunctionRefInst( |
225 | 247 | DynamicFunctionRefInst *FRI) { |
226 | 248 | maybeAddFunctionToWorklist(FRI->getInitiallyReferencedFunction(), |
227 | | - FRI->getFunction()->getSerializedKind()); |
| 249 | + FRI->getFunction()->getSerializedKind(), |
| 250 | + FRI->getFunction()); |
228 | 251 | } |
229 | 252 |
|
230 | 253 | void SILLinkerVisitor::visitPreviousDynamicFunctionRefInst( |
231 | 254 | PreviousDynamicFunctionRefInst *FRI) { |
232 | 255 | maybeAddFunctionToWorklist(FRI->getInitiallyReferencedFunction(), |
233 | | - FRI->getFunction()->getSerializedKind()); |
| 256 | + FRI->getFunction()->getSerializedKind(), |
| 257 | + FRI->getFunction()); |
234 | 258 | } |
235 | 259 |
|
236 | 260 | // Eagerly visiting all used conformances leads to a large blowup |
@@ -470,6 +494,9 @@ void SILLinkerVisitor::process() { |
470 | 494 | for (auto &BB : *Fn) { |
471 | 495 | for (auto &I : BB) { |
472 | 496 | visit(&I); |
| 497 | + |
| 498 | + if (hasError) |
| 499 | + return; |
473 | 500 | } |
474 | 501 | } |
475 | 502 | } |
|
0 commit comments