mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Revert "Avoid creating an immutable map in the Automaton class."
This reverts commit 051d330314cb1f175025ca37da8e5e1d851e1790. It broke buildbots, for example, http://lab.llvm.org:8011/builders/clang-x86_64-debian-fast/builds/21908.
This commit is contained in:
parent
269a6bd0b2
commit
bac0121a4b
@ -154,42 +154,29 @@ public:
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
// Type representing a transition in the DFA state.
|
||||
// The action type can be a custom type.
|
||||
template <typename ActionT> struct TransitionType {
|
||||
using StateT = unsigned;
|
||||
StateT FromDfaState; // The transitioned-from DFA state.
|
||||
ActionT Action; // The input symbol that causes this transition.
|
||||
StateT ToDfaState; // The transitioned-to DFA state.
|
||||
unsigned InfoIdx; // Start index into TransitionInfo.
|
||||
};
|
||||
|
||||
/// A deterministic finite-state automaton. The automaton is defined in
|
||||
/// TableGen; this object drives an automaton defined by tblgen-emitted tables.
|
||||
///
|
||||
/// An automaton accepts a sequence of input tokens ("actions"). This class is
|
||||
/// templated on the type of these actions.
|
||||
template <typename ActionT> class Automaton {
|
||||
using TransitionT = TransitionType<ActionT>;
|
||||
using TransitionKeyT = std::pair<decltype(TransitionT::FromDfaState),
|
||||
decltype(TransitionT::Action)>;
|
||||
using StateT = typename TransitionT::StateT;
|
||||
/// Map from {State, Action} to {NewState, TransitionInfoIdx}.
|
||||
/// TransitionInfoIdx is used by the DfaTranscriber to analyze the transition.
|
||||
ArrayRef<TransitionT> TransitionMap;
|
||||
/// FIXME: This uses a std::map because ActionT can be a pair type including
|
||||
/// an enum. In particular DenseMapInfo<ActionT> must be defined to use
|
||||
/// DenseMap here.
|
||||
/// This is a shared_ptr to allow very quick copy-construction of Automata; this
|
||||
/// state is immutable after construction so this is safe.
|
||||
using MapTy = std::map<std::pair<uint64_t, ActionT>, std::pair<uint64_t, unsigned>>;
|
||||
std::shared_ptr<MapTy> M;
|
||||
/// An optional transcription object. This uses much more state than simply
|
||||
/// traversing the DFA for acceptance, so is heap allocated.
|
||||
std::shared_ptr<internal::NfaTranscriber> Transcriber;
|
||||
/// The initial DFA state is 1.
|
||||
StateT State = 1;
|
||||
uint64_t State = 1;
|
||||
/// True if we should transcribe and false if not (even if Transcriber is defined).
|
||||
bool Transcribe;
|
||||
|
||||
static bool transitionLessThan(const TransitionT &A,
|
||||
const TransitionKeyT &B) {
|
||||
return std::make_pair(A.FromDfaState, A.Action) < B;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Create an automaton.
|
||||
/// \param Transitions The Transitions table as created by TableGen. Note that
|
||||
@ -202,24 +189,21 @@ public:
|
||||
/// NFA taken by the DFA. NOTE: This is substantially more work than simply
|
||||
/// driving the DFA, so unless you require the getPaths() method leave this
|
||||
/// empty.
|
||||
Automaton(ArrayRef<TransitionT> Transitions,
|
||||
template <typename InfoT>
|
||||
Automaton(ArrayRef<InfoT> Transitions,
|
||||
ArrayRef<NfaStatePair> TranscriptionTable = {}) {
|
||||
if (!TranscriptionTable.empty())
|
||||
Transcriber =
|
||||
std::make_shared<internal::NfaTranscriber>(TranscriptionTable);
|
||||
Transcribe = Transcriber != nullptr;
|
||||
TransitionMap = Transitions;
|
||||
assert(std::is_sorted(TransitionMap.begin(), TransitionMap.end(),
|
||||
[](const TransitionT &A, const TransitionT &B) {
|
||||
return std::make_pair(A.FromDfaState, A.Action) <
|
||||
std::make_pair(B.FromDfaState, B.Action);
|
||||
}) &&
|
||||
"The transitions array is expected to be sorted by FromDfaState and "
|
||||
"Action");
|
||||
M = std::make_shared<MapTy>();
|
||||
for (const auto &I : Transitions)
|
||||
// Greedily read and cache the transition table.
|
||||
M->emplace(std::make_pair(I.FromDfaState, I.Action),
|
||||
std::make_pair(I.ToDfaState, I.InfoIdx));
|
||||
}
|
||||
Automaton(const Automaton &Other)
|
||||
: TransitionMap(Other.TransitionMap), State(Other.State),
|
||||
Transcribe(Other.Transcribe) {
|
||||
: M(Other.M), State(Other.State), Transcribe(Other.Transcribe) {
|
||||
// Transcriber is not thread-safe, so create a new instance on copy.
|
||||
if (Other.Transcriber)
|
||||
Transcriber = std::make_shared<internal::NfaTranscriber>(
|
||||
@ -249,22 +233,19 @@ public:
|
||||
/// If this function returns false, all methods are undefined until reset() is
|
||||
/// called.
|
||||
bool add(const ActionT &A) {
|
||||
auto I = lower_bound(TransitionMap.begin(), TransitionMap.end(),
|
||||
std::make_pair(State, A), transitionLessThan);
|
||||
if (I == TransitionMap.end() || State != I->FromDfaState || A != I->Action)
|
||||
auto I = M->find({State, A});
|
||||
if (I == M->end())
|
||||
return false;
|
||||
if (Transcriber && Transcribe)
|
||||
Transcriber->transition(I->InfoIdx);
|
||||
State = I->ToDfaState;
|
||||
Transcriber->transition(I->second.second);
|
||||
State = I->second.first;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Return true if the automaton can be transitioned based on input symbol A.
|
||||
bool canAdd(const ActionT &A) {
|
||||
auto I = lower_bound(TransitionMap.begin(), TransitionMap.end(),
|
||||
std::make_pair(State, A), transitionLessThan);
|
||||
return I != TransitionMap.end() && State == I->FromDfaState &&
|
||||
A == I->Action;
|
||||
auto I = M->find({State, A});
|
||||
return I != M->end();
|
||||
}
|
||||
|
||||
/// Obtain a set of possible paths through the input nondeterministic
|
||||
|
@ -131,9 +131,15 @@ void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
|
||||
OS << "}};\n\n";
|
||||
|
||||
OS << "// A transition in the generated " << Name << " DFA.\n";
|
||||
OS << "using " << Name << "Transition = TransitionType<";
|
||||
OS << "struct " << Name << "Transition {\n";
|
||||
OS << " unsigned FromDfaState; // The transitioned-from DFA state.\n";
|
||||
OS << " ";
|
||||
printActionType(OS);
|
||||
OS << ">;\n\n";
|
||||
OS << " Action; // The input symbol that causes this transition.\n";
|
||||
OS << " unsigned ToDfaState; // The transitioned-to DFA state.\n";
|
||||
OS << " unsigned InfoIdx; // Start index into " << Name
|
||||
<< "TransitionInfo.\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
OS << "// A table of DFA transitions, ordered by {FromDfaState, Action}.\n";
|
||||
OS << "// The initial state is 1, not zero.\n";
|
||||
|
Loading…
Reference in New Issue
Block a user