@@ -1329,6 +1329,17 @@ static SILInstruction *beginOfInterpolation(ApplyInst *oslogInit) {
1329
1329
worklist.push_back (storeInst);
1330
1330
candidateStartInstructions.insert (storeInst);
1331
1331
}
1332
+ // Skip other uses of alloc_stack including function calls on the
1333
+ // alloc_stack and data dependenceis through them. This is done because
1334
+ // all functions using the alloc_stack are expected to be constant evaluated
1335
+ // and therefore should only be passed constants or auto closures. These
1336
+ // constants must be constructed immediately before the call and would only
1337
+ // appear in the SIL after the alloc_stack instruction. This invariant is
1338
+ // relied upon here so as to restrict the backward dependency search, which
1339
+ // in turn keeps the code that is constant evaluated small.
1340
+ // Note that if the client code violates this assumption, it will be
1341
+ // diagnosed by this pass (in function detectAndDiagnoseErrors) as it will
1342
+ // result in non-constant values for OSLogMessage instance.
1332
1343
}
1333
1344
1334
1345
// Find the first basic block in the control-flow order. Typically, if
@@ -1342,14 +1353,27 @@ static SILInstruction *beginOfInterpolation(ApplyInst *oslogInit) {
1342
1353
}
1343
1354
1344
1355
SILBasicBlock *firstBB = nullptr ;
1345
- SILBasicBlock *entryBB = oslogInit->getFunction ()->getEntryBlock ();
1346
- for (SILBasicBlock *bb: llvm::breadth_first<SILBasicBlock *>(entryBB)) {
1347
- if (candidateBBs.count (bb)) {
1348
- firstBB = bb;
1349
- break ;
1356
+ if (candidateBBs.size () == 1 ) {
1357
+ firstBB = *candidateBBs.begin ();
1358
+ } else {
1359
+ SILBasicBlock *entryBB = oslogInit->getFunction ()->getEntryBlock ();
1360
+ for (SILBasicBlock *bb : llvm::breadth_first<SILBasicBlock *>(entryBB)) {
1361
+ if (candidateBBs.count (bb)) {
1362
+ firstBB = bb;
1363
+ break ;
1364
+ }
1365
+ }
1366
+ if (!firstBB) {
1367
+ // This case will be reached only if the log call appears in unreachable
1368
+ // code and, for some reason, its data depedencies extend beyond a basic
1369
+ // block. This case should generally not happen unless the library
1370
+ // implementation of the os log APIs change. It is better to warn in this
1371
+ // case, rather than skipping the call silently.
1372
+ diagnose (callee->getASTContext (), oslogInit->getLoc ().getSourceLoc (),
1373
+ diag::oslog_call_in_unreachable_code);
1374
+ return nullptr ;
1350
1375
}
1351
1376
}
1352
- assert (firstBB);
1353
1377
1354
1378
// Iterate over the instructions in the firstBB and find the instruction that
1355
1379
// starts the interpolation.
@@ -1360,7 +1384,7 @@ static SILInstruction *beginOfInterpolation(ApplyInst *oslogInit) {
1360
1384
break ;
1361
1385
}
1362
1386
}
1363
- assert (startInst);
1387
+ assert (startInst && " could not find beginning of interpolation " );
1364
1388
return startInst;
1365
1389
}
1366
1390
@@ -1450,7 +1474,10 @@ class OSLogOptimization : public SILFunctionTransform {
1450
1474
// iteration.
1451
1475
for (auto *oslogInit : oslogMessageInits) {
1452
1476
SILInstruction *interpolationStart = beginOfInterpolation (oslogInit);
1453
- assert (interpolationStart);
1477
+ if (!interpolationStart) {
1478
+ // The log call is in unreachable code here.
1479
+ continue ;
1480
+ }
1454
1481
madeChange |= constantFold (interpolationStart, oslogInit, assertConfig);
1455
1482
}
1456
1483
0 commit comments