//=== unittests/CodeGen/IRMatchers.h - Match on the LLVM IR -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// This file provides a simple mechanism for performing search operations over
/// IR including metadata and types. It allows writing complex search patterns
/// using understandable syntax. For instance, the code:
///
/// \code
///       const BasicBlock *BB = ...
///       const Instruction *I = match(BB,
///           MInstruction(Instruction::Store,
///               MConstInt(4, 8),
///               MMTuple(
///                   MMTuple(
///                       MMString("omnipotent char"),
///                       MMTuple(
///                           MMString("Simple C/C++ TBAA")),
///                       MConstInt(0, 64)),
///                   MSameAs(0),
///                   MConstInt(0))));
/// \endcode
///
/// searches the basic block BB for the 'store' instruction, first argument of
/// which is 'i8 4', and the attached metadata has an item described by the
/// given tree.
//===----------------------------------------------------------------------===//

#ifndef CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H
#define CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H

#include "llvm/ADT/PointerUnion.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Value.h"

namespace llvm {

/// Keeps information about pending match queries.
///
/// This class stores state of all unfinished match actions. It allows to
/// use queries like "this operand is the same as n-th operand", which are
/// hard to implement otherwise.
///
class MatcherContext {
public:

  /// Describes pending match query.
  ///
  /// The query is represented by the current entity being investigated (type,
  /// value or metadata). If the entity is a member of a list (like arguments),
  /// the query also keeps the entity number in that list.
  ///
  class Query {
    PointerUnion3<const Value *, const Metadata *, const Type *> Entity;
    unsigned OperandNo;

  public:
    Query(const Value *V, unsigned N) : Entity(V), OperandNo(N) {}
    Query(const Metadata *M, unsigned N) : Entity(M), OperandNo(N) {}
    Query(const Type *T, unsigned N) : Entity(T), OperandNo(N) {}

    template<typename T>
    const T *get() const {
      return Entity.dyn_cast<const T *>();
    }

    unsigned getOperandNo() const { return OperandNo; }
  };

  template<typename T>
  void push(const T *V, unsigned N = ~0) {
    MatchStack.push_back(Query(V, N));
  }

  void pop() { MatchStack.pop_back(); }

  template<typename T>
  const T *top() const { return MatchStack.back().get<T>(); }

  size_t size() const { return MatchStack.size(); }

  unsigned getOperandNo() const { return MatchStack.back().getOperandNo(); }

  /// Returns match query at the given offset from the top of queries.
  ///
  /// Offset 0 corresponds to the topmost query.
  ///
  const Query &getQuery(unsigned Offset) const {
    assert(MatchStack.size() > Offset);
    return MatchStack[MatchStack.size() - 1 - Offset];
  }

private:
  SmallVector<Query, 8> MatchStack;
};


/// Base of all matcher classes.
///
class Matcher {
public:
  virtual ~Matcher() {}

