Skip to content

Commit cd59d96

Browse files
authored
Merge pull request #6342 from gottesmm/some_small_fixes
[sil-ownership] Fix some cases in SILValue::getOwnershipKind().
2 parents 268c2b6 + a178ac9 commit cd59d96

File tree

4 files changed

+164
-61
lines changed

4 files changed

+164
-61
lines changed

include/swift/SIL/SILValue.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,11 @@ enum class ValueOwnershipKind : uint8_t {
9393
/// instruction exactly once along any path through the program.
9494
Guaranteed,
9595

96-
/// A SILValue with undefined ownership. This means that it could take on
97-
/// /any/ ownership semantics. This is meant only to model SILUndef.
98-
Undef,
96+
/// A SILValue with undefined ownership. It can pair with /Any/ ownership
97+
/// kinds . This means that it could take on /any/ ownership semantics. This
98+
/// is meant only to model SILUndef and to express certain situations where we
99+
/// use unqualified ownership. Expected to tighten over time.
100+
Any,
99101
};
100102

101103
Optional<ValueOwnershipKind>
@@ -261,7 +263,7 @@ class SILValue {
261263
///
262264
/// An example of a SILValue without ownership semantics is a
263265
/// struct_element_addr.
264-
Optional<ValueOwnershipKind> getOwnershipKind() const;
266+
ValueOwnershipKind getOwnershipKind() const;
265267
};
266268

267269
/// A formal SIL reference to a value, suitable for use as a stored

lib/SIL/SILPrinter.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,8 +2088,13 @@ void SILModule::print(SILPrintContext &PrintCtx, Module *M,
20882088
break;
20892089
}
20902090

2091-
OS << "\n\nimport Builtin\nimport " << STDLIB_NAME
2092-
<< "\nimport SwiftShims" << "\n\n";
2091+
OS << "\n\nimport Builtin\n";
2092+
2093+
// If we are compiling stdlib, do not try to import ourselves
2094+
if (!M->isStdlibModule())
2095+
OS << "import " << STDLIB_NAME << "\n";
2096+
2097+
OS << "import SwiftShims" << "\n\n";
20932098

20942099
// Print the declarations and types from the origin module, unless we're not
20952100
// in whole-module mode.

lib/SIL/SILValue.cpp

Lines changed: 130 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/SIL/SILArgument.h"
1515
#include "swift/SIL/SILBuiltinVisitor.h"
1616
#include "swift/SIL/SILInstruction.h"
17+
#include "swift/SIL/SILModule.h"
1718
#include "swift/SIL/SILVisitor.h"
1819

1920
using namespace swift;
@@ -84,8 +85,8 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
8485
return os << "Owned";
8586
case ValueOwnershipKind::Guaranteed:
8687
return os << "Guaranteed";
87-
case ValueOwnershipKind::Undef:
88-
return os << "Undef";
88+
case ValueOwnershipKind::Any:
89+
return os << "Any";
8990
}
9091
}
9192

