Files
swift-mirror/include/swift/SIL/Projection.h
Michael Gottesman 3ba6b7c663 [sil-combine] Make output of (extract (load)) -> (load (element_addr)) deterministic by not using pointer address as a sorting criteria for vardecls.
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
2014-02-13 04:57:54 +00:00

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