mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Instead for vardecls, we use the index of the field in the structdecl itself as a stable ordering of vardecls. I validated that the indeterminism was gone by running the failing test 1000 times in a row. Doug and I were hitting the indeterminism with well less than 100 iterations before, so I feel the number of iterations is sufficient. Swift SVN r13859
130 lines
4.1 KiB
C++
130 lines
4.1 KiB
C++
//===--- Projection.h - Defines the Projection class ------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the class Projection, a representation of type projections
|
|
// that is nominal, tuple agnostic. This is useful for working with aggregate
|
|
// type trees at a high level.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_PROJECTION_H
|
|
#define SWIFT_SIL_PROJECTION_H
|
|
|
|
#include "swift/SIL/SILValue.h"
|
|
#include "swift/SIL/SILInstruction.h"
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
|
|
namespace swift {
|
|
|
|
/// An abstract representation of a SIL Projection that allows one to refer to
|
|
/// either nominal fields or tuple indices.
|
|
class Projection {
|
|
public:
|
|
|
|
/// The nominal type of the projection if representing a var decl. This allows
|
|
/// us to distinguish in between struct_element_addr and ref_element_addr in a
|
|
/// manner independent of the two.
|
|
enum class NominalType : unsigned {
|
|
Struct,
|
|
Class,
|
|
};
|
|
|
|
private:
|
|
/// The type of this projection.
|
|
SILType Type;
|
|
|
|
/// The decl associated with this projection if the projection is representing
|
|
/// a nominal type.
|
|
llvm::PointerIntPair<VarDecl *, 1> Decl;
|
|
|
|
/// The index associated with the projection if the projection is representing
|
|
/// a tuple type.
|
|
unsigned Index;
|
|
|
|
public:
|
|
|
|
Projection(SILType T, VarDecl *D, NominalType NT,
|
|
unsigned I) : Type(T), Decl(D, unsigned(NT)), Index(-1) {}
|
|
|
|
Projection(SILType T, unsigned I) : Type(T), Decl(), Index(I) {}
|
|
|
|
explicit Projection(StructElementAddrInst *SEA)
|
|
: Type(SEA->getType()), Decl(SEA->getField(),
|
|
unsigned(NominalType::Struct)),
|
|
Index(SEA->getFieldNo()) { }
|
|
|
|
explicit Projection(TupleElementAddrInst *TEA) : Type(TEA->getType()),
|
|
Decl(nullptr),
|
|
Index(TEA->getFieldNo()) { }
|
|
explicit Projection(RefElementAddrInst *REA)
|
|
: Type(REA->getType()), Decl(REA->getField(), unsigned(NominalType::Class)),
|
|
Index(REA->getFieldNo()) { }
|
|
|
|
explicit Projection(StructExtractInst *SEI)
|
|
: Type(SEI->getType()), Decl(SEI->getField(),
|
|
unsigned(NominalType::Struct)),
|
|
Index(SEI->getFieldNo()) { }
|
|
|
|
explicit Projection(TupleExtractInst *TEI) : Type(TEI->getType()),
|
|
Decl(nullptr),
|
|
Index(TEI->getFieldNo()) { }
|
|
|
|
SILType getType() const { return Type; }
|
|
VarDecl *getDecl() const { return Decl.getPointer(); }
|
|
unsigned getIndex() const { return Index; }
|
|
NominalType getNominalType() const { return NominalType(Decl.getInt()); }
|
|
|
|
bool operator==(Projection &Other) const {
|
|
if (auto *D = getDecl())
|
|
return D == Other.getDecl();
|
|
else
|
|
return !Other.getDecl() && Index == Other.getIndex();
|
|
}
|
|
|
|
bool operator!=(Projection &Other) const {
|
|
return !(*this == Other);
|
|
}
|
|
|
|
bool operator<(Projection Other) const {
|
|
auto *D1 = getDecl();
|
|
auto *D2 = Other.getDecl();
|
|
|
|
// Decl is sorted before non-decl. If they are both the same, just compare
|
|
// the indices.
|
|
if (D1 && !D2)
|
|
return D1;
|
|
else if (!D1 && D2)
|
|
return D2;
|
|
else
|
|
return Index < Other.Index;
|
|
}
|
|
|
|
static bool isAddressProjection(SILValue V) {
|
|
switch (V->getKind()) {
|
|
case ValueKind::StructElementAddrInst:
|
|
case ValueKind::TupleElementAddrInst:
|
|
case ValueKind::RefElementAddrInst:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
|
|
bool
|
|
findAddressProjectionPathBetweenValues(SILValue V1, SILValue V2,
|
|
llvm::SmallVectorImpl<Projection> &Path);
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|