@@ -97,12 +98,12 @@ swift::ValueOwnershipKindMerge(Optional<ValueOwnershipKind> LHS,
9798
auto LHSVal = LHS.getValue();
9899
auto RHSVal = RHS.getValue();
99100

100-
// Undef merges with anything.
101-
if (LHSVal == ValueOwnershipKind::Undef) {
101+
// Any merges with anything.
102+
if (LHSVal == ValueOwnershipKind::Any) {
102103
return RHSVal;
103104
}
104-
// Undef merges with anything.
105-
if (RHSVal == ValueOwnershipKind::Undef) {
105+
// Any merges with anything.
106+
if (RHSVal == ValueOwnershipKind::Any) {
106107
return LHSVal;
107108
}
108109

@@ -117,29 +118,28 @@ namespace {
117118

118119
class ValueOwnershipKindVisitor
119120
: public SILVisitor<ValueOwnershipKindVisitor,
120-
Optional<ValueOwnershipKind>> {
121+
ValueOwnershipKind> {
121122

122123
public:
123124
ValueOwnershipKindVisitor() = default;
124125
~ValueOwnershipKindVisitor() = default;
125126
ValueOwnershipKindVisitor(const ValueOwnershipKindVisitor &) = delete;
126127
ValueOwnershipKindVisitor(ValueOwnershipKindVisitor &&) = delete;
127128

128-
Optional<ValueOwnershipKind> visitForwardingInst(SILInstruction *I);
129-
Optional<ValueOwnershipKind> visitPHISILArgument(SILArgument *Arg);
129+
ValueOwnershipKind visitForwardingInst(SILInstruction *I);
130+
ValueOwnershipKind visitPHISILArgument(SILArgument *Arg);
130131

131-
Optional<ValueOwnershipKind> visitValueBase(ValueBase *V) {
132+
ValueOwnershipKind visitValueBase(ValueBase *V) {
132133
llvm_unreachable("unimplemented method on ValueBaseOwnershipVisitor");
133134
}
134-
#define VALUE(Id, Parent) \
135-
Optional<ValueOwnershipKind> visit##Id(Id *ID);
135+
#define VALUE(Id, Parent) ValueOwnershipKind visit##Id(Id *ID);
136136
#include "swift/SIL/SILNodes.def"
137137
};
138138

139139
} // end anonymous namespace
140140

141141
#define CONSTANT_OWNERSHIP_INST(OWNERSHIP, INST) \
142-
Optional<ValueOwnershipKind> ValueOwnershipKindVisitor::visit##INST##Inst( \
142+
ValueOwnershipKind ValueOwnershipKindVisitor::visit##INST##Inst( \
143143
INST##Inst *Arg) { \
144144
assert(Arg->hasValue() && "Expected to have a result"); \
145145
if (ValueOwnershipKind::OWNERSHIP == ValueOwnershipKind::Trivial) { \
@@ -151,9 +151,6 @@ class ValueOwnershipKindVisitor
151151
}
152152
CONSTANT_OWNERSHIP_INST(Guaranteed, BeginBorrow)
153153
CONSTANT_OWNERSHIP_INST(Guaranteed, LoadBorrow)
154-
CONSTANT_OWNERSHIP_INST(Guaranteed, StructExtract)
155-
CONSTANT_OWNERSHIP_INST(Guaranteed, TupleExtract)
156-
CONSTANT_OWNERSHIP_INST(Guaranteed, UncheckedEnumData)
157154
CONSTANT_OWNERSHIP_INST(Owned, AllocBox)
158155
CONSTANT_OWNERSHIP_INST(Owned, AllocExistentialBox)
159156
CONSTANT_OWNERSHIP_INST(Owned, AllocRef)
@@ -192,9 +189,10 @@ CONSTANT_OWNERSHIP_INST(Trivial, MarkFunctionEscape)
192189
CONSTANT_OWNERSHIP_INST(Trivial, MarkUninitialized)
193190
CONSTANT_OWNERSHIP_INST(Trivial, MarkUninitializedBehavior)
194191
CONSTANT_OWNERSHIP_INST(Trivial, Metatype)
195-
CONSTANT_OWNERSHIP_INST(Trivial, ObjCExistentialMetatypeToObject) // Is this right?
196-
CONSTANT_OWNERSHIP_INST(Trivial, ObjCMetatypeToObject) // Is this right?
197-
CONSTANT_OWNERSHIP_INST(Trivial, ObjCProtocol) // Is this right?
192+
CONSTANT_OWNERSHIP_INST(Trivial,
193+
ObjCExistentialMetatypeToObject) // Is this right?
194+
CONSTANT_OWNERSHIP_INST(Trivial, ObjCMetatypeToObject) // Is this right?
195+
CONSTANT_OWNERSHIP_INST(Trivial, ObjCProtocol) // Is this right?
198196
CONSTANT_OWNERSHIP_INST(Trivial, ObjCToThickMetatype)
199197
CONSTANT_OWNERSHIP_INST(Trivial, OpenExistentialAddr)
200198
CONSTANT_OWNERSHIP_INST(Trivial, OpenExistentialBox)
@@ -233,13 +231,25 @@ CONSTANT_OWNERSHIP_INST(Unowned, UnmanagedToRef)
233231
CONSTANT_OWNERSHIP_INST(Unowned, UnownedToRef)
234232
#undef CONSTANT_OWNERSHIP_INST
235233

234+
#define CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(OWNERSHIP, INST) \
235+
ValueOwnershipKind ValueOwnershipKindVisitor::visit##INST##Inst(INST##Inst *I) { \
236+
if (I->getType().isTrivial(I->getModule())) { \
237+
return ValueOwnershipKind::Trivial; \
238+
} \
239+
return ValueOwnershipKind::OWNERSHIP; \
240+
}
241+
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, StructExtract)
242+
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, TupleExtract)
243+
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, UncheckedEnumData)
244+
#undef CONSTANT_OR_TRIVIAL_OWNERSHIP_INST
245+
236246
// These are instructions that do not have any result, so we should never reach
237247
// this point in the code since we need a SILValue to compute
238248
// ValueOwnershipKind. We define methods so that all instructions have a method
239249
// on the visitor (causing the compiler to warn if a new instruction is added
240250
// within a method being added).
241251
#define NO_RESULT_OWNERSHIP_INST(INST) \
242-
Optional<ValueOwnershipKind> ValueOwnershipKindVisitor::visit##INST##Inst( \
252+
ValueOwnershipKind ValueOwnershipKindVisitor::visit##INST##Inst( \
243253
INST##Inst *I) { \
244254
assert(!I->hasValue() && "Expected an instruction without a result"); \
245255
llvm_unreachable("Instruction without a result can not have ownership"); \
@@ -294,34 +304,58 @@ NO_RESULT_OWNERSHIP_INST(CheckedCastBranch)
294304
NO_RESULT_OWNERSHIP_INST(CheckedCastAddrBranch)
295305
#undef NO_RESULT_OWNERSHIP_INST
296306

297-
// For a forwarding instruction, we loop over all operands and make sure they
298-
// are all the same.
299-
Optional<ValueOwnershipKind>
307+
// For a forwarding instruction, we loop over all operands and make sure that
308+
// all non-trivial values have the same ownership.
309+
ValueOwnershipKind
300310
ValueOwnershipKindVisitor::visitForwardingInst(SILInstruction *I) {
301311
ArrayRef<Operand> Ops = I->getAllOperands();
312+
// A forwarding inst without operands must be trivial.
302313
if (Ops.empty())
303-
llvm_unreachable("All forwarding insts should have operands");
304-
Optional<ValueOwnershipKind> Base = Ops[0].get().getOwnershipKind();
305-
if (!Base)
306-
return None;
307-
308-
for (const Operand &Op : Ops.slice(1)) {
309-
if (!(Base = ValueOwnershipKindMerge(Base, Op.get().getOwnershipKind()))) {
310-
return None;
314+
return ValueOwnershipKind::Trivial;
315+
316+
// Find the first index where we have a trivial value.
317+
auto Iter =
318+
find_if(Ops,
319+
[](const Operand &Op) -> bool {
320+
return Op.get().getOwnershipKind() != ValueOwnershipKind::Trivial;
321+
});
322+
// All trivial.
323+
if (Iter == Ops.end()) {
324+
return ValueOwnershipKind::Trivial;
325+
}
326+
327+
// See if we have any Any. If we do, just return that for now.
328+
if (any_of(Ops,
329+
[](const Operand &Op) -> bool {
330+
return Op.get().getOwnershipKind() == ValueOwnershipKind::Any;
331+
}))
332+
return ValueOwnershipKind::Any;
333+
unsigned Index = std::distance(Ops.begin(), Iter);
334+
335+
ValueOwnershipKind Base = Ops[Index].get().getOwnershipKind();
336+
337+
for (const Operand &Op : Ops.slice(Index+1)) {
338+
auto OpKind = Op.get().getOwnershipKind();
339+
if (ValueOwnershipKindMerge(OpKind, ValueOwnershipKind::Trivial))
340+
continue;
341+
342+
auto MergedValue = ValueOwnershipKindMerge(Base, OpKind);
343+
if (!MergedValue.hasValue()) {
344+
llvm_unreachable("Forwarding inst with mismatching ownership kinds?!");
311345
}
312346
}
347+
313348
return Base;
314349
}
315350

316351
#define FORWARDING_OWNERSHIP_INST(INST) \
317-
Optional<ValueOwnershipKind> ValueOwnershipKindVisitor::visit##INST##Inst( \
352+
ValueOwnershipKind ValueOwnershipKindVisitor::visit##INST##Inst( \
318353
INST##Inst *I) { \
319354
assert(I->hasValue() && "Expected to have a value"); \
320355
return visitForwardingInst(I); \
321356
}
322357
FORWARDING_OWNERSHIP_INST(BridgeObjectToRef)
323358
FORWARDING_OWNERSHIP_INST(ConvertFunction)
324-
FORWARDING_OWNERSHIP_INST(Enum)
325359
FORWARDING_OWNERSHIP_INST(InitExistentialRef)
326360
FORWARDING_OWNERSHIP_INST(OpenExistentialRef)
327361
FORWARDING_OWNERSHIP_INST(RefToBridgeObject)
@@ -334,18 +368,27 @@ FORWARDING_OWNERSHIP_INST(UnconditionalCheckedCast)
334368
FORWARDING_OWNERSHIP_INST(Upcast)
335369
#undef FORWARDING_OWNERSHIP_INST
336370

337-
Optional<ValueOwnershipKind>
371+
// An enum without payload is trivial. One with non-trivial payload is
372+
// forwarding.
373+
ValueOwnershipKind
374+
ValueOwnershipKindVisitor::visitEnumInst(EnumInst *EI) {
375+
if (!EI->hasOperand())
376+
return ValueOwnershipKind::Trivial;
377+
return visitForwardingInst(EI);
378+
}
379+
380+
ValueOwnershipKind
338381
ValueOwnershipKindVisitor::visitSILUndef(SILUndef *Arg) {
339-
return ValueOwnershipKind::Undef;
382+
return ValueOwnershipKind::Any;
340383
}
341384

342-
Optional<ValueOwnershipKind>
385+
ValueOwnershipKind
343386
ValueOwnershipKindVisitor::visitPHISILArgument(SILArgument *Arg) {
344387
// For now just return undef.
345-
return ValueOwnershipKind::Undef;
388+
return ValueOwnershipKind::Any;
346389
}
347390

348-
Optional<ValueOwnershipKind>
391+
ValueOwnershipKind
349392
ValueOwnershipKindVisitor::visitSILArgument(SILArgument *Arg) {
350393
// If we have a PHI node, we need to look at our predecessors.
351394
if (!Arg->isFunctionArg()) {
@@ -378,41 +421,79 @@ ValueOwnershipKindVisitor::visitSILArgument(SILArgument *Arg) {
378421
}
379422

380423
// This is a forwarding instruction through only one of its arguments.
381-
Optional<ValueOwnershipKind>
424+
ValueOwnershipKind
382425
ValueOwnershipKindVisitor::visitMarkDependenceInst(MarkDependenceInst *MDI) {
383426
return MDI->getValue().getOwnershipKind();
384427
}
385428

386-
Optional<ValueOwnershipKind>
387-
ValueOwnershipKindVisitor::visitApplyInst(ApplyInst *AI) {
388-
auto Result = AI->getSingleResult();
389-
assert(Result && "SIL for now only has single results");
390-
switch (Result->getConvention()) {
429+
static ValueOwnershipKind getResultOwnershipKind(const SILResultInfo &Info,
430+
SILModule &M) {
431+
SILType Ty = M.Types.getLoweredType(Info.getType());
432+
bool IsTrivial = Ty.isTrivial(M);
433+
switch (Info.getConvention()) {
391434
case ResultConvention::Indirect:
392-
return None;
435+
return ValueOwnershipKind::Trivial; // Should this be an Any?
393436
case ResultConvention::Autoreleased:
394437
case ResultConvention::Owned:
395438
return ValueOwnershipKind::Owned;
396439
case ResultConvention::Unowned:
397440
case ResultConvention::UnownedInnerPointer:
441+
if (IsTrivial)
442+
return ValueOwnershipKind::Trivial;
398443
return ValueOwnershipKind::Unowned;
399444
}
400445
}
401446

402-
Optional<ValueOwnershipKind>
447+
ValueOwnershipKind
448+
ValueOwnershipKindVisitor::visitApplyInst(ApplyInst *AI) {
449+
SILModule &M = AI->getModule();
450+
bool IsTrivial = AI->getType().isTrivial(M);
451+
auto Results = AI->getSubstCalleeType()->getDirectResults();
452+
// No results => empty tuple result => Trivial.
453+
if (Results.empty() || IsTrivial)
454+
return ValueOwnershipKind::Trivial;
455+
456+
// Find the first index where we have a trivial value.
457+
auto Iter =
458+
find_if(Results,
459+
[&M](const SILResultInfo &Info) -> bool {
460+
return getResultOwnershipKind(Info, M) != ValueOwnershipKind::Trivial;
461+
});
462+
// If we have all trivial, then we must be trivial.
463+
if (Iter == Results.end())
464+
return ValueOwnershipKind::Trivial;
465+
466+
unsigned Index = std::distance(Results.begin(), Iter);
467+
ValueOwnershipKind Base = getResultOwnershipKind(Results[Index], M);
468+
469+
for (const SILResultInfo &ResultInfo : Results.slice(Index+1)) {
470+
auto RKind = getResultOwnershipKind(ResultInfo, M);
471+
if (ValueOwnershipKindMerge(RKind, ValueOwnershipKind::Trivial))
472+
continue;
473+
474+
auto MergedValue = ValueOwnershipKindMerge(Base, RKind);
475+
if (!MergedValue.hasValue()) {
476+
llvm_unreachable("Forwarding inst with mismatching ownership kinds?!");
477+
}
478+
}
479+
480+
return Base;
481+
}
482+
483+
ValueOwnershipKind
403484
ValueOwnershipKindVisitor::visitLoadInst(LoadInst *LI) {
404485
switch (LI->getOwnershipQualifier()) {
405486
case LoadOwnershipQualifier::Take:
406487
case LoadOwnershipQualifier::Copy:
407488
return ValueOwnershipKind::Owned;
408489
case LoadOwnershipQualifier::Unqualified:
409-
return None;
490+
return ValueOwnershipKind::Any;
410491
case LoadOwnershipQualifier::Trivial:
411492
return ValueOwnershipKind::Trivial;
412493
}
413494
}
414495

415-
Optional<ValueOwnershipKind> SILValue::getOwnershipKind() const {
496+
ValueOwnershipKind SILValue::getOwnershipKind() const {
416497
// Once we have multiple return values, this must be changed.
417498
return ValueOwnershipKindVisitor().visit(const_cast<ValueBase *>(Value));
418499
}
@@ -623,7 +704,7 @@ UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(InsertElement)
623704
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(ZeroInitializer)
624705
#undef UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT
625706

626-
Optional<ValueOwnershipKind>
707+
ValueOwnershipKind
627708
ValueOwnershipKindVisitor::visitBuiltinInst(BuiltinInst *BI) {
628709
// For now, just conservatively say builtins are None. We need to use a
629710
// builtin in here to guarantee correctness.

0 commit comments

Comments
 (0)