Skip to content

Divide the SIL concepts of values and instructions #12057

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ Here is an example of a ``.sil`` file::
%2 = struct_extract %0 : $Point, #Point.x
%3 = struct_extract %0 : $Point, #Point.y
%4 = apply %1(%2, %3) : $(Double, Double) -> Double
%5 = return %4 : Double
return %4 : Double
}

// Define a SIL vtable. This matches dynamically-dispatched method
Expand Down Expand Up @@ -4625,7 +4625,7 @@ unconditional_checked_cast_addr
sil-type 'in' sil-operand 'to'
sil-type 'in' sil-operand

%1 = unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in $*@thick B
unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in $*@thick B
// $A and $B must be both addresses
// %1 will be of type $*B
// $A is destroyed during the conversion. There is no implicit copy.
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@ ERROR(expected_sil_instr_start_of_line,none,
"SIL instructions must be at the start of a line", ())
ERROR(expected_equal_in_sil_instr,none,
"expected '=' in SIL instruction", ())
ERROR(wrong_result_count_in_sil_instr,none,
"wrong number of results for SIL instruction, expected %0", (unsigned))
ERROR(expected_sil_instr_opcode,none,
"expected SIL instruction opcode", ())
ERROR(expected_tok_in_sil_instr,none,
Expand Down
36 changes: 36 additions & 0 deletions include/swift/Basic/ArrayRefView.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ template <class Orig, class Projected, Projected (&Project)(const Orig &),
class ArrayRefView {
llvm::ArrayRef<Orig> Array;
public:
ArrayRefView() {}
ArrayRefView(llvm::ArrayRef<Orig> array) : Array(array) {}

class iterator {
Expand Down Expand Up @@ -111,6 +112,41 @@ class ArrayRefView {
"original array access not enabled for this view");
return Array;
}

friend bool operator==(ArrayRefView lhs, ArrayRefView rhs) {
if (lhs.size() != rhs.size())
return false;
for (auto i : indices(lhs))
if (lhs[i] != rhs[i])
return false;
return true;
}
friend bool operator==(llvm::ArrayRef<Projected> lhs, ArrayRefView rhs) {
if (lhs.size() != rhs.size())
return false;
for (auto i : indices(lhs))
if (lhs[i] != rhs[i])
return false;
return true;
}
friend bool operator==(ArrayRefView lhs, llvm::ArrayRef<Projected> rhs) {
if (lhs.size() != rhs.size())
return false;
for (auto i : indices(lhs))
if (lhs[i] != rhs[i])
return false;
return true;
}

friend bool operator!=(ArrayRefView lhs, ArrayRefView rhs) {
return !(lhs == rhs);
}
friend bool operator!=(llvm::ArrayRef<Projected> lhs, ArrayRefView rhs) {
return !(lhs == rhs);
}
friend bool operator!=(ArrayRefView lhs, llvm::ArrayRef<Projected> rhs) {
return !(lhs == rhs);
}
};

} // end namespace swift
Expand Down
92 changes: 70 additions & 22 deletions include/swift/Basic/Range.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,47 @@ namespace swift {
return result;
}

