Update prebuilt Clang to r416183b from Android.
https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef
clang 12.0.5 (based on r416183b) from build 7284624.
Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/TableGen/Automaton.td b/linux-x64/clang/include/llvm/TableGen/Automaton.td
new file mode 100644
index 0000000..13ced2a
--- /dev/null
+++ b/linux-x64/clang/include/llvm/TableGen/Automaton.td
@@ -0,0 +1,95 @@
+//===- Automaton.td ----------------------------------------*- tablegen -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the key top-level classes needed to produce a reasonably
+// generic finite-state automaton.
+//
+//===----------------------------------------------------------------------===//
+
+// Define a record inheriting from GenericAutomaton to generate a reasonably
+// generic finite-state automaton over a set of actions and states.
+//
+// This automaton is defined by:
+// 1) a state space (explicit, always bits<32>).
+// 2) a set of input symbols (actions, explicit) and
+// 3) a transition function from state + action -> state.
+//
+// A theoretical automaton is defined by <Q, S, d, q0, F>:
+// Q: A set of possible states.
+// S: (sigma) The input alphabet.
+// d: (delta) The transition function f(q in Q, s in S) -> q' in Q.
+// F: The set of final (accepting) states.
+//
+// Because generating all possible states is tedious, we instead define the
+// transition function only and crawl all reachable states starting from the
+// initial state with all inputs under all transitions until termination.
+//
+// We define F = S, that is, all valid states are accepting.
+//
+// To ensure the generation of the automaton terminates, the state transitions
+// are defined as a lattice (meaning every transitioned-to state is more
+// specific than the transitioned-from state, for some definition of specificity).
+// Concretely a transition may set one or more bits in the state that were
+// previously zero to one. If any bit was not zero, the transition is invalid.
+//
+// Instead of defining all possible states (which would be cumbersome), the user
+// provides a set of possible Transitions from state A, consuming an input
+// symbol A to state B. The Transition object transforms state A to state B and
+// acts as a predicate. This means the state space can be discovered by crawling
+// all the possible transitions until none are valid.
+//
+// This automaton is considered to be nondeterministic, meaning that multiple
+// transitions can occur from any (state, action) pair. The generated automaton
+// is determinized, meaning that is executes in O(k) time where k is the input
+// sequence length.
+//
+// In addition to a generated automaton that determines if a sequence of inputs
+// is accepted or not, a table is emitted that allows determining a plausible
+// sequence of states traversed to accept that input.
+class GenericAutomaton {
+ // Name of a class that inherits from Transition. All records inheriting from
+ // this class will be considered when constructing the automaton.
+ string TransitionClass;
+
+ // Names of fields within TransitionClass that define the action symbol. This
+ // defines the action as an N-tuple.
+ //
+ // Each symbol field can be of class, int, string or code type.
+ // If the type of a field is a class, the Record's name is used verbatim
+ // in C++ and the class name is used as the C++ type name.
+ // If the type of a field is a string, code or int, that is also used
+ // verbatim in C++.
+ //
+ // To override the C++ type name for field F, define a field called TypeOf_F.
+ // This should be a string that will be used verbatim in C++.
+ //
+ // As an example, to define a 2-tuple with an enum and a string, one might:
+ // def MyTransition : Transition {
+ // MyEnum S1;
+ // int S2;
+ // }
+ // def MyAutomaton : GenericAutomaton }{
+ // let TransitionClass = "Transition";
+ // let SymbolFields = ["S1", "S2"];
+ // let TypeOf_S1 = "MyEnumInCxxKind";
+ // }
+ list<string> SymbolFields;
+}
+
+// All transitions inherit from Transition.
+class Transition {
+ // A transition S' = T(S) is valid if, for every set bit in NewState, the
+ // corresponding bit in S is clear. That is:
+ // def T(S):
+ // S' = S | NewState
+ // return S' if S' != S else Failure
+ //
+ // The automaton generator uses this property to crawl the set of possible
+ // transitions from a starting state of 0b0.
+ bits<32> NewState;
+}
diff --git a/linux-x64/clang/include/llvm/TableGen/DirectiveEmitter.h b/linux-x64/clang/include/llvm/TableGen/DirectiveEmitter.h
new file mode 100644
index 0000000..41258ad
--- /dev/null
+++ b/linux-x64/clang/include/llvm/TableGen/DirectiveEmitter.h
@@ -0,0 +1,216 @@
+#ifndef LLVM_TABLEGEN_DIRECTIVEEMITTER_H
+#define LLVM_TABLEGEN_DIRECTIVEEMITTER_H
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Record.h"
+
+namespace llvm {
+
+// Wrapper class that contains DirectiveLanguage's information defined in
+// DirectiveBase.td and provides helper methods for accessing it.
+class DirectiveLanguage {
+public:
+ explicit DirectiveLanguage(const llvm::RecordKeeper &Records)
+ : Records(Records) {
+ const auto &DirectiveLanguages = getDirectiveLanguages();
+ Def = DirectiveLanguages[0];
+ }
+
+ StringRef getName() const { return Def->getValueAsString("name"); }
+
+ StringRef getCppNamespace() const {
+ return Def->getValueAsString("cppNamespace");
+ }
+
+ StringRef getDirectivePrefix() const {
+ return Def->getValueAsString("directivePrefix");
+ }
+
+ StringRef getClausePrefix() const {
+ return Def->getValueAsString("clausePrefix");
+ }
+
+ StringRef getIncludeHeader() const {
+ return Def->getValueAsString("includeHeader");
+ }
+
+ StringRef getClauseEnumSetClass() const {
+ return Def->getValueAsString("clauseEnumSetClass");
+ }
+
+ StringRef getFlangClauseBaseClass() const {
+ return Def->getValueAsString("flangClauseBaseClass");
+ }
+
+ bool hasMakeEnumAvailableInNamespace() const {
+ return Def->getValueAsBit("makeEnumAvailableInNamespace");
+ }
+
+ bool hasEnableBitmaskEnumInNamespace() const {
+ return Def->getValueAsBit("enableBitmaskEnumInNamespace");
+ }
+
+ const std::vector<Record *> getDirectives() const {
+ return Records.getAllDerivedDefinitions("Directive");
+ }
+
+ const std::vector<Record *> getClauses() const {
+ return Records.getAllDerivedDefinitions("Clause");
+ }
+
+ bool HasValidityErrors() const;
+
+private:
+ const llvm::Record *Def;
+ const llvm::RecordKeeper &Records;
+
+ const std::vector<Record *> getDirectiveLanguages() const {
+ return Records.getAllDerivedDefinitions("DirectiveLanguage");
+ }
+};
+
+// Base record class used for Directive and Clause class defined in
+// DirectiveBase.td.
+class BaseRecord {
+public:
+ explicit BaseRecord(const llvm::Record *Def) : Def(Def) {}
+
+ StringRef getName() const { return Def->getValueAsString("name"); }
+
+ StringRef getAlternativeName() const {
+ return Def->getValueAsString("alternativeName");
+ }
+
+ // Returns the name of the directive formatted for output. Whitespace are
+ // replaced with underscores.
+ std::string getFormattedName() {
+ StringRef Name = Def->getValueAsString("name");
+ std::string N = Name.str();
+ std::replace(N.begin(), N.end(), ' ', '_');
+ return N;
+ }
+
+ bool isDefault() const { return Def->getValueAsBit("isDefault"); }
+
+ // Returns the record name.
+ const StringRef getRecordName() const { return Def->getName(); }
+
+protected:
+ const llvm::Record *Def;
+};
+
+// Wrapper class that contains a Directive's information defined in
+// DirectiveBase.td and provides helper methods for accessing it.
+class Directive : public BaseRecord {
+public:
+ explicit Directive(const llvm::Record *Def) : BaseRecord(Def) {}
+
+ std::vector<Record *> getAllowedClauses() const {
+ return Def->getValueAsListOfDefs("allowedClauses");
+ }
+
+ std::vector<Record *> getAllowedOnceClauses() const {
+ return Def->getValueAsListOfDefs("allowedOnceClauses");
+ }
+
+ std::vector<Record *> getAllowedExclusiveClauses() const {
+ return Def->getValueAsListOfDefs("allowedExclusiveClauses");
+ }
+
+ std::vector<Record *> getRequiredClauses() const {
+ return Def->getValueAsListOfDefs("requiredClauses");
+ }
+};
+
+// Wrapper class that contains Clause's information defined in DirectiveBase.td
+// and provides helper methods for accessing it.
+class Clause : public BaseRecord {
+public:
+ explicit Clause(const llvm::Record *Def) : BaseRecord(Def) {}
+
+ // Optional field.
+ StringRef getClangClass() const {
+ return Def->getValueAsString("clangClass");
+ }
+
+ // Optional field.
+ StringRef getFlangClass() const {
+ return Def->getValueAsString("flangClass");
+ }
+
+ // Optional field.
+ StringRef getFlangClassValue() const {
+ return Def->getValueAsString("flangClassValue");
+ }
+
+ // Get the formatted name for Flang parser class. The generic formatted class
+ // name is constructed from the name were the first letter of each word is
+ // captitalized and the underscores are removed.
+ // ex: async -> Async
+ // num_threads -> NumThreads
+ std::string getFormattedParserClassName() {
+ StringRef Name = Def->getValueAsString("name");
+ std::string N = Name.str();
+ bool Cap = true;
+ std::transform(N.begin(), N.end(), N.begin(), [&Cap](unsigned char C) {
+ if (Cap == true) {
+ C = llvm::toUpper(C);
+ Cap = false;
+ } else if (C == '_') {
+ Cap = true;
+ }
+ return C;
+ });
+ N.erase(std::remove(N.begin(), N.end(), '_'), N.end());
+ return N;
+ }
+
+ // Optional field.
+ StringRef getEnumName() const {
+ return Def->getValueAsString("enumClauseValue");
+ }
+
+ std::vector<Record *> getClauseVals() const {
+ return Def->getValueAsListOfDefs("allowedClauseValues");
+ }
+
+ bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
+
+ bool isValueList() const { return Def->getValueAsBit("isValueList"); }
+
+ StringRef getDefaultValue() const {
+ return Def->getValueAsString("defaultValue");
+ }
+
+ bool isImplicit() const { return Def->getValueAsBit("isImplicit"); }
+};
+
+// Wrapper class that contains VersionedClause's information defined in
+// DirectiveBase.td and provides helper methods for accessing it.
+class VersionedClause {
+public:
+ explicit VersionedClause(const llvm::Record *Def) : Def(Def) {}
+
+ // Return the specific clause record wrapped in the Clause class.
+ Clause getClause() const { return Clause{Def->getValueAsDef("clause")}; }
+
+ int64_t getMinVersion() const { return Def->getValueAsInt("minVersion"); }
+
+ int64_t getMaxVersion() const { return Def->getValueAsInt("maxVersion"); }
+
+private:
+ const llvm::Record *Def;
+};
+
+class ClauseVal : public BaseRecord {
+public:
+ explicit ClauseVal(const llvm::Record *Def) : BaseRecord(Def) {}
+
+ int getValue() const { return Def->getValueAsInt("value"); }
+
+ bool isUserVisible() const { return Def->getValueAsBit("isUserValue"); }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/TableGen/Error.h b/linux-x64/clang/include/llvm/TableGen/Error.h
index 7c83b62..f63b50a 100644
--- a/linux-x64/clang/include/llvm/TableGen/Error.h
+++ b/linux-x64/clang/include/llvm/TableGen/Error.h
@@ -15,22 +15,38 @@
#define LLVM_TABLEGEN_ERROR_H
#include "llvm/Support/SourceMgr.h"
+#include "llvm/TableGen/Record.h"
namespace llvm {
+void PrintNote(const Twine &Msg);
void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(ArrayRef<SMLoc> ErrorLoc,
+ const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const Record *Rec,
+ const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void PrintFatalNote(const RecordVal *RecVal,
+ const Twine &Msg);
+
+void PrintWarning(const Twine &Msg);
void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg);
void PrintWarning(const char *Loc, const Twine &Msg);
-void PrintWarning(const Twine &Msg);
+void PrintError(const Twine &Msg);
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
void PrintError(const char *Loc, const Twine &Msg);
-void PrintError(const Twine &Msg);
+void PrintError(const Record *Rec, const Twine &Msg);
+void PrintError(const RecordVal *RecVal, const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc,
const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const Record *Rec,
+ const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const RecordVal *RecVal,
+ const Twine &Msg);
extern SourceMgr SrcMgr;
extern unsigned ErrorsPrinted;
diff --git a/linux-x64/clang/include/llvm/TableGen/Main.h b/linux-x64/clang/include/llvm/TableGen/Main.h
index e464cd4..4e05da3 100644
--- a/linux-x64/clang/include/llvm/TableGen/Main.h
+++ b/linux-x64/clang/include/llvm/TableGen/Main.h
@@ -22,7 +22,7 @@
/// Returns true on error, false otherwise.
using TableGenMainFn = bool (raw_ostream &OS, RecordKeeper &Records);
-int TableGenMain(char *argv0, TableGenMainFn *MainFn);
+int TableGenMain(const char *argv0, TableGenMainFn *MainFn);
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/TableGen/Record.h b/linux-x64/clang/include/llvm/TableGen/Record.h
index bf7f022..2853a47 100644
--- a/linux-x64/clang/include/llvm/TableGen/Record.h
+++ b/linux-x64/clang/include/llvm/TableGen/Record.h
@@ -24,6 +24,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/Timer.h"
#include "llvm/Support/TrailingObjects.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -57,7 +58,6 @@
enum RecTyKind {
BitRecTyKind,
BitsRecTyKind,
- CodeRecTyKind,
IntRecTyKind,
StringRecTyKind,
ListRecTyKind,
@@ -67,6 +67,7 @@
private:
RecTyKind Kind;
+ /// ListRecTy of the list that has elements of this type.
ListRecTy *ListTy = nullptr;
public:
@@ -87,7 +88,7 @@
/// a bit set is not an int, but they are convertible.
virtual bool typeIsA(const RecTy *RHS) const;
- /// Returns the type representing list<this>.
+ /// Returns the type representing list<thistype>.
ListRecTy *getListTy();
};
@@ -136,24 +137,6 @@
bool typeIsA(const RecTy *RHS) const override;
};
-/// 'code' - Represent a code fragment
-class CodeRecTy : public RecTy {
- static CodeRecTy Shared;
-
- CodeRecTy() : RecTy(CodeRecTyKind) {}
-
-public:
- static bool classof(const RecTy *RT) {
- return RT->getRecTyKind() == CodeRecTyKind;
- }
-
- static CodeRecTy *get() { return &Shared; }
-
- std::string getAsString() const override { return "code"; }
-
- bool typeIsConvertibleTo(const RecTy *RHS) const override;
-};
-
/// 'int' - Represent an integer value of no particular size
class IntRecTy : public RecTy {
static IntRecTy Shared;
@@ -190,14 +173,14 @@
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
-/// 'list<Ty>' - Represent a list of values, all of which must be of
-/// the specified type.
+/// 'list<Ty>' - Represent a list of element values, all of which must be of
+/// the specified type. The type is stored in ElementTy.
class ListRecTy : public RecTy {
friend ListRecTy *RecTy::getListTy();
- RecTy *Ty;
+ RecTy *ElementTy;
- explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {}
+ explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), ElementTy(T) {}
public:
static bool classof(const RecTy *RT) {
@@ -205,7 +188,7 @@
}
static ListRecTy *get(RecTy *T) { return T->getListTy(); }
- RecTy *getElementType() const { return Ty; }
+ RecTy *getElementType() const { return ElementTy; }
std::string getAsString() const override;
@@ -304,7 +287,6 @@
IK_FirstTypedInit,
IK_BitInit,
IK_BitsInit,
- IK_CodeInit,
IK_DagInit,
IK_DefInit,
IK_FieldInit,
@@ -337,6 +319,7 @@
virtual void anchor();
public:
+ /// Get the kind (type) of the value.
InitKind getKind() const { return Kind; }
protected:
@@ -347,63 +330,61 @@
Init &operator=(const Init &) = delete;
virtual ~Init() = default;
- /// This virtual method should be overridden by values that may
- /// not be completely specified yet.
+ /// Is this a complete value with no unset (uninitialized) subvalues?
virtual bool isComplete() const { return true; }
/// Is this a concrete and fully resolved value without any references or
/// stuck operations? Unset values are concrete.
virtual bool isConcrete() const { return false; }
- /// Print out this value.
+ /// Print this value.
void print(raw_ostream &OS) const { OS << getAsString(); }
- /// Convert this value to a string form.
+ /// Convert this value to a literal form.
virtual std::string getAsString() const = 0;
- /// Convert this value to a string form,
- /// without adding quote markers. This primaruly affects
- /// StringInits where we will not surround the string value with
- /// quotes.
+
+ /// Convert this value to a literal form,
+ /// without adding quotes around a string.
virtual std::string getAsUnquotedString() const { return getAsString(); }
- /// Debugging method that may be called through a debugger, just
+ /// Debugging method that may be called through a debugger; just
/// invokes print on stderr.
void dump() const;
- /// If this initializer is convertible to Ty, return an initializer whose
- /// type is-a Ty, generating a !cast operation if required. Otherwise, return
- /// nullptr.
+ /// If this value is convertible to type \p Ty, return a value whose
+ /// type is \p Ty, generating a !cast operation if required.
+ /// Otherwise, return null.
virtual Init *getCastTo(RecTy *Ty) const = 0;
- /// Convert to an initializer whose type is-a Ty, or return nullptr if this
- /// is not possible (this can happen if the initializer's type is convertible
- /// to Ty, but there are unresolved references).
+ /// Convert to a value whose type is \p Ty, or return null if this
+ /// is not possible. This can happen if the value's type is convertible
+ /// to \p Ty, but there are unresolved references.
virtual Init *convertInitializerTo(RecTy *Ty) const = 0;
- /// This method is used to implement the bitrange
- /// selection operator. Given an initializer, it selects the specified bits
- /// out, returning them as a new init of bits type. If it is not legal to use
- /// the bit subscript operator on this initializer, return null.
+ /// This function is used to implement the bit range
+ /// selection operator. Given a value, it selects the specified bits,
+ /// returning them as a new \p Init of type \p bits. If it is not legal
+ /// to use the bit selection operator on this value, null is returned.
virtual Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const {
return nullptr;
}
- /// This method is used to implement the list slice
- /// selection operator. Given an initializer, it selects the specified list
- /// elements, returning them as a new init of list type. If it is not legal
- /// to take a slice of this, return null.
+ /// This function is used to implement the list slice
+ /// selection operator. Given a value, it selects the specified list
+ /// elements, returning them as a new \p Init of type \p list. If it
+ /// is not legal to use the slice operator, null is returned.
virtual Init *convertInitListSlice(ArrayRef<unsigned> Elements) const {
return nullptr;
}
- /// This method is used to implement the FieldInit class.
- /// Implementors of this method should return the type of the named field if
- /// they are of record type.
+ /// This function is used to implement the FieldInit class.
+ /// Implementors of this method should return the type of the named
+ /// field if they are of type record.
virtual RecTy *getFieldType(StringInit *FieldName) const {
return nullptr;
}
- /// This method is used by classes that refer to other
+ /// This function is used by classes that refer to other
/// variables which may not be defined at the time the expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
@@ -411,8 +392,7 @@
return const_cast<Init *>(this);
}
- /// This method is used to return the initializer for the specified
- /// bit.
+ /// Get the \p Init value of the specified bit.
virtual Init *getBit(unsigned Bit) const = 0;
};
@@ -420,14 +400,14 @@
I.print(OS); return OS;
}
-/// This is the common super-class of types that have a specific,
-/// explicit, type.
+/// This is the common superclass of types that have a specific,
+/// explicit type, stored in ValueTy.
class TypedInit : public Init {
- RecTy *Ty;
+ RecTy *ValueTy;
protected:
explicit TypedInit(InitKind K, RecTy *T, uint8_t Opc = 0)
- : Init(K, Opc), Ty(T) {}
+ : Init(K, Opc), ValueTy(T) {}
public:
TypedInit(const TypedInit &) = delete;
@@ -438,7 +418,8 @@
I->getKind() <= IK_LastTypedInit;
}
- RecTy *getType() const { return Ty; }
+ /// Get the type of the Init as a RecTy.
+ RecTy *getType() const { return ValueTy; }
Init *getCastTo(RecTy *Ty) const override;
Init *convertInitializerTo(RecTy *Ty) const override;
@@ -448,12 +429,11 @@
/// This method is used to implement the FieldInit class.
/// Implementors of this method should return the type of the named field if
- /// they are of record type.
- ///
+ /// they are of type record.
RecTy *getFieldType(StringInit *FieldName) const override;
};
-/// '?' - Represents an uninitialized value
+/// '?' - Represents an uninitialized value.
class UnsetInit : public Init {
UnsetInit() : Init(IK_UnsetInit) {}
@@ -465,6 +445,7 @@
return I->getKind() == IK_UnsetInit;
}
+ /// Get the singleton unset Init.
static UnsetInit *get();
Init *getCastTo(RecTy *Ty) const override;
@@ -474,8 +455,12 @@
return const_cast<UnsetInit*>(this);
}
+ /// Is this a complete value with no unset (uninitialized) subvalues?
bool isComplete() const override { return false; }
+
bool isConcrete() const override { return true; }
+
+ /// Get the string representation of the Init.
std::string getAsString() const override { return "?"; }
};
@@ -592,10 +577,18 @@
/// "foo" - Represent an initialization by a string value.
class StringInit : public TypedInit {
- StringRef Value;
+public:
+ enum StringFormat {
+ SF_String, // Format as "text"
+ SF_Code, // Format as [{text}]
+ };
- explicit StringInit(StringRef V)
- : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
+private:
+ StringRef Value;
+ StringFormat Format;
+
+ explicit StringInit(StringRef V, StringFormat Fmt)
+ : TypedInit(IK_StringInit, StringRecTy::get()), Value(V), Format(Fmt) {}
public:
StringInit(const StringInit &) = delete;
@@ -605,51 +598,30 @@
return I->getKind() == IK_StringInit;
}
- static StringInit *get(StringRef);
+ static StringInit *get(StringRef, StringFormat Fmt = SF_String);
+
+ static StringFormat determineFormat(StringFormat Fmt1, StringFormat Fmt2) {
+ return (Fmt1 == SF_Code || Fmt2 == SF_Code) ? SF_Code : SF_String;
+ }
StringRef getValue() const { return Value; }
+ StringFormat getFormat() const { return Format; }
+ bool hasCodeFormat() const { return Format == SF_Code; }
Init *convertInitializerTo(RecTy *Ty) const override;
bool isConcrete() const override { return true; }
- std::string getAsString() const override { return "\"" + Value.str() + "\""; }
- std::string getAsUnquotedString() const override { return Value; }
-
- Init *getBit(unsigned Bit) const override {
- llvm_unreachable("Illegal bit reference off string");
- }
-};
-
-class CodeInit : public TypedInit {
- StringRef Value;
- SMLoc Loc;
-
- explicit CodeInit(StringRef V, const SMLoc &Loc)
- : TypedInit(IK_CodeInit, static_cast<RecTy *>(CodeRecTy::get())),
- Value(V), Loc(Loc) {}
-
-public:
- CodeInit(const StringInit &) = delete;
- CodeInit &operator=(const StringInit &) = delete;
-
- static bool classof(const Init *I) {
- return I->getKind() == IK_CodeInit;
- }
-
- static CodeInit *get(StringRef, const SMLoc &Loc);
-
- StringRef getValue() const { return Value; }
- const SMLoc &getLoc() const { return Loc; }
-
- Init *convertInitializerTo(RecTy *Ty) const override;
-
- bool isConcrete() const override { return true; }
std::string getAsString() const override {
- return "[{" + Value.str() + "}]";
+ if (Format == SF_String)
+ return "\"" + Value.str() + "\"";
+ else
+ return "[{" + Value.str() + "}]";
}
- std::string getAsUnquotedString() const override { return Value; }
+ std::string getAsUnquotedString() const override {
+ return std::string(Value);
+ }
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off string");
@@ -751,7 +723,7 @@
///
class UnOpInit : public OpInit, public FoldingSetNode {
public:
- enum UnaryOp : uint8_t { CAST, HEAD, TAIL, SIZE, EMPTY };
+ enum UnaryOp : uint8_t { CAST, NOT, HEAD, TAIL, SIZE, EMPTY, GETDAGOP };
private:
Init *LHS;
@@ -800,9 +772,9 @@
/// !op (X, Y) - Combine two inits.
class BinOpInit : public OpInit, public FoldingSetNode {
public:
- enum BinaryOp : uint8_t { ADD, MUL, AND, OR, SHL, SRA, SRL, LISTCONCAT,
- LISTSPLAT, STRCONCAT, CONCAT, EQ, NE, LE, LT, GE,
- GT };
+ enum BinaryOp : uint8_t { ADD, SUB, MUL, AND, OR, XOR, SHL, SRA, SRL, LISTCONCAT,
+ LISTSPLAT, STRCONCAT, INTERLEAVE, CONCAT, EQ,
+ NE, LE, LT, GE, GT, SETDAGOP };
private:
Init *LHS, *RHS;
@@ -822,7 +794,6 @@
RecTy *Type);
static Init *getStrConcat(Init *lhs, Init *rhs);
static Init *getListConcat(TypedInit *lhs, Init *rhs);
- static Init *getListSplat(TypedInit *lhs, Init *rhs);
void Profile(FoldingSetNodeID &ID) const;
@@ -858,7 +829,7 @@
/// !op (X, Y, Z) - Combine two inits.
class TernOpInit : public OpInit, public FoldingSetNode {
public:
- enum TernaryOp : uint8_t { SUBST, FOREACH, IF, DAG };
+ enum TernaryOp : uint8_t { SUBST, FOREACH, FILTER, IF, DAG, SUBSTR };
private:
Init *LHS, *MHS, *RHS;
@@ -1098,7 +1069,7 @@
Init *getBit(unsigned Bit) const override;
- std::string getAsString() const override { return getName(); }
+ std::string getAsString() const override { return std::string(getName()); }
};
/// Opcode{0} - Represent access to one bit of a variable or field.
@@ -1263,7 +1234,14 @@
FieldInit(Init *R, StringInit *FN)
: TypedInit(IK_FieldInit, R->getFieldType(FN)), Rec(R), FieldName(FN) {
- assert(getType() && "FieldInit with non-record type!");
+#ifndef NDEBUG
+ if (!getType()) {
+ llvm::errs() << "In Record = " << Rec->getAsString()
+ << ", got FieldName = " << *FieldName
+ << " with non-record type!\n";
+ llvm_unreachable("FieldInit with non-record type!");
+ }
+#endif
}
public:
@@ -1284,6 +1262,7 @@
Init *resolveReferences(Resolver &R) const override;
Init *Fold(Record *CurRec) const;
+ bool isConcrete() const override;
std::string getAsString() const override {
return Rec->getAsString() + "." + FieldName->getValue().str();
}
@@ -1323,6 +1302,7 @@
void Profile(FoldingSetNodeID &ID) const;
Init *getOperator() const { return Val; }
+ Record *getOperatorAsDef(ArrayRef<SMLoc> Loc) const;
StringInit *getName() const { return ValName; }
@@ -1384,30 +1364,70 @@
// High-Level Classes
//===----------------------------------------------------------------------===//
+/// This class represents a field in a record, including its name, type,
+/// value, and source location.
class RecordVal {
friend class Record;
+public:
+ enum FieldKind {
+ FK_Normal, // A normal record field.
+ FK_NonconcreteOK, // A field that can be nonconcrete ('field' keyword).
+ FK_TemplateArg, // A template argument.
+ };
+
+private:
Init *Name;
- PointerIntPair<RecTy *, 1, bool> TyAndPrefix;
+ SMLoc Loc; // Source location of definition of name.
+ PointerIntPair<RecTy *, 2, FieldKind> TyAndKind;
Init *Value;
public:
- RecordVal(Init *N, RecTy *T, bool P);
+ RecordVal(Init *N, RecTy *T, FieldKind K);
+ RecordVal(Init *N, SMLoc Loc, RecTy *T, FieldKind K);
+ /// Get the name of the field as a StringRef.
StringRef getName() const;
+
+ /// Get the name of the field as an Init.
Init *getNameInit() const { return Name; }
+ /// Get the name of the field as a std::string.
std::string getNameInitAsString() const {
return getNameInit()->getAsUnquotedString();
}
- bool getPrefix() const { return TyAndPrefix.getInt(); }
- RecTy *getType() const { return TyAndPrefix.getPointer(); }
+ /// Get the source location of the point where the field was defined.
+ const SMLoc &getLoc() const { return Loc; }
+
+ /// Is this a field where nonconcrete values are okay?
+ bool isNonconcreteOK() const {
+ return TyAndKind.getInt() == FK_NonconcreteOK;
+ }
+
+ /// Is this a template argument?
+ bool isTemplateArg() const {
+ return TyAndKind.getInt() == FK_TemplateArg;
+ }
+
+ /// Get the type of the field value as a RecTy.
+ RecTy *getType() const { return TyAndKind.getPointer(); }
+
+ /// Get the type of the field for printing purposes.
+ std::string getPrintType() const;
+
+ /// Get the value of the field as an Init.
Init *getValue() const { return Value; }
+ /// Set the value of the field from an Init.
bool setValue(Init *V);
+ /// Set the value and source location of the field.
+ bool setValue(Init *V, SMLoc NewLoc);
+
void dump() const;
+
+ /// Print the value to an output stream, possibly with a semicolon.
void print(raw_ostream &OS, bool PrintSem = true) const;
};
@@ -1425,15 +1445,18 @@
SmallVector<SMLoc, 4> Locs;
SmallVector<Init *, 0> TemplateArgs;
SmallVector<RecordVal, 0> Values;
+ // Vector of [source location, condition Init, message Init].
+ SmallVector<std::tuple<SMLoc, Init *, Init *>, 0> Assertions;
- // All superclasses in the inheritance forest in reverse preorder (yes, it
+ // All superclasses in the inheritance forest in post-order (yes, it
// must be a forest; diamond-shaped inheritance is not allowed).
SmallVector<std::pair<Record *, SMRange>, 0> SuperClasses;
// Tracks Record instances. Not owned by Record.
RecordKeeper &TrackedRecords;
- DefInit *TheInit = nullptr;
+ // The DefInit corresponding to this record.
+ DefInit *CorrespondingDefInit = nullptr;
// Unique record ID.
unsigned ID;
@@ -1457,8 +1480,8 @@
: Record(StringInit::get(N), locs, records, false, Class) {}
// When copy-constructing a Record, we must still guarantee a globally unique
- // ID number. Don't copy TheInit either since it's owned by the original
- // record. All other fields can be copied normally.
+ // ID number. Don't copy CorrespondingDefInit either, since it's owned by the
+ // original record. All other fields can be copied normally.
Record(const Record &O)
: Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
Values(O.Values), SuperClasses(O.SuperClasses),
@@ -1498,11 +1521,18 @@
ArrayRef<RecordVal> getValues() const { return Values; }
+ ArrayRef<std::tuple<SMLoc, Init *, Init *>> getAssertions() const {
+ return Assertions;
+ }
+
ArrayRef<std::pair<Record *, SMRange>> getSuperClasses() const {
return SuperClasses;
}
- /// Append the direct super classes of this record to Classes.
+ /// Determine whether this record has the specified direct superclass.
+ bool hasDirectSuperClass(const Record *SuperClass) const;
+
+ /// Append the direct superclasses of this record to Classes.
void getDirectSuperClasses(SmallVectorImpl<Record *> &Classes) const;
bool isTemplateArg(Init *Name) const {
@@ -1552,6 +1582,10 @@
removeValue(StringInit::get(Name));
}
+ void addAssertion(SMLoc Loc, Init *Condition, Init *Message) {
+ Assertions.push_back(std::make_tuple(Loc, Condition, Message));
+ }
+
bool isSubClassOf(const Record *R) const {
for (const auto &SCPair : SuperClasses)
if (SCPair.first == R)
@@ -1572,7 +1606,8 @@
}
void addSuperClass(Record *R, SMRange Range) {
- assert(!TheInit && "changing type of record after it has been referenced");
+ assert(!CorrespondingDefInit &&
+ "changing type of record after it has been referenced");
assert(!isSubClassOf(R) && "Already subclassing record!");
SuperClasses.push_back(std::make_pair(R, Range));
}
@@ -1591,11 +1626,6 @@
/// recursion / infinite loops.
void resolveReferences(Resolver &R, const RecordVal *SkipVal = nullptr);
- /// If anything in this record refers to RV, replace the
- /// reference to RV with the RHS of RV. If RV is null, we resolve all
- /// possible references.
- void resolveReferencesTo(const RecordVal *RV);
-
RecordKeeper &getRecords() const {
return TrackedRecords;
}
@@ -1604,13 +1634,15 @@
return IsAnonymous;
}
- void print(raw_ostream &OS) const;
void dump() const;
//===--------------------------------------------------------------------===//
// High-level methods useful to tablegen back-ends
//
+ ///Return the source location for the named field.
+ SMLoc getFieldLoc(StringRef FieldName) const;
+
/// Return the initializer for a value with the specified name,
/// or throw an exception if the field does not exist.
Init *getValueInit(StringRef FieldName) const;
@@ -1626,6 +1658,11 @@
StringRef getValueAsString(StringRef FieldName) const;
/// This method looks up the specified field and returns
+ /// its value as a string, throwing an exception if the field if the value is
+ /// not a string and llvm::Optional() if the field does not exist.
+ llvm::Optional<StringRef> getValueAsOptionalString(StringRef FieldName) const;
+
+ /// This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
BitsInit *getValueAsBitsInit(StringRef FieldName) const;
@@ -1655,6 +1692,12 @@
/// the value is not the right type.
Record *getValueAsDef(StringRef FieldName) const;
+ /// This method looks up the specified field and returns its value as a
+ /// Record, returning null if the field exists but is "uninitialized"
+ /// (i.e. set to `?`), and throwing an exception if the field does not
+ /// exist or if its value is not the right type.
+ Record *getValueAsOptionalDef(StringRef FieldName) const;
+
/// This method looks up the specified field and returns its
/// value as a bit, throwing an exception if the field does not exist or if
/// the value is not the right type.
@@ -1680,26 +1723,50 @@
class RecordKeeper {
friend class RecordRecTy;
- using RecordMap = std::map<std::string, std::unique_ptr<Record>>;
+
+ using RecordMap = std::map<std::string, std::unique_ptr<Record>, std::less<>>;
+ using GlobalMap = std::map<std::string, Init *, std::less<>>;
+
+ std::string InputFilename;
RecordMap Classes, Defs;
+ mutable StringMap<std::vector<Record *>> ClassRecordsMap;
FoldingSet<RecordRecTy> RecordTypePool;
- std::map<std::string, Init *> ExtraGlobals;
+ std::map<std::string, Init *, std::less<>> ExtraGlobals;
unsigned AnonCounter = 0;
+ // These members are for the phase timing feature. We need a timer group,
+ // the last timer started, and a flag to say whether the last timer
+ // is the special "backend overall timer."
+ TimerGroup *TimingGroup = nullptr;
+ Timer *LastTimer = nullptr;
+ bool BackendTimer = false;
+
public:
+ /// Get the main TableGen input file's name.
+ const std::string getInputFilename() const { return InputFilename; }
+
+ /// Get the map of classes.
const RecordMap &getClasses() const { return Classes; }
+
+ /// Get the map of records (defs).
const RecordMap &getDefs() const { return Defs; }
+ /// Get the map of global variables.
+ const GlobalMap &getGlobals() const { return ExtraGlobals; }
+
+ /// Get the class with the specified name.
Record *getClass(StringRef Name) const {
auto I = Classes.find(Name);
return I == Classes.end() ? nullptr : I->second.get();
}
+ /// Get the concrete record with the specified name.
Record *getDef(StringRef Name) const {
auto I = Defs.find(Name);
return I == Defs.end() ? nullptr : I->second.get();
}
+ /// Get the \p Init value of the specified global variable.
Init *getGlobal(StringRef Name) const {
if (Record *R = getDef(Name))
return R->getDefInit();
@@ -1707,22 +1774,26 @@
return It == ExtraGlobals.end() ? nullptr : It->second;
}
+ void saveInputFilename(std::string Filename) {
+ InputFilename = Filename;
+ }
+
void addClass(std::unique_ptr<Record> R) {
- bool Ins = Classes.insert(std::make_pair(R->getName(),
+ bool Ins = Classes.insert(std::make_pair(std::string(R->getName()),
std::move(R))).second;
(void)Ins;
assert(Ins && "Class already exists");
}
void addDef(std::unique_ptr<Record> R) {
- bool Ins = Defs.insert(std::make_pair(R->getName(),
+ bool Ins = Defs.insert(std::make_pair(std::string(R->getName()),
std::move(R))).second;
(void)Ins;
assert(Ins && "Record already exists");
}
void addExtraGlobal(StringRef Name, Init *I) {
- bool Ins = ExtraGlobals.insert(std::make_pair(Name, I)).second;
+ bool Ins = ExtraGlobals.insert(std::make_pair(std::string(Name), I)).second;
(void)Ins;
assert(!getDef(Name));
assert(Ins && "Global already exists");
@@ -1730,14 +1801,42 @@
Init *getNewAnonymousName();
- //===--------------------------------------------------------------------===//
- // High-level helper methods, useful for tablegen backends...
+ /// Start phase timing; called if the --time-phases option is specified.
+ void startPhaseTiming() {
+ TimingGroup = new TimerGroup("TableGen", "TableGen Phase Timing");
+ }
- /// This method returns all concrete definitions
- /// that derive from the specified class name. A class with the specified
- /// name must exist.
+ /// Start timing a phase. Automatically stops any previous phase timer.
+ void startTimer(StringRef Name);
+
+ /// Stop timing a phase.
+ void stopTimer();
+
+ /// Start timing the overall backend. If the backend itself starts a timer,
+ /// then this timer is cleared.
+ void startBackendTimer(StringRef Name);
+
+ /// Stop timing the overall backend.
+ void stopBackendTimer();
+
+ /// Stop phase timing and print the report.
+ void stopPhaseTiming() {
+ if (TimingGroup)
+ delete TimingGroup;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // High-level helper methods, useful for tablegen backends.
+
+ /// Get all the concrete records that inherit from the one specified
+ /// class. The class must be defined.
std::vector<Record *> getAllDerivedDefinitions(StringRef ClassName) const;
+ /// Get all the concrete records that inherit from all the specified
+ /// classes. The classes must be defined.
+ std::vector<Record *> getAllDerivedDefinitions(
+ ArrayRef<StringRef> ClassNames) const;
+
void dump() const;
};
@@ -1913,25 +2012,6 @@
bool keepUnsetBits() const override { return true; }
};
-/// Resolve all references to a specific RecordVal.
-//
-// TODO: This is used for resolving references to template arguments, in a
-// rather inefficient way. Change those uses to resolve all template
-// arguments simultaneously and get rid of this class.
-class RecordValResolver final : public Resolver {
- const RecordVal *RV;
-
-public:
- explicit RecordValResolver(Record &R, const RecordVal *RV)
- : Resolver(&R), RV(RV) {}
-
- Init *resolve(Init *VarName) override {
- if (VarName == RV->getNameInit())
- return RV->getValue();
- return nullptr;
- }
-};
-
/// Delegate resolving to a sub-resolver, but shadow some variable names.
class ShadowResolver final : public Resolver {
Resolver &R;
@@ -1982,6 +2062,7 @@
Init *resolve(Init *VarName) override;
};
+void EmitDetailedRecords(RecordKeeper &RK, raw_ostream &OS);
void EmitJSON(RecordKeeper &RK, raw_ostream &OS);
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/TableGen/SearchableTable.td b/linux-x64/clang/include/llvm/TableGen/SearchableTable.td
index 2680c71..61dfa5c 100644
--- a/linux-x64/clang/include/llvm/TableGen/SearchableTable.td
+++ b/linux-x64/clang/include/llvm/TableGen/SearchableTable.td
@@ -67,9 +67,13 @@
// List of the names of fields of collected records that contain the data for
// table entries, in the order that is used for initialization in C++.
//
- // For each field of the table named XXX, TableGen will look for a value
- // called TypeOf_XXX and use that as a more detailed description of the
- // type of the field if present. This is required for fields whose type
+ // TableGen needs to know the type of the fields so that it can format
+ // the initializers correctly. It can infer the type of bit, bits, string,
+ // Intrinsic, and Instruction values.
+ //
+ // For each field of the table named xxx, TableGen will look for a field
+ // named TypeOf_xxx and use that as a more detailed description of the
+ // type of the field. This is required for fields whose type
// cannot be deduced automatically, such as enum fields. For example:
//
// def MyEnum : GenericEnum {
@@ -85,15 +89,15 @@
// def MyTable : GenericTable {
// let FilterClass = "MyTableEntry";
// let Fields = ["V", ...];
- // GenericEnum TypeOf_V = MyEnum;
+ // string TypeOf_V = "MyEnum";
// }
//
- // Fields of type bit, bits<N>, string, Intrinsic, and Instruction (or
- // derived classes of those) are supported natively.
+ // If a string field was initialized with a code literal, TableGen will
+ // emit the code verbatim. However, if a string field was initialized
+ // in some other way, but should be interpreted as code, then a TypeOf_xxx
+ // field is necessary, with a value of "code":
//
- // Additionally, fields of type `code` can appear, where the value is used
- // verbatim as an initializer. However, these fields cannot be used as
- // search keys.
+ // string TypeOf_Predicate = "code";
list<string> Fields;
// (Optional) List of fields that make up the primary key.
@@ -103,7 +107,7 @@
string PrimaryKeyName;
// See SearchIndex.EarlyOut
- bit PrimaryKeyEarlyOut = 0;
+ bit PrimaryKeyEarlyOut = false;
}
// Define a record derived from this class to generate an additional search
@@ -124,7 +128,7 @@
// instructions.
//
// Can only be used when the first field is an integral (non-string) type.
- bit EarlyOut = 0;
+ bit EarlyOut = false;
}
// Legacy table type with integrated enum.
diff --git a/linux-x64/clang/include/llvm/TableGen/StringToOffsetTable.h b/linux-x64/clang/include/llvm/TableGen/StringToOffsetTable.h
index 76ce518..7fcf20a 100644
--- a/linux-x64/clang/include/llvm/TableGen/StringToOffsetTable.h
+++ b/linux-x64/clang/include/llvm/TableGen/StringToOffsetTable.h
@@ -45,7 +45,7 @@
// Escape the string.
SmallString<256> Str;
raw_svector_ostream(Str).write_escaped(AggregateString);
- AggregateString = Str.str();
+ AggregateString = std::string(Str.str());
O << " \"";
unsigned CharsPrinted = 0;