Skip to content

Commit ab3f77b

Browse files
committed
Make SILInstruction no longer a subclass of ValueBase and
introduce a common superclass, SILNode. This is in preparation for allowing instructions to have multiple results. It is also a somewhat more elegant representation for instructions that have zero results. Instructions that are known to have exactly one result inherit from a class, SingleValueInstruction, that subclasses both ValueBase and SILInstruction. Some care must be taken when working with SILNode pointers and testing for equality; please see the comment on SILNode for more information. A number of SIL passes needed to be updated in order to handle this new distinction between SIL values and SIL instructions. Note that the SIL parser is now stricter about not trying to assign a result value from an instruction (like 'return' or 'strong_retain') that does not produce any.
1 parent 6d9294f commit ab3f77b

File tree

195 files changed

+6098
-4969
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+6098
-4969
lines changed

docs/SIL.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ Here is an example of a ``.sil`` file::
167167
%2 = struct_extract %0 : $Point, #Point.x
168168
%3 = struct_extract %0 : $Point, #Point.y
169169
%4 = apply %1(%2, %3) : $(Double, Double) -> Double
170-
%5 = return %4 : Double
170+
return %4 : Double
171171
}
172172

173173
// Define a SIL vtable. This matches dynamically-dispatched method
@@ -4625,7 +4625,7 @@ unconditional_checked_cast_addr
46254625
sil-type 'in' sil-operand 'to'
46264626
sil-type 'in' sil-operand
46274627