  /// Returns true if the entity on the top of the specified context satisfies
  /// the matcher condition.
  ///
  virtual bool match(MatcherContext &MC) = 0;
};


/// Base class of matchers that test particular entity.
///
template<typename T>
class EntityMatcher : public Matcher {
public:
  bool match(MatcherContext &MC) override {
    if (auto V = MC.top<T>())
      return matchEntity(*V, MC);
    return false;
  }
  virtual bool matchEntity(const T &M, MatcherContext &C) = 0;
};


/// Matcher that matches any entity of the specified kind.
///
template<typename T>
class AnyMatcher : public EntityMatcher<T> {
public:
  bool matchEntity(const T &M, MatcherContext &C) override { return true; }
};


/// Matcher that tests if the current entity satisfies the specified
/// condition.
///
template<typename T>
class CondMatcher : public EntityMatcher<T> {
  std::function<bool(const T &)> Condition;
public:
  CondMatcher(std::function<bool(const T &)> C) : Condition(C) {}
  bool matchEntity(const T &V, MatcherContext &C) override {
    return Condition(V);
  }
};


/// Matcher that save pointer to the entity that satisfies condition of the
// specified matcher.
///
template<typename T>
class SavingMatcher : public EntityMatcher<T> {
  const T *&Var;
  std::shared_ptr<Matcher> Next;
public:
  SavingMatcher(const T *&V, std::shared_ptr<Matcher> N) : Var(V), Next(N) {}
  bool matchEntity(const T &V, MatcherContext &C) override {
    bool Result = Next->match(C);
    if (Result)
      Var = &V;
    return Result;
  }
};


/// Matcher that checks that the entity is identical to another entity in the
/// same container.
///
class SameAsMatcher : public Matcher {
  unsigned OpNo;
public:
  SameAsMatcher(unsigned N) : OpNo(N) {}
  bool match(MatcherContext &C) override {
    if (C.getOperandNo() != ~0U) {
      // Handle all known containers here.
      const MatcherContext::Query &StackRec = C.getQuery(1);
      if (const Metadata *MR = StackRec.get<Metadata>()) {
        if (const auto *MT = dyn_cast<MDTuple>(MR)) {
          if (OpNo < MT->getNumOperands())
            return C.top<Metadata>() == MT->getOperand(OpNo).get();
          return false;
        }
        llvm_unreachable("Unknown metadata container");
      }
      if (const Value *VR = StackRec.get<Value>()) {
        if (const auto *Insn = dyn_cast<Instruction>(VR)) {
          if (OpNo < Insn->getNumOperands())
            return C.top<Value>() == Insn->getOperand(OpNo);
          return false;
        }
        llvm_unreachable("Unknown value container");
      }
      llvm_unreachable("Unknown type container");
    }
    return false;
  }
};


/// Matcher that tests if the entity is a constant integer.
///
class ConstantIntMatcher : public Matcher {
  uint64_t IntValue;
  unsigned Width;
public:
  ConstantIntMatcher(uint64_t V, unsigned W = 0) : IntValue(V), Width(W) {}
  bool match(MatcherContext &Ctx) override {
    if (const Value *V = Ctx.top<Value>()) {
      if (const auto *CI = dyn_cast<ConstantInt>(V))
        return (Width == 0 || CI->getBitWidth() == Width) &&
               CI->getLimitedValue() == IntValue;
    }
    if (const Metadata *M = Ctx.top<Metadata>()) {
      if (const auto *MT = dyn_cast<ValueAsMetadata>(M))
        if (const auto *C = dyn_cast<ConstantInt>(MT->getValue()))
          return (Width == 0 || C->getBitWidth() == Width) &&
                 C->getLimitedValue() == IntValue;
    }
    return false;
  }
};


/// Value matcher tuned to test instructions.
///
class InstructionMatcher : public EntityMatcher<Value> {
  SmallVector<std::shared_ptr<Matcher>, 8> OperandMatchers;
  std::shared_ptr<EntityMatcher<Metadata>> MetaMatcher = nullptr;
  unsigned Code;
public:
  InstructionMatcher(unsigned C) : Code(C) {}

  void push(std::shared_ptr<EntityMatcher<Metadata>> M) {
    assert(!MetaMatcher && "Only one metadata matcher may be specified");
    MetaMatcher = M;
  }
  void push(std::shared_ptr<Matcher> V) { OperandMatchers.push_back(V); }
  template<typename... Args>
  void push(std::shared_ptr<Matcher> V, Args... A) {
    push(V);
    push(A...);
  }

  virtual bool matchInstruction(const Instruction &I) {
    return I.getOpcode() == Code;
  }

