Skip to content

Commit f3de468

Browse files
authored
Merge pull request #401 from swiftwasm/master
[pull] swiftwasm from master
2 parents 39508a4 + bf51db3 commit f3de468

File tree

7 files changed

+150
-43
lines changed

7 files changed

+150
-43
lines changed

CMakeLists.txt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,11 +1041,13 @@ if(SWIFT_BUILD_SYNTAXPARSERLIB OR SWIFT_BUILD_SOURCEKIT)
10411041
set(SOURCEKIT_RUNTIME_DIR lib)
10421042
endif()
10431043
add_dependencies(sourcekit-inproc BlocksRuntime dispatch)
1044-
swift_install_in_component(FILES
1045-
$<TARGET_FILE:dispatch>
1046-
$<TARGET_FILE:BlocksRuntime>
1047-
DESTINATION ${SOURCEKIT_RUNTIME_DIR}
1048-
COMPONENT sourcekit-inproc)
1044+
if("${SWIFT_HOST_VARIANT_SDK}" MATCHES "OSX|WINDOWS")
1045+
swift_install_in_component(FILES
1046+
$<TARGET_FILE:dispatch>
1047+
$<TARGET_FILE:BlocksRuntime>
1048+
DESTINATION ${SOURCEKIT_RUNTIME_DIR}
1049+
COMPONENT sourcekit-inproc)
1050+
endif()
10491051
if(SWIFT_HOST_VARIANT_SDK STREQUAL WINDOWS)
10501052
swift_install_in_component(FILES
10511053
$<TARGET_LINKER_FILE:dispatch>

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ source code and up to 70 GB of disk space for the build artifacts with full
7878
debugging. Depending on your machine, a clean build can take a few minutes to
7979
several hours. Naturally, incremental builds are much faster.
8080

81+
Once you are able to build things successfully and have a compile-test-debug
82+
loop going, check out the [development tips][docs/DevelopmentTips.md] for
83+
better productivity while working on the compiler.
8184

8285
### System Requirements
8386

include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ class BasicBlockCloner;
3333
class SILLoop;
3434
class SILLoopInfo;
3535

36+
/// Compute the set of reachable blocks.
37+
class ReachableBlocks {
38+
SmallPtrSet<SILBasicBlock *, 32> visited;
39+
40+
public:
41+
/// Invoke \p visitor for each reachable block in \p f in worklist order (at
42+
/// least one predecessor has been visited--defs are always visited before
43+
/// uses except for phi-type block args). The \p visitor takes a block
44+
/// argument, which is already marked visited, and must return true to
45+
/// continue visiting blocks.
46+
///
47+
/// Returns true if all reachable blocks were visited.
48+
bool visit(SILFunction *f, function_ref<bool(SILBasicBlock *)> visitor);
49+
50+
/// Return true if \p bb has been visited.
51+
bool isVisited(SILBasicBlock *bb) const { return visited.count(bb); }
52+
};
53+
3654
/// Remove all instructions in the body of \p bb in safe manner by using
3755
/// undef.
3856
void clearBlockBody(SILBasicBlock *bb);

lib/SILOptimizer/Analysis/EscapeAnalysis.cpp

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/SILOptimizer/Analysis/ArraySemantic.h"
1919
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
2020
#include "swift/SILOptimizer/PassManager/PassManager.h"
21+
#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
2122
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
2223
#include "llvm/Support/CommandLine.h"
2324
#include "llvm/Support/GraphWriter.h"
@@ -1585,17 +1586,19 @@ void EscapeAnalysis::ConnectionGraph::verify() const {
15851586
verifyStructure();
15861587

15871588
// Verify that all pointer nodes are still mapped, otherwise the process of
1588-
// merging nodes may have lost information.
1589-
for (SILBasicBlock &BB : *F) {
1590-
for (auto &I : BB) {
1591-
if (isNonWritableMemoryAddress(&I))
1589+
// merging nodes may have lost information. Only visit reachable blocks,
1590+
// because the graph builder only mapped values from reachable blocks.
1591+
ReachableBlocks reachable;
1592+
reachable.visit(F, [this](SILBasicBlock *bb) {
1593+
for (auto &i : *bb) {
1594+
if (isNonWritableMemoryAddress(&i))
15921595
continue;
15931596

1594-
if (auto ai = dyn_cast<ApplyInst>(&I)) {
1597+
if (auto ai = dyn_cast<ApplyInst>(&i)) {
15951598
if (EA->canOptimizeArrayUninitializedCall(ai, this).isValid())
15961599
continue;
15971600
}
1598-
for (auto result : I.getResults()) {
1601+
for (auto result : i.getResults()) {
15991602
if (EA->getPointerBase(result))
16001603
continue;
16011604

@@ -1611,7 +1614,8 @@ void EscapeAnalysis::ConnectionGraph::verify() const {
16111614
}
16121615
}
16131616
}
1614-
}
1617+
return true;
1618+
});
16151619
#endif
16161620
}
16171621

@@ -1705,27 +1709,21 @@ void EscapeAnalysis::buildConnectionGraph(FunctionInfo *FInfo,
17051709
ConnectionGraph *ConGraph = &FInfo->Graph;
17061710
assert(ConGraph->isEmpty());
17071711

1708-
// We use a worklist for iteration to visit the blocks in dominance order.
1709-
llvm::SmallPtrSet<SILBasicBlock*, 32> VisitedBlocks;
1710-
llvm::SmallVector<SILBasicBlock *, 16> WorkList;
1711-
VisitedBlocks.insert(&*ConGraph->F->begin());
1712-
WorkList.push_back(&*ConGraph->F->begin());
1713-
1714-
while (!WorkList.empty()) {
1715-
SILBasicBlock *BB = WorkList.pop_back_val();
1716-
1712+
// Visit the blocks in dominance order.
1713+
ReachableBlocks reachable;
1714+
reachable.visit(ConGraph->F, [&](SILBasicBlock *bb) {
17171715
// Create edges for the instructions.
1718-
for (auto &I : *BB) {
1719-
analyzeInstruction(&I, FInfo, BottomUpOrder, RecursionDepth);
1716+
for (auto &i : *bb) {
1717+
analyzeInstruction(&i, FInfo, BottomUpOrder, RecursionDepth);
17201718
}
1721-
for (auto &Succ : BB->getSuccessors()) {
1722-
if (VisitedBlocks.insert(Succ.getBB()).second)
1723-
WorkList.push_back(Succ.getBB());
1724-
}
1725-
}
1719+
return true;
1720+
});
17261721

17271722
// Second step: create defer-edges for block arguments.
17281723
for (SILBasicBlock &BB : *ConGraph->F) {
1724+
if (!reachable.isVisited(&BB))
1725+
continue;
1726+
17291727
if (!linkBBArgs(&BB))
17301728
continue;
17311729

lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,30 @@
1717

1818
using namespace swift;
1919

20+
/// Invoke \p visitor for each reachable block in \p f in worklist order (at
21+
/// least one predecessor has been visited).
22+
bool ReachableBlocks::visit(SILFunction *f,
23+
function_ref<bool(SILBasicBlock *)> visitor) {
24+
assert(visited.empty() && "blocks already visited");
25+
26+
// Walk over the CFG, starting at the entry block, until all reachable blocks
27+
// are visited.
28+
SILBasicBlock *entryBB = f->getEntryBlock();
29+
SmallVector<SILBasicBlock *, 8> worklist = {entryBB};
30+
visited.insert(entryBB);
31+
while (!worklist.empty()) {
32+
SILBasicBlock *bb = worklist.pop_back_val();
33+
if (!visitor(bb))
34+
return false;
35+
36+
for (auto &succ : bb->getSuccessors()) {
37+
if (visited.insert(succ).second)
38+
worklist.push_back(succ);
39+
}
40+
}
41+
return true;
42+
}
43+
2044
/// Remove all instructions in the body of \p bb in safe manner by using
2145
/// undef.
2246
void swift::clearBlockBody(SILBasicBlock *bb) {
@@ -42,25 +66,16 @@ void swift::removeDeadBlock(SILBasicBlock *bb) {
4266
}
4367

4468
bool swift::removeUnreachableBlocks(SILFunction &f) {
45-
// All reachable blocks, but does not include the entry block.
46-
llvm::SmallPtrSet<SILBasicBlock *, 8> visited;
47-
48-
// Walk over the CFG, starting at the entry block, until all reachable blocks are visited.
49-
llvm::SmallVector<SILBasicBlock *, 8> worklist(1, f.getEntryBlock());
50-
while (!worklist.empty()) {
51-
SILBasicBlock *bb = worklist.pop_back_val();
52-
for (auto &Succ : bb->getSuccessors()) {
53-
if (visited.insert(Succ).second)
54-
worklist.push_back(Succ);
55-
}
56-
}
69+
ReachableBlocks reachable;
70+
// Visit all the blocks without doing any extra work.
71+
reachable.visit(&f, [](SILBasicBlock *) { return true; });
5772

58-
// Remove the blocks we never reached. Exclude the entry block from the iteration because it's
59-
// not included in the Visited set.
73+
// Remove the blocks we never reached. Assume the entry block is visited.
74+
// Reachable's visited set contains dangling pointers during this loop.
6075
bool changed = false;
6176
for (auto ii = std::next(f.begin()), end = f.end(); ii != end;) {
6277
auto *bb = &*ii++;
63-
if (!visited.count(bb)) {
78+
if (!reachable.isVisited(bb)) {
6479
removeDeadBlock(bb);
6580
changed = true;
6681
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
2+
// REQUIRES: asserts
3+
4+
sil_stage canonical
5+
6+
class Klass {}
7+
8+
class KlassUser {
9+
var field: Klass
10+
}
11+
12+
// CHECK-LABEL: Function: 'simple_error_ref_element_addr'
13+
// CHECK-NEXT: Found use after free?!
14+
// CHECK-NEXT: Value: %1 = begin_borrow %0 : $KlassUser // users: %3, %2
15+
// CHECK-NEXT: Consuming User: end_borrow %1 : $KlassUser // id: %3
16+
// CHECK-NEXT: Non Consuming User: %5 = load [copy] %2 : $*Klass // user: %6
17+
// CHECK-NEXT: Block: bb0
18+
sil [ossa] @simple_error_ref_element_addr : $@convention(thin) (@owned KlassUser) -> @owned Klass {
19+
bb0(%0 : @owned $KlassUser):
20+
%1 = begin_borrow %0 : $KlassUser
21+
%2 = ref_element_addr %1 : $KlassUser, #KlassUser.field
22+
end_borrow %1 : $KlassUser
23+
destroy_value %0 : $KlassUser
24+
%3 = load [copy] %2 : $*Klass
25+
return %3 : $Klass
26+
}
27+
28+
// CHECK-LABEL: Function: 'simple_error_ref_tail_addr'
29+
// CHECK-NEXT: Found use after free?!
30+
// CHECK-NEXT: Value: %1 = begin_borrow %0 : $KlassUser // users: %3, %2
31+
// CHECK-NEXT: Consuming User: end_borrow %1 : $KlassUser // id: %3
32+
// CHECK-NEXT: Non Consuming User: %5 = load [copy] %2 : $*Klass // user: %6
33+
// CHECK-NEXT: Block: bb0
34+
sil [ossa] @simple_error_ref_tail_addr : $@convention(thin) (@owned KlassUser) -> @owned Klass {
35+
bb0(%0 : @owned $KlassUser):
36+
%1 = begin_borrow %0 : $KlassUser
37+
%2 = ref_tail_addr %1 : $KlassUser, $Klass
38+
end_borrow %1 : $KlassUser
39+
destroy_value %0 : $KlassUser
40+
%3 = load [copy] %2 : $*Klass
41+
return %3 : $Klass
42+
}

test/SILOptimizer/escape_analysis.sil

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,3 +1909,32 @@ bb0(%0 : $*SomeData):
19091909
%5 = tuple ()
19101910
return %5 : $()
19111911
}
1912+
1913+
// -----------------------------------------------------------------------------
1914+
// Unreachable blocks are not mapped to the connection graph. Test
1915+
// that verification does not assert with "Missing escape connection
1916+
// graph mapping". <rdar://problem/60373501> EscapeAnalysis crashes
1917+
// with CFG with unreachable
1918+
sil_global hidden @globalInt: $Int
1919+
1920+
// CHECK-LABEL: CG of testUnreachable
1921+
// CHECK-LABEL: End
1922+
sil hidden [noinline] @testUnreachable : $@convention(thin) () -> () {
1923+
bb0:
1924+
%g1 = global_addr @globalInt : $*Int
1925+
%a1 = begin_access [read] [dynamic] [no_nested_conflict] %g1 : $*Int // users: %18, %17
1926+
%v1 = load %a1 : $*Int
1927+
end_access %a1 : $*Int
1928+
br bb4
1929+
1930+
bb2:
1931+
%g2 = global_addr @globalInt : $*Int
1932+
%a2 = begin_access [read] [dynamic] [no_nested_conflict] %g2 : $*Int // users: %18, %17
1933+
%v2 = load %a2 : $*Int
1934+
end_access %a2 : $*Int
1935+
br bb4
1936+
1937+
bb4:
1938+
%z = tuple ()
1939+
return %z : $()
1940+
}

0 commit comments

Comments
 (0)