blob: 91d70a8393d8689e9e1c8918981e1fc6d18024eb [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UTILS_TABLEGEN_DECODERTREE_H
#define LLVM_UTILS_TABLEGEN_DECODERTREE_H
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include <map>
#include <memory>
namespace llvm {
class InstructionEncoding;
using PredicateSet = SetVector<CachedHashString>;
using DecoderSet = SetVector<CachedHashString>;
/// Context shared across decoder trees.
/// Predicates and decoders are shared across decoder trees to provide more
/// opportunities for uniqueness. If SpecializeDecodersPerBitwidth is enabled,
/// decoders are shared across all trees for a given bitwidth, else they are
/// shared across all trees. Predicates are always shared across all trees.
struct DecoderContext {
PredicateSet Predicates;
DecoderSet Decoders;
unsigned getPredicateIndex(StringRef Predicate) {
Predicates.insert(CachedHashString(Predicate));
PredicateSet::const_iterator I = find(Predicates, Predicate);
return std::distance(Predicates.begin(), I);
}
unsigned getDecoderIndex(StringRef Decoder) {
Decoders.insert(CachedHashString(Decoder));
DecoderSet::const_iterator I = find(Decoders, Decoder);
return std::distance(Decoders.begin(), I);
}
};
class DecoderTreeNode {
public:
virtual ~DecoderTreeNode();
enum KindTy {
CheckAny,
CheckAll,
CheckField,
SwitchField,
CheckPredicate,
SoftFail,
Decode,
};
KindTy getKind() const { return Kind; }
protected:
explicit DecoderTreeNode(KindTy Kind) : Kind(Kind) {}
private:
KindTy Kind;
};
/// Common base class for nodes with multiple children.
class CheckManyNode : public DecoderTreeNode {
SmallVector<std::unique_ptr<DecoderTreeNode>, 0> Children;
static const DecoderTreeNode *
mapElement(decltype(Children)::const_reference Element) {
return Element.get();
}
protected:
explicit CheckManyNode(KindTy Kind) : DecoderTreeNode(Kind) {}
public:
void addChild(std::unique_ptr<DecoderTreeNode> Child) {
Children.push_back(std::move(Child));
}
using child_iterator = mapped_iterator<decltype(Children)::const_iterator,
decltype(&mapElement)>;
child_iterator child_begin() const {
return child_iterator(Children.begin(), mapElement);
}
child_iterator child_end() const {
return child_iterator(Children.end(), mapElement);
}
iterator_range<child_iterator> children() const {
return make_range(child_begin(), child_end());
}
};
/// Executes child nodes one by one until one of them succeeds or all fail.
/// The node fails if all child nodes fail. It never succeeds, because if a
/// child node succeeds, it does not return.
class CheckAnyNode : public CheckManyNode {
public:
CheckAnyNode() : CheckManyNode(CheckAny) {}
};
/// Executes child nodes one by one until one of them fails all all succeed.
/// The node fails if any of the child nodes fails.
class CheckAllNode : public CheckManyNode {
public:
CheckAllNode() : CheckManyNode(CheckAll) {}
};
/// Checks the value of encoding bits in the specified range.
class CheckFieldNode : public DecoderTreeNode {
unsigned StartBit;
unsigned NumBits;
uint64_t Value;
public:
CheckFieldNode(unsigned StartBit, unsigned NumBits, uint64_t Value)
: DecoderTreeNode(CheckField), StartBit(StartBit), NumBits(NumBits),
Value(Value) {}
unsigned getStartBit() const { return StartBit; }
unsigned getNumBits() const { return NumBits; }
uint64_t getValue() const { return Value; }
};
/// Switch based on the value of encoding bits in the specified range.
/// If the value of the bits in the range doesn't match any of the cases,
/// the node fails. This is semantically equivalent to CheckAny node where
/// every child is a CheckField node, but is faster.
class SwitchFieldNode : public DecoderTreeNode {
unsigned StartBit;
unsigned NumBits;
std::map<uint64_t, std::unique_ptr<DecoderTreeNode>> Cases;
static std::pair<uint64_t, const DecoderTreeNode *>
mapElement(decltype(Cases)::const_reference Element) {
return std::pair(Element.first, Element.second.get());
}
public:
SwitchFieldNode(unsigned StartBit, unsigned NumBits)
: DecoderTreeNode(SwitchField), StartBit(StartBit), NumBits(NumBits) {}
void addCase(uint64_t Value, std::unique_ptr<DecoderTreeNode> N) {
Cases.try_emplace(Value, std::move(N));
}
unsigned getStartBit() const { return StartBit; }
unsigned getNumBits() const { return NumBits; }
using case_iterator =
mapped_iterator<decltype(Cases)::const_iterator, decltype(&mapElement)>;
case_iterator case_begin() const {
return case_iterator(Cases.begin(), mapElement);
}
case_iterator case_end() const {
return case_iterator(Cases.end(), mapElement);
}
iterator_range<case_iterator> cases() const {
return make_range(case_begin(), case_end());
}
};
/// Checks that the instruction to be decoded has its predicates satisfied.
class CheckPredicateNode : public DecoderTreeNode {
unsigned PredicateIndex;
public:
explicit CheckPredicateNode(unsigned PredicateIndex)
: DecoderTreeNode(CheckPredicate), PredicateIndex(PredicateIndex) {}
unsigned getPredicateIndex() const { return PredicateIndex; }
};
/// Checks if the encoding bits are correct w.r.t. SoftFail semantics.
/// This is the only node that can never fail.
class SoftFailNode : public DecoderTreeNode {
uint64_t PositiveMask, NegativeMask;
public:
SoftFailNode(uint64_t PositiveMask, uint64_t NegativeMask)
: DecoderTreeNode(SoftFail), PositiveMask(PositiveMask),
NegativeMask(NegativeMask) {}
uint64_t getPositiveMask() const { return PositiveMask; }
uint64_t getNegativeMask() const { return NegativeMask; }
};
/// Attempts to decode the specified encoding as the specified instruction.
class DecodeNode : public DecoderTreeNode {
StringRef EncodingName;
unsigned InstOpcode;
unsigned DecoderIndex;
public:
DecodeNode(StringRef EncodingName, unsigned InstOpcode, unsigned DecoderIndex)
: DecoderTreeNode(Decode), EncodingName(EncodingName),
InstOpcode(InstOpcode), DecoderIndex(DecoderIndex) {}
StringRef getEncodingName() const { return EncodingName; }
unsigned getInstOpcode() const { return InstOpcode; }
unsigned getDecoderIndex() const { return DecoderIndex; }
};
} // namespace llvm
#endif // LLVM_UTILS_TABLEGEN_DECODERTREE_H