  bool matchEntity(const Value &V, MatcherContext &C) override {
    if (const auto *I = dyn_cast<Instruction>(&V)) {
      if (!matchInstruction(*I))
        return false;
      if (OperandMatchers.size() > I->getNumOperands())
        return false;
      for (unsigned N = 0, E = OperandMatchers.size(); N != E; ++N) {
        C.push(I->getOperand(N), N);
        if (!OperandMatchers[N]->match(C)) {
          C.pop();
          return false;
        }
        C.pop();
      }
      if (MetaMatcher) {
        SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
        I->getAllMetadata(MDs);
        bool Found = false;
        for (auto Item : MDs) {
          C.push(Item.second);
          if (MetaMatcher->match(C)) {
            Found = true;
            C.pop();
            break;
          }
          C.pop();
        }
        return Found;
      }
      return true;
    }
    return false;
  }
};


/// Matcher that tests type of the current value using the specified
/// type matcher.
///
class ValueTypeMatcher : public EntityMatcher<Value> {
  std::shared_ptr<EntityMatcher<Type>> TyM;
public:
  ValueTypeMatcher(std::shared_ptr<EntityMatcher<Type>> T) : TyM(T) {}
  ValueTypeMatcher(const Type *T)
    : TyM(new CondMatcher<Type>([T](const Type &Ty) -> bool {
                                  return &Ty == T;
                                })) {}
  bool matchEntity(const Value &V, MatcherContext &Ctx) override {
    Type *Ty = V.getType();
    Ctx.push(Ty);
    bool Res = TyM->match(Ctx);
    Ctx.pop();
    return Res;
  }
};


/// Matcher that matches string metadata.
///
class NameMetaMatcher : public EntityMatcher<Metadata> {
  StringRef Name;
public:
  NameMetaMatcher(StringRef N) : Name(N) {}
  bool matchEntity(const Metadata &M, MatcherContext &C) override {
    if (auto *MDS = dyn_cast<MDString>(&M))
      return MDS->getString().equals(Name);
    return false;
  }
};


/// Matcher that matches metadata tuples.
///
class MTupleMatcher : public EntityMatcher<Metadata> {
  SmallVector<std::shared_ptr<Matcher>, 4> Operands;
public:
  void push(std::shared_ptr<Matcher> M) { Operands.push_back(M); }
  template<typename... Args>
  void push(std::shared_ptr<Matcher> M, Args... A) {
    push(M);
    push(A...);
  }
  bool matchEntity(const Metadata &M, MatcherContext &C) override {
    if (const auto *MT = dyn_cast<MDTuple>(&M)) {
      if (MT->getNumOperands() != Operands.size())
        return false;
      for (unsigned I = 0, E = MT->getNumOperands(); I != E; ++I) {
        const MDOperand &Op = MT->getOperand(I);
        C.push(Op.get(), I);
        if (!Operands[I]->match(C)) {
          C.pop();
          return false;
        }
        C.pop();
      }
      return true;
    }
    return false;
  }
};


// Helper function used to construct matchers.

inline std::shared_ptr<Matcher> MSameAs(unsigned N) {
  return std::shared_ptr<Matcher>(new SameAsMatcher(N));
}

template<typename... T>
std::shared_ptr<InstructionMatcher> MInstruction(unsigned C, T... Args) {
  auto Result = new InstructionMatcher(C);
  Result->push(Args...);
  return std::shared_ptr<InstructionMatcher>(Result);
}

inline std::shared_ptr<Matcher> MConstInt(uint64_t V, unsigned W = 0) {
  return std::shared_ptr<Matcher>(new ConstantIntMatcher(V, W));
}

inline std::shared_ptr<EntityMatcher<Value>>
MValType(std::shared_ptr<EntityMatcher<Type>> T) {
  return std::shared_ptr<EntityMatcher<Value>>(new ValueTypeMatcher(T));
}

inline std::shared_ptr<EntityMatcher<Value>> MValType(const Type *T) {
  return std::shared_ptr<EntityMatcher<Value>>(new ValueTypeMatcher(T));
}

inline std::shared_ptr<EntityMatcher<Type>>
MType(std::function<bool(const Type &)> C) {
  return std::shared_ptr<EntityMatcher<Type>>(new CondMatcher<Type>(C));
}

inline std::shared_ptr<EntityMatcher<Metadata>> MMAny() {
  return std::shared_ptr<EntityMatcher<Metadata>>(new AnyMatcher<Metadata>);
}

inline std::shared_ptr<EntityMatcher<Metadata>>
MMSave(const Metadata *&V, std::shared_ptr<EntityMatcher<Metadata>> M) {
  return std::shared_ptr<EntityMatcher<Metadata>>(
      new SavingMatcher<Metadata>(V, M));
}

inline std::shared_ptr<EntityMatcher<Metadata>> MMString(const char *Name) {
  return std::shared_ptr<EntityMatcher<Metadata>>(new NameMetaMatcher(Name));
}

template<typename... T>
std::shared_ptr<EntityMatcher<Metadata>> MMTuple(T... Args) {
  auto Res = new MTupleMatcher();
  Res->push(Args...);
  return std::shared_ptr<EntityMatcher<Metadata>>(Res);
}


/// Looks for the instruction that satisfies condition of the specified
/// matcher inside the given basic block.
/// \returns Pointer to the found instruction or nullptr if such instruction
///          was not found.
///
inline const Instruction *match(const BasicBlock *BB,
                                std::shared_ptr<Matcher> M) {
  MatcherContext MC;
  for (const auto &I : *BB) {
    MC.push(&I);
    if (M->match(MC))
      return &I;
    MC.pop();
  }
  assert(MC.size() == 0);
  return nullptr;
}

/// Looks for the instruction that satisfies condition of the specified
/// matcher starting from the specified instruction inside the same basic block.
///
/// The given instruction is not checked.
///
inline const Instruction *matchNext(const Instruction *I, std::shared_ptr<Matcher> M) {
  if (!I)
    return nullptr;
  MatcherContext MC;
  const BasicBlock *BB = I->getParent();
  if (!BB)
    return nullptr;
  for (auto P = ++BasicBlock::const_iterator(I), E = BB->end(); P != E; ++P) {
    MC.push(&*P);
    if (M->match(MC))
      return &*P;
    MC.pop();
  }
  assert(MC.size() == 0);
  return nullptr;
}

}
#endif