/// A range of integers. This type behaves roughly like an ArrayRef.
template <class T=unsigned> class IntRange {
static_assert(std::is_integral<T>::value, "T must be an integer type");
template <class T, bool IsEnum = std::is_enum<T>::value>
struct IntRangeTraits;

template <class T>
struct IntRangeTraits<T, /*is enum*/ false> {
static_assert(std::is_integral<T>::value,
"argument type of IntRange is either an integer nor an enum");
using int_type = T;
using difference_type = typename std::make_signed<int_type>::type;

static T addOffset(T value, difference_type quantity) {
return T(difference_type(value) + quantity);
}
static difference_type distance(T begin, T end) {
return difference_type(end) - difference_type(begin);
}
};

template <class T>
struct IntRangeTraits<T, /*is enum*/ true> {
using int_type = typename std::underlying_type<T>::type;
using difference_type = typename std::make_signed<int_type>::type;

static T addOffset(T value, difference_type quantity) {
return T(difference_type(value) + quantity);
}
static difference_type distance(T begin, T end) {
return difference_type(end) - difference_type(begin);
}
};

/// A range of integers or enum values. This type behaves roughly
/// like an ArrayRef.
template <class T = unsigned, class Traits = IntRangeTraits<T>>
class IntRange {
T Begin;
T End;

using int_type = typename Traits::int_type;
using difference_type = typename Traits::difference_type;

public:
IntRange() : Begin(0), End(0) {}
IntRange(T end) : Begin(0), End(end) {}
Expand All @@ -87,37 +123,48 @@ template <class T=unsigned> class IntRange {
typedef std::random_access_iterator_tag iterator_category;

T operator*() const { return Value; }
iterator &operator++() { Value++; return *this; }
iterator operator++(int) { return iterator(Value++); }
iterator &operator++() {
return *this += 1;
}
iterator operator++(int) {
auto copy = *this;
*this += 1;
return copy;
}
iterator &operator--() {
Value--;
return *this;
return *this -= 1;
}
iterator operator--(int) {
auto copy = *this;
*this -= 1;
return copy;
}
iterator operator--(int) { return iterator(Value--); }
bool operator==(iterator rhs) { return Value == rhs.Value; }
bool operator!=(iterator rhs) { return Value != rhs.Value; }

iterator &operator+=(difference_type i) {
Value += T(i);
Value = Traits::addOffset(Value, i);
return *this;
}
iterator operator+(difference_type i) const {
return iterator(Value + T(i));
return iterator(Traits::adddOfset(Value, i));
}
friend iterator operator+(difference_type i, iterator base) {
return iterator(base.Value + T(i));
return iterator(Traits::addOffset(base.Value, i));
}
iterator &operator-=(difference_type i) {
Value -= T(i);
Value = Traits::addOffset(Value, -i);
return *this;
}
iterator operator-(difference_type i) const {
return iterator(Value - T(i));
return iterator(Traits::addOffset(Value, -i));
}
difference_type operator-(iterator rhs) const {
return difference_type(Value - rhs.Value);
return Traits::distance(rhs.Value, Value);
}
T operator[](difference_type i) const {
return Traits::addOffset(Value, i);
}
T operator[](difference_type i) const { return Value + T(i); }
bool operator<(iterator rhs) const { return Value < rhs.Value; }
bool operator<=(iterator rhs) const { return Value <= rhs.Value; }
bool operator>(iterator rhs) const { return Value > rhs.Value; }
Expand All @@ -134,26 +181,27 @@ template <class T=unsigned> class IntRange {
}

bool empty() const { return Begin == End; }
size_t size() const { return End - Begin; }
size_t size() const { return size_t(Traits::distance(Begin, End)); }
T operator[](size_t i) const {
assert(i < size());
return Begin + i;
return Traits::addOffset(Begin, i);
}
T front() const { assert(!empty()); return Begin; }
T back() const { assert(!empty()); return End - 1; }
T back() const { assert(!empty()); return Traits::addOffset(End, -1); }
IntRange drop_back(size_t length = 1) const {
assert(length <= size());
return IntRange(Begin, End - length);
return IntRange(Begin, Traits::addOffset(End, -length));
}

IntRange slice(size_t start) const {
assert(start <= size());
return IntRange(Begin + start, End);
return IntRange(Traits::addOffset(Begin, start), End);
}
IntRange slice(size_t start, size_t length) const {
assert(start <= size());
return IntRange(Begin + start,
Begin + start + std::min(length, End - (Begin + start)));
auto newBegin = Traits::addOffset(Begin, start);
auto newSize = std::min(length, size_t(Traits::distance(newBegin, End)));
return IntRange(newBegin, Traits::addOffset(newBegin, newSize));
}

bool operator==(IntRange other) const {
Expand Down
38 changes: 29 additions & 9 deletions include/swift/SIL/DebugUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ inline bool onlyHaveDebugUses(SILValue V) {
return NonDebugUses.begin() == NonDebugUses.end();
}

/// Return true if all of the results of the given instruction have no uses
/// except debug instructions.
inline bool onlyHaveDebugUsesOfAllResults(SILInstruction *I) {
for (auto result : I->getResults()) {
if (!onlyHaveDebugUses(result))
return false;
}
return true;
}

/// Returns true if a value (e.g. SILInstruction) has exactly one use which is
/// not a debug instruction.
inline bool hasOneNonDebugUse(SILValue V) {
Expand All @@ -169,16 +179,26 @@ inline SILInstruction *getSingleNonDebugUser(SILValue V) {
/// incremented.
inline void eraseFromParentWithDebugInsts(SILInstruction *I,
SILBasicBlock::iterator &InstIter) {
while (!I->use_empty()) {
auto *User = I->use_begin()->getUser();
assert(isDebugInst(User));
if (InstIter != SILBasicBlock::iterator() &&
InstIter != I->getParent()->end() &&
&*InstIter == User) {
InstIter++;
auto results = I->getResults();

bool foundAny;
do {
foundAny = false;
for (auto result : results) {
while (!result->use_empty()) {
foundAny = true;
auto *User = result->use_begin()->getUser();
assert(isDebugInst(User));
if (InstIter != SILBasicBlock::iterator() &&
InstIter != I->getParent()->end() &&
&*InstIter == User) {
InstIter++;
}
User->eraseFromParent();
}
}
User->eraseFromParent();
}
} while (foundAny);

I->eraseFromParent();
}

Expand Down
4 changes: 2 additions & 2 deletions include/swift/SIL/Notifications.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace swift {

class ValueBase;
class SILNode;

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

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

/// Returns True if the pass, analysis or other entity wants to receive
/// notifications. This callback is called once when the class is being
Expand Down
38 changes: 24 additions & 14 deletions include/swift/SIL/PatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,19 +296,24 @@ using m_One = match_integer<1>;
// Unary Instructions
//===----------------------------------------------------------------------===//

template<typename OpMatchTy, ValueKind Kind>
template<typename OpMatchTy, SILInstructionKind Kind>
struct UnaryOp_match {
OpMatchTy OpMatch;

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

template<typename OpTy>
bool match(OpTy *V) {
if (V->getKind() != Kind)
bool match(SILNode *node) {
if (node->getKind() != SILNodeKind(Kind))
return false;

return match(cast<SILInstruction>(node));
}

bool match(SILInstruction *I) {
if (I->getKind() != Kind)
return false;

auto *I = dyn_cast<SILInstruction>(V);
if (!I || I->getNumOperands() != 1)
if (I->getNumOperands() != 1)
return false;

return OpMatch.match(I->getOperand(0));
Expand All @@ -319,7 +324,7 @@ struct UnaryOp_match {
// further matchers to the operands of the unary operation.
#define UNARY_OP_MATCH_WITH_ARG_MATCHER(Class) \
template <typename Ty> \
UnaryOp_match<Ty, ValueKind::Class> \
UnaryOp_match<Ty, SILInstructionKind::Class> \
m_##Class(const Ty &T) { \
return T; \
}
Expand Down Expand Up @@ -393,20 +398,25 @@ UNARY_OP_MATCH_WITH_ARG_MATCHER(ReturnInst)
// Binary Instructions
//===----------------------------------------------------------------------===//

template<typename LHSTy, typename RHSTy, ValueKind Kind>
template<typename LHSTy, typename RHSTy, SILInstructionKind Kind>
struct BinaryOp_match {
LHSTy L;
RHSTy R;

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

template<typename OpTy>
bool match(OpTy *V) {
if (V->getKind() != Kind)
bool match(SILNode *node) {
if (node->getKind() != SILNodeKind(Kind))
return false;

return match(cast<SILInstruction>(node));
}

bool match(SILInstruction *I) {
if (I->getKind() != Kind)
return false;

auto *I = dyn_cast<SILInstruction>(V);
if (!I || I->getNumOperands() != 2)
if (I->getNumOperands() != 2)
return false;

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

template <typename LTy, typename RTy>
BinaryOp_match<LTy, RTy, ValueKind::IndexRawPointerInst>
BinaryOp_match<LTy, RTy, SILInstructionKind::IndexRawPointerInst>
m_IndexRawPointerInst(const LTy &Left, const RTy &Right) {
return {Left, Right};
}
Expand Down
Loading