4628-
%1 = unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in $*@thick B
4628+
unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in $*@thick B
46294629
// $A and $B must be both addresses
46304630
// %1 will be of type $*B
46314631
// $A is destroyed during the conversion. There is no implicit copy.

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ ERROR(expected_sil_instr_start_of_line,none,
511511
"SIL instructions must be at the start of a line", ())
512512
ERROR(expected_equal_in_sil_instr,none,
513513
"expected '=' in SIL instruction", ())
514+
ERROR(wrong_result_count_in_sil_instr,none,
515+
"wrong number of results for SIL instruction, expected %0", (unsigned))
514516
ERROR(expected_sil_instr_opcode,none,
515517
"expected SIL instruction opcode", ())
516518
ERROR(expected_tok_in_sil_instr,none,

include/swift/SIL/DebugUtils.h

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,16 @@ inline bool onlyHaveDebugUses(SILValue V) {
143143
return NonDebugUses.begin() == NonDebugUses.end();
144144
}
145145

146+
/// Return true if all of the results of the given instruction have no uses
147+
/// except debug instructions.
148+
inline bool onlyHaveDebugUsesOfAllResults(SILInstruction *I) {
149+
for (auto result : I->getResults()) {
150+
if (!onlyHaveDebugUses(result))
151+
return false;
152+
}
153+
return true;
154+
}
155+
146156
/// Returns true if a value (e.g. SILInstruction) has exactly one use which is
147157
/// not a debug instruction.
148158
inline bool hasOneNonDebugUse(SILValue V) {
@@ -169,16 +179,26 @@ inline SILInstruction *getSingleNonDebugUser(SILValue V) {
169179
/// incremented.
170180
inline void eraseFromParentWithDebugInsts(SILInstruction *I,
171181
SILBasicBlock::iterator &InstIter) {
172-
while (!I->use_empty()) {
173-
auto *User = I->use_begin()->getUser();
174-
assert(isDebugInst(User));
175-
if (InstIter != SILBasicBlock::iterator() &&
176-
InstIter != I->getParent()->end() &&
177-
&*InstIter == User) {
178-
InstIter++;
182+
auto results = I->getResults();
183+
184+
bool foundAny;
185+
do {
186+
foundAny = false;
187+
for (auto result : results) {
188+
while (!result->use_empty()) {
189+
foundAny = true;
190+
auto *User = result->use_begin()->getUser();
191+
assert(isDebugInst(User));
192+
if (InstIter != SILBasicBlock::iterator() &&
193+
InstIter != I->getParent()->end() &&
194+
&*InstIter == User) {
195+
InstIter++;
196+
}
197+
User->eraseFromParent();
198+
}
179199
}
180-
User->eraseFromParent();
181-
}
200+
} while (foundAny);
201+
182202
I->eraseFromParent();
183203
}
184204

include/swift/SIL/Notifications.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
namespace swift {
1717

18-
class ValueBase;
18+
class SILNode;
1919

2020
/// A protocol (or interface) for handling value deletion notifications.
2121
///
@@ -29,7 +29,7 @@ struct DeleteNotificationHandler {
2929
virtual ~DeleteNotificationHandler() {}
3030

3131
/// Handle the invalidation message for the value \p Value.
32-
virtual void handleDeleteNotification(swift::ValueBase *Value) { }
32+
virtual void handleDeleteNotification(SILNode *value) { }
3333

3434
/// Returns True if the pass, analysis or other entity wants to receive
3535
/// notifications. This callback is called once when the class is being

include/swift/SIL/PatternMatch.h

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -296,19 +296,24 @@ using m_One = match_integer<1>;
296296
// Unary Instructions
297297
//===----------------------------------------------------------------------===//
298298

299-
template<typename OpMatchTy, ValueKind Kind>
299+
template<typename OpMatchTy, SILInstructionKind Kind>
300300
struct UnaryOp_match {
301301
OpMatchTy OpMatch;
302302

303303
UnaryOp_match(const OpMatchTy &Op) : OpMatch(Op) { }
304304

305-
template<typename OpTy>
306-
bool match(OpTy *V) {
307-
if (V->getKind() != Kind)
305+
bool match(SILNode *node) {
306+
if (node->getKind() != SILNodeKind(Kind))
307+
return false;
308+
309+
return match(cast<SILInstruction>(node));
310+
}
311+
312+
bool match(SILInstruction *I) {
313+
if (I->getKind() != Kind)
308314
return false;
309315

310-
auto *I = dyn_cast<SILInstruction>(V);
311-
if (!I || I->getNumOperands() != 1)
316+
if (I->getNumOperands() != 1)
312317
return false;
313318

314319
return OpMatch.match(I->getOperand(0));
@@ -319,7 +324,7 @@ struct UnaryOp_match {
319324
// further matchers to the operands of the unary operation.
320325
#define UNARY_OP_MATCH_WITH_ARG_MATCHER(Class) \
321326
template <typename Ty> \
322-
UnaryOp_match<Ty, ValueKind::Class> \
327+
UnaryOp_match<Ty, SILInstructionKind::Class> \
323328
m_##Class(const Ty &T) { \
324329
return T; \
325330
}
@@ -393,20 +398,25 @@ UNARY_OP_MATCH_WITH_ARG_MATCHER(ReturnInst)
393398
// Binary Instructions
394399
//===----------------------------------------------------------------------===//
395400

396-
template<typename LHSTy, typename RHSTy, ValueKind Kind>
401+
template<typename LHSTy, typename RHSTy, SILInstructionKind Kind>
397402
struct BinaryOp_match {
398403
LHSTy L;
399404
RHSTy R;
400405

401406
BinaryOp_match(const LHSTy &LHS, const RHSTy &RHS) : L(LHS), R(RHS) {}
402407

403-
template<typename OpTy>
404-
bool match(OpTy *V) {
405-
if (V->getKind() != Kind)
408+
bool match(SILNode *node) {
409+
if (node->getKind() != SILNodeKind(Kind))
410+
return false;
411+
412+
return match(cast<SILInstruction>(node));
413+
}
414+
415+
bool match(SILInstruction *I) {
416+
if (I->getKind() != Kind)
406417
return false;
407418

408-
auto *I = dyn_cast<SILInstruction>(V);
409-
if (!I || I->getNumOperands() != 2)
419+
if (I->getNumOperands() != 2)
410420
return false;
411421

412422
return L.match((ValueBase *)I->getOperand(0)) &&
@@ -415,7 +425,7 @@ struct BinaryOp_match {
415425
};
416426

417427
template <typename LTy, typename RTy>
418-
BinaryOp_match<LTy, RTy, ValueKind::IndexRawPointerInst>
428+
BinaryOp_match<LTy, RTy, SILInstructionKind::IndexRawPointerInst>
419429
m_IndexRawPointerInst(const LTy &Left, const RTy &Right) {
420430
return {Left, Right};
421431
}

include/swift/SIL/Projection.h

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,10 @@ class Projection {
228228
Projection() = delete;
229229

230230
explicit Projection(SILValue V)
231-
: Projection(dyn_cast<SILInstruction>(V)) {}
232-
explicit Projection(SILInstruction *I);
231+
: Projection(dyn_cast<SingleValueInstruction>(V)) {}
232+
explicit Projection(SILInstruction *I)
233+
: Projection(dyn_cast<SingleValueInstruction>(I)) {}
234+
explicit Projection(SingleValueInstruction *I);
233235

234236
Projection(ProjectionKind Kind, unsigned NewIndex)
235237
: Value(Kind, NewIndex) {}
@@ -255,7 +257,7 @@ class Projection {
255257

256258
/// Determine if I is a value projection instruction whose corresponding
257259
/// projection equals this projection.
258-
bool matchesObjectProjection(SILInstruction *I) const {
260+
bool matchesObjectProjection(SingleValueInstruction *I) const {
259261
Projection P(I);
260262
return P.isValid() && P == *this;
261263
}
@@ -264,17 +266,17 @@ class Projection {
264266
/// type differences and this Projection is representable as a value
265267
/// projection, create the relevant value projection and return it. Otherwise,
266268
/// return nullptr.
267-
NullablePtr<SILInstruction>
269+
NullablePtr<SingleValueInstruction>
268270
createObjectProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const;
269271

270272
/// If Base's type matches this Projections type ignoring Address vs Object
271273
/// type differences and this projection is representable as an address
272274
/// projection, create the relevant address projection and return
273275
/// it. Otherwise, return nullptr.
274-
NullablePtr<SILInstruction>
276+
NullablePtr<SingleValueInstruction>
275277
createAddressProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const;
276278

277-
NullablePtr<SILInstruction>
279+
NullablePtr<SingleValueInstruction>
278280
createProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const {
279281
if (Base->getType().isAddress()) {
280282
return createAddressProjection(B, Loc, Base);
@@ -370,34 +372,37 @@ class Projection {
370372

371373
/// Returns true if this instruction projects from an address type to an
372374
/// address subtype.
373-
static bool isAddressProjection(SILValue V) {
375+
static SingleValueInstruction *isAddressProjection(SILValue V) {
374376
switch (V->getKind()) {
375377
default:
376-
return false;
378+
return nullptr;
377379
case ValueKind::IndexAddrInst: {
380+
auto I = cast<IndexAddrInst>(V);
378381
unsigned Scalar;
379-
return getIntegerIndex(cast<IndexAddrInst>(V)->getIndex(), Scalar);
382+
if (getIntegerIndex(I->getIndex(), Scalar))
383+
return I;
384+
return nullptr;
380385
}
381386
case ValueKind::StructElementAddrInst:
382387
case ValueKind::RefElementAddrInst:
383388
case ValueKind::RefTailAddrInst:
384389
case ValueKind::ProjectBoxInst:
385390
case ValueKind::TupleElementAddrInst:
386391
case ValueKind::UncheckedTakeEnumDataAddrInst:
387-
return true;
392+
return cast<SingleValueInstruction>(V);
388393
}
389394
}
390395

391396
/// Returns true if this instruction projects from an object type to an object
392397
/// subtype.
393-
static bool isObjectProjection(SILValue V) {
398+
static SingleValueInstruction *isObjectProjection(SILValue V) {
394399
switch (V->getKind()) {
395400
default:
396-
return false;
401+
return nullptr;
397402
case ValueKind::StructExtractInst:
398403
case ValueKind::TupleExtractInst:
399404
case ValueKind::UncheckedEnumDataInst:
400-
return true;
405+
return cast<SingleValueInstruction>(V);
401406
}
402407
}
403408

@@ -465,7 +470,7 @@ class Projection {
465470
/// This can be used with getFirstLevelProjections to project out/reform
466471
/// values. We do not need to use the original projections here since to build
467472
/// aggregate instructions the order is the only important thing.
468-
static NullablePtr<SILInstruction>
473+
static NullablePtr<SingleValueInstruction>
469474
createAggFromFirstLevelProjections(SILBuilder &B, SILLocation Loc,
470475
SILType BaseType,
471476
llvm::SmallVectorImpl<SILValue> &Values);
@@ -788,10 +793,10 @@ class ProjectionTreeNode {
788793
ProjectionTreeNode *getChildForProjection(ProjectionTree &Tree,
789794
const Projection &P);
790795

791-
NullablePtr<SILInstruction> createProjection(SILBuilder &B, SILLocation Loc,
792-
SILValue Arg) const;
796+
NullablePtr<SingleValueInstruction>
797+
createProjection(SILBuilder &B, SILLocation Loc, SILValue Arg) const;
793798

794-
SILInstruction *
799+
SingleValueInstruction *
795800
createAggregate(SILBuilder &B, SILLocation Loc,
796801
ArrayRef<SILValue> Args) const;
797802

include/swift/SIL/SILArgument.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace swift {
2222

2323
class SILBasicBlock;
2424
class SILModule;
25+
class SILUndef;
2526

2627
// Map an argument index onto a SILArgumentConvention.
2728
inline SILArgumentConvention
@@ -58,9 +59,11 @@ class SILArgument : public ValueBase {
5859

5960
const ValueDecl *getDecl() const { return Decl; }
6061

61-
static bool classof(const ValueBase *V) {
62-
return V->getKind() >= ValueKind::First_SILArgument &&
63-
V->getKind() <= ValueKind::Last_SILArgument;
62+
static bool classof(const SILInstruction *) = delete;
63+
static bool classof(const SILUndef *) = delete;
64+
static bool classof(const SILNode *node) {
65+
return node->getKind() >= SILNodeKind::First_SILArgument &&
66+
node->getKind() <= SILNodeKind::Last_SILArgument;
6467
}
6568

6669
unsigned getIndex() const {
@@ -165,8 +168,10 @@ class SILPHIArgument : public SILArgument {
165168
/// payload argument is the enum itself (the operand of the switch_enum).
166169
SILValue getSingleIncomingValue() const;
167170

168-
static bool classof(const ValueBase *V) {
169-
return V->getKind() == ValueKind::SILPHIArgument;
171+
static bool classof(const SILInstruction *) = delete;
172+
static bool classof(const SILUndef *) = delete;
173+
static bool classof(const SILNode *node) {
174+
return node->getKind() == SILNodeKind::SILPHIArgument;
170175
}
171176

172177
private:
@@ -216,8 +221,10 @@ class SILFunctionArgument : public SILArgument {
216221
return getArgumentConvention() == P;
217222
}
218223

219-
static bool classof(const ValueBase *V) {
220-
return V->getKind() == ValueKind::SILFunctionArgument;
224+
static bool classof(const SILInstruction *) = delete;
225+
static bool classof(const SILUndef *) = delete;
226+
static bool classof(const SILNode *node) {
227+
return node->getKind() == SILNodeKind::SILFunctionArgument;
221228
}
222229

223230
private:

include/swift/SIL/SILBasicBlock.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,7 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
389389
I.dropAllReferences();
390390
}
391391

392-
void eraseInstructions() {
393-
for (auto It = begin(); It != end();) {
394-
auto *Inst = &*It++;
395-
Inst->replaceAllUsesWithUndef();
396-
Inst->eraseFromParent();
397-
}
398-
}
392+
void eraseInstructions();
399393

400394
private:
401395
friend class SILArgument;

include/swift/SIL/SILBuilder.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,12 +1525,12 @@ class SILBuilder {
15251525
// Create an UncheckedRefCast if the source and dest types are legal,
15261526
// otherwise return null.
15271527
// Unwrap or wrap optional types as needed.
1528-
SILInstruction *tryCreateUncheckedRefCast(SILLocation Loc, SILValue Op,
1529-
SILType ResultTy);
1528+
SingleValueInstruction *tryCreateUncheckedRefCast(SILLocation Loc, SILValue Op,
1529+
SILType ResultTy);
15301530

15311531
// Create the appropriate cast instruction based on result type.
1532-
SILInstruction *createUncheckedBitCast(SILLocation Loc, SILValue Op,
1533-
SILType Ty);
1532+
SingleValueInstruction *createUncheckedBitCast(SILLocation Loc, SILValue Op,
1533+
SILType Ty);
15341534

15351535
//===--------------------------------------------------------------------===//
15361536
// Runtime failure

0 commit comments

Comments
 (0)