Skip to content

Commit da187ea

Browse files
committed
[verify][swift] Allow passing swifterror to phi instructions
1 parent 25fc52e commit da187ea

File tree

2 files changed

+76
-14
lines changed

2 files changed

+76
-14
lines changed

llvm/lib/IR/Verifier.cpp

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3653,18 +3653,36 @@ void Verifier::visitCallBase(CallBase &Call) {
36533653
// well.
36543654
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
36553655
if (Call.paramHasAttr(i, Attribute::SwiftError)) {
3656-
Value *SwiftErrorArg = Call.getArgOperand(i);
3657-
if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) {
3658-
Check(AI->isSwiftError(),
3659-
"swifterror argument for call has mismatched alloca", AI, Call);
3660-
continue;
3656+
SetVector<const Value *> Args;
3657+
Args.insert(Call.getArgOperand(i));
3658+
bool DidChange;
3659+
do {
3660+
DidChange = false;
3661+
// Inherit the incoming values of phi instructions to capture all
3662+
// values.
3663+
for (const Value *Arg : Args)
3664+
if (auto *PhiI = dyn_cast<PHINode>(Arg))
3665+
for (const auto &Op : PhiI->incoming_values())
3666+
DidChange |= Args.insert(Op.get());
3667+
} while (DidChange);
3668+
3669+
for (const Value *SwiftErrorArg : Args) {
3670+
if (isa<PHINode>(SwiftErrorArg))
3671+
continue;
3672+
if (auto AI =
3673+
dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) {
3674+
Check(AI->isSwiftError(),
3675+
"swifterror argument for call has mismatched alloca", AI, Call);
3676+
continue;
3677+
}
3678+
auto ArgI = dyn_cast<Argument>(SwiftErrorArg);
3679+
Check(ArgI,
3680+
"swifterror argument should come from an alloca or parameter",
3681+
SwiftErrorArg, Call);
3682+
Check(ArgI->hasSwiftErrorAttr(),
3683+
"swifterror argument for call has mismatched parameter", ArgI,
3684+
Call);
36613685
}
3662-
auto ArgI = dyn_cast<Argument>(SwiftErrorArg);
3663-
Check(ArgI, "swifterror argument should come from an alloca or parameter",
3664-
SwiftErrorArg, Call);
3665-
Check(ArgI->hasSwiftErrorAttr(),
3666-
"swifterror argument for call has mismatched parameter", ArgI,
3667-
Call);
36683686
}
36693687

36703688
if (Attrs.hasParamAttr(i, Attribute::ImmArg)) {
@@ -4356,11 +4374,23 @@ void Verifier::verifySwiftErrorCall(CallBase &Call,
43564374
}
43574375

43584376
void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) {
4377+
SetVector<const User *> Users(SwiftErrorVal->users().begin(),
4378+
SwiftErrorVal->users().end());
4379+
bool DidChange;
4380+
do {
4381+
DidChange = false;
4382+
// Inherit the users of phi instructions to capture all users.
4383+
for (const User *U : Users)
4384+
if (auto PhiI = dyn_cast<PHINode>(U))
4385+
for (const User *U : PhiI->users())
4386+
DidChange |= Users.insert(U);
4387+
} while (DidChange);
4388+
43594389
// Check that swifterror value is only used by loads, stores, or as
43604390
// a swifterror argument.
4361-
for (const User *U : SwiftErrorVal->users()) {
4391+
for (const User *U : Users) {
43624392
Check(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) ||
4363-
isa<InvokeInst>(U),
4393+
isa<InvokeInst>(U) || isa<PHINode>(U),
43644394
"swifterror value can only be loaded and stored from, or "
43654395
"as a swifterror argument!",
43664396
SwiftErrorVal, U);

llvm/test/Verifier/swifterror.ll

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
1+
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=swifterror
22

33
%swift_error = type {i64, i8}
44

@@ -10,6 +10,36 @@ define float @foo(ptr swifterror %error_ptr_ref) {
1010
ret float 1.0
1111
}
1212

13+
; CHECK: swifterror value can only be loaded and stored from, or as a swifterror argument!
14+
; CHECK: %ptr0 = alloca swifterror ptr, align 8
15+
; CHECK: %t = getelementptr inbounds ptr, ptr %err, i64 1
16+
; CHECK: swifterror value can only be loaded and stored from, or as a swifterror argument!
17+
; CHECK: %ptr1 = alloca swifterror ptr, align 8
18+
; CHECK: %t = getelementptr inbounds ptr, ptr %err, i64 1
19+
define float @phi(i1 %a) {
20+
entry:
21+
%ptr0 = alloca swifterror ptr, align 8
22+
%ptr1 = alloca swifterror ptr, align 8
23+
%ptr2 = alloca ptr, align 8
24+
br i1 %a, label %body, label %body2
25+
26+
body:
27+
%err = phi ptr [ %ptr0, %entry ], [ %ptr1, %body ]
28+
%t = getelementptr inbounds ptr, ptr %err, i64 1
29+
br label %body
30+
31+
; CHECK: swifterror argument for call has mismatched alloca
32+
; CHECK: %ptr2 = alloca ptr, align 8
33+
; CHECK: %call = call float @foo(ptr swifterror %err_bad)
34+
body2:
35+
%err_bad = phi ptr [ %ptr0, %entry ], [ %ptr2, %body2 ]
36+
%call = call float @foo(ptr swifterror %err_bad)
37+
br label %body2
38+
39+
end:
40+
ret float 1.0
41+
}
42+
1343
; CHECK: swifterror argument for call has mismatched alloca
1444
; CHECK: %error_ptr_ref = alloca ptr
1545
; CHECK: %call = call float @foo(ptr swifterror %error_ptr_ref)
@@ -22,12 +52,14 @@ entry:
2252
}
2353

2454
; CHECK: swifterror alloca must have pointer type
55+
; CHECK: %a = alloca swifterror i128, align 8
2556
define void @swifterror_alloca_invalid_type() {
2657
%a = alloca swifterror i128
2758
ret void
2859
}
2960

3061
; CHECK: swifterror alloca must not be array allocation
62+
; CHECK: %a = alloca swifterror ptr, i64 2, align 8
3163
define void @swifterror_alloca_array() {
3264
%a = alloca swifterror ptr, i64 2
3365
ret void

0 commit comments

Comments
 (0)