HsiangKai updated this revision to Diff 387488.
HsiangKai added a comment.

Check required extensions when adding the declarations.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D111617/new/

https://reviews.llvm.org/D111617

Files:
  clang/include/clang/Basic/CMakeLists.txt
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/utils/TableGen/RISCVVEmitter.cpp
  clang/utils/TableGen/TableGen.cpp
  clang/utils/TableGen/TableGenBackends.h
  llvm/docs/CommandGuide/tblgen.rst

Index: llvm/docs/CommandGuide/tblgen.rst
===================================================================
--- llvm/docs/CommandGuide/tblgen.rst
+++ llvm/docs/CommandGuide/tblgen.rst
@@ -348,6 +348,10 @@
 
   Generate ``riscv_vector_builtin_cg.inc`` for Clang.
 
+.. option:: -gen-riscv-vector-builtin-sema
+
+  Generate ``riscv_vector_builtin_sema.inc`` for Clang.
+
 .. option:: -gen-attr-docs
 
   Generate attribute documentation.
Index: clang/utils/TableGen/TableGenBackends.h
===================================================================
--- clang/utils/TableGen/TableGenBackends.h
+++ clang/utils/TableGen/TableGenBackends.h
@@ -110,6 +110,7 @@
 void EmitRVVHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitRVVBuiltins(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitRVVBuiltinCG(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitRVVBuiltinSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 
 void EmitCdeHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitCdeBuiltinDef(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
Index: clang/utils/TableGen/TableGen.cpp
===================================================================
--- clang/utils/TableGen/TableGen.cpp
+++ clang/utils/TableGen/TableGen.cpp
@@ -88,6 +88,7 @@
   GenRISCVVectorHeader,
   GenRISCVVectorBuiltins,
   GenRISCVVectorBuiltinCG,
+  GenRISCVVectorBuiltinSema,
   GenAttrDocs,
   GenDiagDocs,
   GenOptDocs,
@@ -243,6 +244,8 @@
                    "Generate riscv_vector_builtins.inc for clang"),
         clEnumValN(GenRISCVVectorBuiltinCG, "gen-riscv-vector-builtin-codegen",
                    "Generate riscv_vector_builtin_cg.inc for clang"),
+        clEnumValN(GenRISCVVectorBuiltinSema, "gen-riscv-vector-builtin-sema",
+                   "Generate riscv_vector_builtin_sema.inc for clang"),
         clEnumValN(GenAttrDocs, "gen-attr-docs",
                    "Generate attribute documentation"),
         clEnumValN(GenDiagDocs, "gen-diag-docs",
@@ -458,6 +461,9 @@
   case GenRISCVVectorBuiltinCG:
     EmitRVVBuiltinCG(Records, OS);
     break;
+  case GenRISCVVectorBuiltinSema:
+    EmitRVVBuiltinSema(Records, OS);
+    break;
   case GenAttrDocs:
     EmitClangAttrDocs(Records, OS);
     break;
Index: clang/utils/TableGen/RISCVVEmitter.cpp
===================================================================
--- clang/utils/TableGen/RISCVVEmitter.cpp
+++ clang/utils/TableGen/RISCVVEmitter.cpp
@@ -15,6 +15,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
@@ -22,6 +23,8 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/TableGenBackend.h"
 #include <numeric>
 
 using namespace llvm;
@@ -55,7 +58,6 @@
     Float,
     Invalid,
   };
-  BasicType BT;
   ScalarTypeKind ScalarType = Invalid;
   LMULType LMUL;
   bool IsPointer = false;
@@ -71,11 +73,26 @@
   std::string ClangBuiltinStr;
   std::string Str;
   std::string ShortStr;
+  std::string QualExpr;
 
 public:
   RVVType() : RVVType(BasicType(), 0, StringRef()) {}
   RVVType(BasicType BT, int Log2LMUL, StringRef prototype);
 
+  const std::string getMangledStr() const {
+    if (!Valid)
+      return "";
+
+    Twine ScalarTypeStr =
+        Twine(Twine(ScalarType) + Twine(IsPointer) + Twine(IsImmediate) +
+              Twine(IsConstant) + Twine(ElementBitwidth));
+    if (isScalar()) {
+      return ScalarTypeStr.str();
+    } else {
+      return Twine(ScalarTypeStr + Twine(Scale.getValue()) + LMUL.str()).str();
+    }
+  }
+
   // Return the string representation of a type, which is an encoded string for
   // passing to the BUILTIN() macro in Builtins.def.
   const std::string &getBuiltinStr() const { return BuiltinStr; }
@@ -97,6 +114,8 @@
     return ShortStr;
   }
 
+  const std::string &getQualExpr() { return QualExpr; }
+
   bool isValid() const { return Valid; }
   bool isScalar() const { return Scale.hasValue() && Scale.getValue() == 0; }
   bool isVector() const { return Scale.hasValue() && Scale.getValue() != 0; }
@@ -110,13 +129,15 @@
   bool isFloat(unsigned Width) const {
     return isFloat() && ElementBitwidth == Width;
   }
+  bool isPointer() const { return IsPointer; }
+  bool isConstant() const { return IsConstant; }
 
 private:
   // Verify RVV vector type and set Valid.
   bool verifyType() const;
 
   // Creates a type based on basic types of TypeRange
-  void applyBasicType();
+  void applyBasicType(BasicType BT);
 
   // Applies a prototype modifier to the current type. The result maybe an
   // invalid type.
@@ -130,6 +151,8 @@
   void initTypeStr();
   // Compute and record a short name of a type for C/C++ name suffix.
   void initShortStr();
+  // Compute and record the expression to create QualType.
+  void initQualExpr();
 };
 
 using RVVTypePtr = RVVType *;
@@ -159,13 +182,12 @@
   bool HasNoMaskedOverloaded;
   bool HasAutoDef; // There is automiatic definition in header
   std::string ManualCodegen;
-  RVVTypePtr OutputType; // Builtin output type
-  RVVTypes InputTypes;   // Builtin input types
   // The types we use to obtain the specific LLVM intrinsic. They are index of
-  // InputTypes. -1 means the return type.
+  // input types. -1 means the return type.
   std::vector<int64_t> IntrinsicTypes;
   uint8_t RISCVExtensions = 0;
   unsigned NF = 1;
+  const RVVTypes Types;
 
 public:
   RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName,
@@ -193,6 +215,7 @@
   const std::vector<int64_t> &getIntrinsicTypes() const {
     return IntrinsicTypes;
   }
+  const RVVTypes &getRVVTypes() const { return Types; }
 
   // Return the type string for a BUILTIN() macro in Builtins.def.
   std::string getBuiltinTypeStr() const;
@@ -201,23 +224,79 @@
   // init the RVVIntrinsic ID and IntrinsicTypes.
   void emitCodeGenSwitchBody(raw_ostream &o) const;
 
-  // Emit the macros for mapping C/C++ intrinsic function to builtin functions.
-  void emitIntrinsicFuncDef(raw_ostream &o) const;
-
   // Emit the mangled function definition.
   void emitMangledFuncDef(raw_ostream &o) const;
 };
 
+// A list of signatures that are shared by one or more builtin functions.
+struct BuiltinTableEntries {
+  SmallVector<StringRef, 4> Names;
+  SmallVector<unsigned, 4> BuiltinIndex;
+  std::vector<std::pair<RVVIntrinsic *, unsigned>> Signatures;
+};
+
 class RVVEmitter {
 private:
+  // A list of indices into the builtin function table.
+  using BuiltinIndexListTy = SmallVector<unsigned, 11>;
+
   RecordKeeper &Records;
+  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
   std::string HeaderCode;
   // Concat BasicType, LMUL and Proto as key
   StringMap<RVVType> LegalTypes;
   StringSet<> IllegalTypes;
 
+  MapVector<RVVType *, unsigned> TypeMap;
+  std::vector<RVVType *> TypeList;
+  std::vector<std::string> BuiltinList;
+  // Map (generic name, RVVSignatureTable index) to RVVBuiltinName index
+  MapVector<std::pair<StringRef, unsigned>, unsigned> GenericBuiltinMap;
+
+  // Contains a list of the available signatures, without the name of the
+  // function. Each pair consists of a signature and a cumulative index.
+  // E.g.:  <<vint8m1_t, vint8m1_t, vint8m1_t, size_t>, 0>,
+  //        <<vint8m1_t, vbool8_t, vint8m1_t, vint8m1_t, vint8m1_t, size_t>, 4>,
+  //        <<vint8m2_t, vint8m2_t, vint8m2_t, size_t>, 10>,
+  std::vector<std::pair<const RVVTypes, unsigned>> SignaturesList;
+
+  // Map the name of a builtin function to its prototypes (instances of the
+  // "RVVIntrinsic" class).
+  // Each prototype is registered as a pair of:
+  //   <pointer to the "RVVIntrinsic" instance,
+  //    cumulative index of the associated signature in the SignaturesList>
+  // E.g.:  The function vadd:
+  // vint8m1_t vadd(vint8m1_t, vint8m1_t, size_t);
+  // vint8m1_t vadd(vbool8_t, vint8m1_t, vint8m1_t, vint8m1_t, size_t);
+  // vint8m2_t vadd(vint8m2_t, vint8m2_t, size_t);
+  // ...
+  //        <"vadd", <<ptr to RVVIntrinsic for vadd_vv_i8m1, 0>,
+  //                  <ptr to RVVIntrinsic for vadd_vv_i8m1_m, 4>,
+  //                  <ptr to RVVIntrinsic for vadd_vv_i8m2, 10>,
+  //                  ...>>
+  MapVector<StringRef, std::vector<std::pair<RVVIntrinsic *, unsigned>>>
+      FctOverloadMap;
+
+  // Map an ordered vector of signatures to their original RVVIntrinsic
+  // instances, and to a list of function names that share these signatures.
+  //
+  // For example, suppose the "vadd" and "vsub" functions have only three
+  // signatures, and these signatures are at index Ix in the SignatureTable:
+  //            vadd      |           vsub    |  Signature    | Index
+  //  vint8m1_t vadd()    | vint8m1_t vsub()  |  Signature1   | I1
+  //  vint8m2_t vadd()    | vint8m2_t vsub()  |  Signature2   | I2
+  //  vint8m4_t vadd()    | vint8m4_t vsub()  |  Signature3   | I3
+  //
+  // Then we will create a mapping of the vector of signatures:
+  // SignatureListMap[<I1, I2, I3>] = <
+  //                  <"vadd", "vsub">,
+  //                  <Signature1, Signature2, Signature3>>
+  // The function "vand", having the same signatures, would be mapped to the
+  // same entry (<I1, I2, I3>).
+  MapVector<BuiltinIndexListTy *, BuiltinTableEntries> SignatureListMap;
+
 public:
-  RVVEmitter(RecordKeeper &R) : Records(R) {}
+  RVVEmitter(RecordKeeper &R) : Records(R) { createRVVIntrinsics(Defs); }
 
   /// Emit riscv_vector.h
   void createHeader(raw_ostream &o);
@@ -228,6 +307,9 @@
   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
   void createCodeGen(raw_ostream &o);
 
+  /// Emit all the information needed by SemaLookup.cpp.
+  void createSema(raw_ostream &o);
+
   std::string getSuffixStr(char Type, int Log2LMUL, StringRef Prototypes);
 
 private:
@@ -256,6 +338,19 @@
   // prototype string individually in the Handler.
   void parsePrototypes(StringRef Prototypes,
                        std::function<void(StringRef)> Handler);
+
+  void EmitDeclarations(raw_ostream &o);
+  void GetOverloads(raw_ostream &o);
+  bool CanReuseSignature(
+      BuiltinIndexListTy *Candidate,
+      std::vector<std::pair<RVVIntrinsic *, unsigned>> &SignatureList);
+  void GroupBySignature(raw_ostream &OS);
+
+  void EmitSignatureTable(raw_ostream &o);
+  void EmitBuiltinTable(raw_ostream &o);
+  void EmitBuiltinMapTable(raw_ostream &o);
+  void EmitStringMatcher(raw_ostream &o);
+  void EmitQualTypeFinder(raw_ostream &o);
 };
 
 } // namespace
@@ -309,13 +404,14 @@
 }
 
 RVVType::RVVType(BasicType BT, int Log2LMUL, StringRef prototype)
-    : BT(BT), LMUL(LMULType(Log2LMUL)) {
-  applyBasicType();
+    : LMUL(LMULType(Log2LMUL)) {
+  applyBasicType(BT);
   applyModifier(prototype);
   Valid = verifyType();
   if (Valid) {
     initBuiltinStr();
     initTypeStr();
+    initQualExpr();
     if (isVector()) {
       initClangBuiltinStr();
     }
@@ -555,6 +651,21 @@
   case ScalarTypeKind::UnsignedInteger:
     ShortStr = "u" + utostr(ElementBitwidth);
     break;
+  case ScalarTypeKind::Void:
+    ShortStr = "void";
+    break;
+  case ScalarTypeKind::Size_t:
+    ShortStr = "size_t";
+    break;
+  case ScalarTypeKind::Ptrdiff_t:
+    ShortStr = "ptrdiff_t";
+    break;
+  case ScalarTypeKind::UnsignedLong:
+    ShortStr = "ulong";
+    break;
+  case ScalarTypeKind::SignedLong:
+    ShortStr = "long";
+    break;
   default:
     PrintFatalError("Unhandled case!");
   }
@@ -562,7 +673,85 @@
     ShortStr += LMUL.str();
 }
 
-void RVVType::applyBasicType() {
+void RVVType::initQualExpr() {
+  switch (ScalarType) {
+  case ScalarTypeKind::Invalid:
+    llvm_unreachable("Type is not valid.");
+  case ScalarTypeKind::Void:
+    QualExpr = "Context.VoidTy";
+    break;
+  case ScalarTypeKind::Size_t:
+    QualExpr = "Context.getSizeType()";
+    break;
+  case ScalarTypeKind::Ptrdiff_t:
+    QualExpr = "Context.getPointerDiffType()";
+    break;
+  case ScalarTypeKind::UnsignedLong:
+    QualExpr = "Context.UnsignedLongTy";
+    break;
+  case ScalarTypeKind::SignedLong:
+    QualExpr = "Context.LongTy";
+    break;
+  case ScalarTypeKind::Boolean:
+    QualExpr = "Context.BoolTy";
+    break;
+  case ScalarTypeKind::SignedInteger:
+    switch (ElementBitwidth) {
+    case 8:
+      QualExpr = "Context.SignedCharTy";
+      break;
+    case 16:
+      QualExpr = "Context.ShortTy";
+      break;
+    case 32:
+      QualExpr = "Context.IntTy";
+      break;
+    case 64:
+      QualExpr = "Context.LongLongTy";
+      break;
+    }
+    break;
+  case ScalarTypeKind::UnsignedInteger:
+    switch (ElementBitwidth) {
+    case 8:
+      QualExpr = "Context.UnsignedCharTy";
+      break;
+    case 16:
+      QualExpr = "Context.UnsignedShortTy";
+      break;
+    case 32:
+      QualExpr = "Context.UnsignedIntTy";
+      break;
+    case 64:
+      QualExpr = "Context.UnsignedLongLongTy";
+      break;
+    }
+    break;
+  case ScalarTypeKind::Float:
+    switch (ElementBitwidth) {
+    case 16:
+      QualExpr = "Context.Float16Ty";
+      break;
+    case 32:
+      QualExpr = "Context.FloatTy";
+      break;
+    case 64:
+      QualExpr = "Context.DoubleTy";
+      break;
+    }
+    break;
+  }
+
+  if (isScalar())
+    return;
+
+  assert(isVector() && "Unexpected type.");
+  QualExpr = Twine("Context.getScalableVectorType(" + QualExpr + ", " +
+                   Twine(Scale.getValue()) + ")")
+                 .str();
+}
+
+void RVVType::applyBasicType(BasicType BT) {
   switch (BT) {
   case 'c':
     ElementBitwidth = 8;
@@ -733,6 +922,7 @@
       break;
     case 'K':
       IsImmediate = true;
+      IsConstant = true;
       break;
     case 'U':
       ScalarType = ScalarTypeKind::UnsignedInteger;
@@ -767,7 +957,7 @@
                            StringRef RequiredExtension, unsigned NF)
     : IRName(IRName), IsMask(IsMask), HasVL(HasVL), HasPolicy(HasPolicy),
       HasNoMaskedOverloaded(HasNoMaskedOverloaded), HasAutoDef(HasAutoDef),
-      ManualCodegen(ManualCodegen.str()), NF(NF) {
+      ManualCodegen(ManualCodegen.str()), NF(NF), Types(OutInTypes) {
 
   // Init BuiltinName, Name and MangledName
   BuiltinName = NewName.str();
@@ -797,10 +987,6 @@
   if (RequiredExtension == "Zvlsseg")
     RISCVExtensions |= RISCVExtension::Zvlsseg;
 
-  // Init OutputType and InputTypes
-  OutputType = OutInTypes[0];
-  InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
-
   // IntrinsicTypes is nonmasked version index. Need to update it
   // if there is maskedoff operand (It is always in first operand).
   IntrinsicTypes = NewIntrinsicTypes;
@@ -814,10 +1000,9 @@
 
 std::string RVVIntrinsic::getBuiltinTypeStr() const {
   std::string S;
-  S += OutputType->getBuiltinStr();
-  for (const auto &T : InputTypes) {
-    S += T->getBuiltinStr();
-  }
+  S += Types[0]->getBuiltinStr();
+  for (unsigned i = 1; i < Types.size(); ++i)
+    S += Types[i]->getBuiltinStr();
   return S;
 }
 
@@ -860,30 +1045,30 @@
   OS << "  break;\n";
 }
 
-void RVVIntrinsic::emitIntrinsicFuncDef(raw_ostream &OS) const {
-  OS << "__attribute__((__clang_builtin_alias__(";
-  OS << "__builtin_rvv_" << getBuiltinName() << ")))\n";
-  OS << OutputType->getTypeStr() << " " << getName() << "(";
-  // Emit function arguments
-  if (!InputTypes.empty()) {
-    ListSeparator LS;
-    for (unsigned i = 0; i < InputTypes.size(); ++i)
-      OS << LS << InputTypes[i]->getTypeStr();
-  }
-  OS << ");\n";
-}
-
 void RVVIntrinsic::emitMangledFuncDef(raw_ostream &OS) const {
-  OS << "__attribute__((__clang_builtin_alias__(";
-  OS << "__builtin_rvv_" << getBuiltinName() << ")))\n";
-  OS << OutputType->getTypeStr() << " " << getMangledName() << "(";
-  // Emit function arguments
-  if (!InputTypes.empty()) {
-    ListSeparator LS;
-    for (unsigned i = 0; i < InputTypes.size(); ++i)
-      OS << LS << InputTypes[i]->getTypeStr();
+  // FIXME:
+  // It is hacky here. If we create the implicit funciton declarations, these
+  // overloaded builtins will trigger "call to %0 is ambiguous" error message.
+  // For example,
+  // vint8m1_t vloxei8(const int8_t *, vuint8m1_t, size_t);
+  // vuint8m1_t vloxei8(const uint8_t *, vuint8m1_t, size_t);
+  // The first pointer type is implicitly convertible. These two declarations
+  // are ambiguous.
+  if (getMangledName() == "vloxei8" || getMangledName() == "vloxei16" ||
+      getMangledName() == "vloxei32" || getMangledName() == "vloxei64" ||
+      getMangledName() == "vluxei8" || getMangledName() == "vluxei16" ||
+      getMangledName() == "vluxei32" || getMangledName() == "vluxei64") {
+    OS << "__rvv_aio __attribute__((__clang_builtin_alias__(";
+    OS << "__builtin_rvv_" << getBuiltinName() << ")))\n";
+    OS << Types[0]->getTypeStr() << " " << getMangledName() << "(";
+    // Emit function arguments
+    if (Types.size() > 1) {
+      ListSeparator LS;
+      for (unsigned i = 1; i < Types.size(); ++i)
+        OS << LS << Types[i]->getTypeStr();
+    }
+    OS << ");\n";
   }
-  OS << ");\n";
 }
 
 //===----------------------------------------------------------------------===//
@@ -917,12 +1102,10 @@
   OS << "#ifdef __cplusplus\n";
   OS << "extern \"C\" {\n";
   OS << "#endif\n\n";
+  OS << "#pragma riscv intrinsic vector\n\n";
 
   createRVVHeaders(OS);
 
-  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
-  createRVVIntrinsics(Defs);
-
   // Print header code
   if (!HeaderCode.empty()) {
     OS << HeaderCode;
@@ -981,16 +1164,6 @@
     return A->getRISCVExtensions() < B->getRISCVExtensions();
   });
 
-  OS << "#define __rvv_ai static __inline__\n";
-
-  // Print intrinsic functions with macro
-  emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
-    OS << "__rvv_ai ";
-    Inst.emitIntrinsicFuncDef(OS);
-  });
-
-  OS << "#undef __rvv_ai\n\n";
-
   OS << "#define __riscv_v_intrinsic_overloading 1\n";
 
   // Print Overloaded APIs
@@ -1000,7 +1173,6 @@
   emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
     if (!Inst.isMask() && !Inst.hasNoMaskedOverloaded())
       return;
-    OS << "__rvv_aio ";
     Inst.emitMangledFuncDef(OS);
   });
 
@@ -1013,9 +1185,6 @@
 }
 
 void RVVEmitter::createBuiltins(raw_ostream &OS) {
-  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
-  createRVVIntrinsics(Defs);
-
   // Map to keep track of which builtin names have already been emitted.
   StringMap<RVVIntrinsic *> BuiltinMap;
 
@@ -1046,8 +1215,6 @@
 }
 
 void RVVEmitter::createCodeGen(raw_ostream &OS) {
-  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
-  createRVVIntrinsics(Defs);
   // IR name could be empty, use the stable sort preserves the relative order.
   llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
                              const std::unique_ptr<RVVIntrinsic> &B) {
@@ -1254,18 +1421,17 @@
 
 Optional<RVVTypePtr> RVVEmitter::computeType(BasicType BT, int Log2LMUL,
                                              StringRef Proto) {
-  std::string Idx = Twine(Twine(BT) + Twine(Log2LMUL) + Proto).str();
-  // Search first
+  RVVType T(BT, Log2LMUL, Proto);
+  std::string Idx = T.getMangledStr();
   auto It = LegalTypes.find(Idx);
   if (It != LegalTypes.end())
     return &(It->second);
   if (IllegalTypes.count(Idx))
     return llvm::None;
-  // Compute type and record the result.
-  RVVType T(BT, Log2LMUL, Proto);
   if (T.isValid()) {
     // Record legal type index and value.
     LegalTypes.insert({Idx, T});
+    TypeList.push_back(&(LegalTypes[Idx]));
     return &(LegalTypes[Idx]);
   }
   // Record illegal type index.
@@ -1310,6 +1476,361 @@
   return true;
 }
 
+void RVVEmitter::EmitDeclarations(raw_ostream &OS) {
+  // Structure definitions.
+  OS << R"(
+enum RISCVFeatures {
+  RISCVFeature_F = 1 << 1,
+  RISCVFeature_D = 1 << 2,
+  RISCVFeature_ZFH = 1 << 3,
+  RISCVFeature_ZVLSSEG = 1 << 4,
+};
+
+// One overload of an RVV builtin function.
+struct RVVBuiltinStruct {
+  // Index of the signature in the RVVSignatureTable table.
+  const unsigned SigTableIndex;
+  // Entries between index SigTableIndex and (SigTableIndex + NumTypes - 1) in
+  // the RVVSignatureTable represent the complete signature.  The first type at
+  // index SigTableIndex is the return type.
+  const unsigned NumTypes;
+  // Required extensions for the builtin.
+  const uint8_t RequiredExts;
+};
+
+)";
+
+  unsigned I = 0;
+  for (auto *Ty : TypeList)
+    TypeMap.insert(std::make_pair(Ty, I++));
+
+  // Enum of scalar/vector type names (float, int, ...).
+  OS << "enum RVVTypeID {\n";
+  StringMap<bool> Seen;
+  for (const auto &T : TypeMap) {
+    auto *RVVTy = T.first;
+    if (Seen.find(RVVTy->getShortStr()) == Seen.end()) {
+      OS << "  RVVT_" + RVVTy->getShortStr() << ",\n";
+      Seen.insert(std::make_pair(RVVTy->getShortStr(), true));
+    }
+  }
+  OS << "};\n\n";
+
+  OS << R"(
+// Represents a return type or argument type.
+struct RVVTypeStruct {
+  // A type (e.g. float, int, ...).
+  const RVVTypeID ID;
+  // 0 if the type is not a pointer.
+  const bool IsPointer : 1;
+  // 0 if the type is not const.
+  const bool IsConst : 1;
+};
+
+)";
+
+  OS << "static const RVVTypeStruct RVVTypeTable[] = {\n";
+  for (const auto &T : TypeMap) {
+    auto *RVVTy = T.first;
+    OS << "  // " << T.second << ", " << RVVTy->getTypeStr() << "\n"
+       << "  {RVVT_" << RVVTy->getShortStr() << ", " << RVVTy->isPointer()
+       << ", " << RVVTy->isConstant() << "},\n";
+  }
+  OS << "};\n\n";
+}
+
+void RVVEmitter::GetOverloads(raw_ostream &OS) {
+  // Populate the SignaturesList and the FctOverloadMap.
+  unsigned CumulativeSignIndex = 0;
+  for (auto &Def : Defs) {
+    StringRef IName = Def->getName();
+    if (FctOverloadMap.find(IName) == FctOverloadMap.end()) {
+      FctOverloadMap.insert(std::make_pair(
+          IName, std::vector<std::pair<RVVIntrinsic *, unsigned>>{}));
+    }
+
+    auto Signature = Def->getRVVTypes();
+    auto it = llvm::find_if(SignaturesList,
+                            [&](const std::pair<const RVVTypes, unsigned> &a) {
+                              return a.first == Signature;
+                            });
+    unsigned SignIndex;
+    if (it == SignaturesList.end()) {
+      SignaturesList.push_back(std::make_pair(Signature, CumulativeSignIndex));
+      SignIndex = CumulativeSignIndex;
+      CumulativeSignIndex += Signature.size();
+    } else {
+      SignIndex = it->second;
+    }
+    FctOverloadMap[IName].push_back(std::make_pair(Def.get(), SignIndex));
+
+    if (Def->isMask() || Def->hasNoMaskedOverloaded()) {
+      // Put the generic builtin into FctOverloadMap.
+      // For example, vadd_vv_i8m1 has 'vadd' generic builtin.
+      StringRef GName = Def->getMangledName();
+      if (FctOverloadMap.find(GName) == FctOverloadMap.end()) {
+        FctOverloadMap.insert(std::make_pair(
+            GName, std::vector<std::pair<RVVIntrinsic *, unsigned>>{}));
+      }
+      FctOverloadMap[GName].push_back(std::make_pair(Def.get(), SignIndex));
+    }
+
+    auto builtin_it = llvm::find_if(BuiltinList, [&](const std::string &a) {
+      return a == "__builtin_rvv_" + Def->getBuiltinName().str();
+    });
+    unsigned BuiltinIdx = builtin_it - BuiltinList.begin();
+    if (Def->isMask() || Def->hasNoMaskedOverloaded()) {
+      StringRef GName = Def->getMangledName();
+      GenericBuiltinMap.insert(
+          std::make_pair(std::make_pair(GName, SignIndex), BuiltinIdx));
+    }
+
+    if (builtin_it == BuiltinList.end()) {
+      BuiltinList.push_back("__builtin_rvv_" + Def->getBuiltinName().str());
+    }
+  }
+}
+
+bool RVVEmitter::CanReuseSignature(
+    BuiltinIndexListTy *Candidate,
+    std::vector<std::pair<RVVIntrinsic *, unsigned>> &SignatureList) {
+  assert(Candidate->size() == SignatureList.size() &&
+         "signature lists should have the same size");
+
+  auto &CandidateSigs = SignatureListMap.find(Candidate)->second.Signatures;
+  for (unsigned Index = 0; Index < Candidate->size(); Index++) {
+    auto *Rec = SignatureList[Index].first;
+    auto *Rec2 = CandidateSigs[Index].first;
+    if (Rec->getRISCVExtensions() == Rec2->getRISCVExtensions())
+      return true;
+  }
+  return false;
+}
+
+void RVVEmitter::GroupBySignature(raw_ostream &OS) {
+  // List of signatures known to be emitted.
+  std::vector<BuiltinIndexListTy *> KnownSignatures;
+
+  for (auto &Fct : FctOverloadMap) {
+    bool FoundReusableSig = false;
+
+    // Gather all signatures for the current function.
+    auto *CurSignatureList = new BuiltinIndexListTy();
+    for (const auto &Signature : Fct.second)
+      CurSignatureList->push_back(Signature.second);
+
+    // Sort the list to facilitate future comparisons.
+    llvm::sort(*CurSignatureList);
+
+    auto it = llvm::find_if(BuiltinList, [&](const std::string &a) {
+      return a ==
+             "__builtin_rvv_" + Fct.second[0].first->getBuiltinName().str();
+    });
+    unsigned BuiltinIndex = it - BuiltinList.begin();
+    // Check if we have already seen another function with the same list of
+    // signatures.  If so, just add the name of the function.
+    for (auto *Candidate : KnownSignatures) {
+      if (Candidate->size() == CurSignatureList->size() &&
+          *Candidate == *CurSignatureList) {
+        if (CanReuseSignature(Candidate, Fct.second)) {
+          SignatureListMap.find(Candidate)->second.Names.push_back(Fct.first);
+          SignatureListMap.find(Candidate)->second.BuiltinIndex.push_back(
+              BuiltinIndex);
+          FoundReusableSig = true;
+        }
+      }
+    }
+
+    if (FoundReusableSig) {
+      delete CurSignatureList;
+    } else {
+      // Add a new entry.
+      SignatureListMap[CurSignatureList] = {
+          SmallVector<StringRef, 4>(1, Fct.first),
+          SmallVector<unsigned, 4>(1, BuiltinIndex), Fct.second};
+      KnownSignatures.push_back(CurSignatureList);
+    }
+  }
+
+  for (auto *I : KnownSignatures)
+    delete I;
+}
+
+void RVVEmitter::EmitSignatureTable(raw_ostream &OS) {
+  // The type is stored as an index
+  // of RVVTypeTable. Multiple entries following each other form a
+  // signature.
+  OS << "static const unsigned short RVVSignatureTable[] = {\n";
+  for (const auto &P : SignaturesList) {
+    OS << "  // " << P.second << ", ";
+    for (auto *Ty : P.first)
+      OS << Ty->getTypeStr() << " ";
+    OS << "\n";
+    for (auto *Ty : P.first) {
+      unsigned Entry = TypeMap.find(Ty)->second;
+      if (Entry > USHRT_MAX) {
+        // Report an error when seeing an entry that is too large for the
+        // current index type (unsigned short).  When hitting this, the type
+        // of SignatureTable will need to be changed.
+        PrintFatalError("Entry in SignatureTable exceeds limit.");
+      }
+      OS << Entry << ", ";
+    }
+    OS << "\n";
+  }
+  OS << "};\n\n";
+}
+
+void RVVEmitter::EmitBuiltinTable(raw_ostream &OS) {
+  OS << "static const char *RVVBuiltinName[] = {\n";
+  for (const auto &B : BuiltinList)
+    OS << "  \"" << B << "\",\n";
+  OS << "};\n\n";
+
+  unsigned Index = 0;
+  OS << "static const RVVBuiltinStruct RVVBuiltinTable[] = {\n";
+  for (const auto &SLM : SignatureListMap) {
+
+    OS << "  // " << (Index + 1) << ": ";
+    for (const auto &Name : SLM.second.Names) {
+      OS << Name << ", ";
+    }
+    OS << "\n";
+
+    OS << "  // Builtins: ";
+    for (const auto &BuiltinIndex : SLM.second.BuiltinIndex) {
+      OS << BuiltinList[BuiltinIndex] << ", ";
+    }
+    OS << "\n";
+
+    for (const auto &Overload : SLM.second.Signatures) {
+      RVVIntrinsic *Intr = Overload.first;
+      OS << "  {" << Overload.second << ", " << Intr->getRVVTypes().size()
+         << ", " << +Intr->getRISCVExtensions() << "},\n";
+      Index++;
+    }
+  }
+  OS << "};\n";
+}
+
+void RVVEmitter::EmitBuiltinMapTable(raw_ostream &OS) {
+  OS << "static std::map<std::pair<StringRef, unsigned>, unsigned> ";
+  OS << " RVVGenericBuiltinMap = {\n";
+  for (const auto &M : GenericBuiltinMap) {
+    OS << " // " << BuiltinList[M.second] << "\n";
+    OS << "  {std::make_pair(\"" << M.first.first << "\", " << M.first.second
+       << "), ";
+    OS << M.second << "},\n";
+  }
+  OS << "};\n";
+}
+
+void RVVEmitter::EmitStringMatcher(raw_ostream &OS) {
+  std::vector<StringMatcher::StringPair> ValidBuiltins;
+  unsigned CumulativeIndex = 1;
+
+  for (const auto &SLM : SignatureListMap) {
+    const auto &Ovl = SLM.second.Signatures;
+
+    // A single signature list may be used by different builtins.  Return the
+    // same <index, length> pair for each of those builtins.
+    for (unsigned i = 0; i < SLM.second.Names.size(); ++i) {
+      const auto &FctName = SLM.second.Names[i];
+      unsigned BuiltinIndex = SLM.second.BuiltinIndex[i];
+      std::string RetStmt;
+      raw_string_ostream SS(RetStmt);
+      SS << "return std::make_tuple(" << CumulativeIndex << ", " << Ovl.size()
+         << ", " << BuiltinIndex << ");";
+      SS.flush();
+      ValidBuiltins.push_back(
+          StringMatcher::StringPair(std::string(FctName), RetStmt));
+    }
+    CumulativeIndex += Ovl.size();
+  }
+
+  OS << R"(
+// Find out whether a string matches an existing RVV builtin function name.
+// Returns: A tuple <0, 0, 0> if no name matches.
+//          A tuple <Index, Len, BuiltinIdx> indexing the RVVBuiltinTable if the name is
+//          matching an RVV builtin function.
+static std::tuple<unsigned, unsigned, unsigned> isRVVBuiltin(llvm::StringRef Name) {
+
+)";
+
+  StringMatcher("Name", ValidBuiltins, OS).Emit(0, true);
+
+  OS << "  return std::make_tuple(0, 0, 0);\n";
+  OS << "} // isRVVBuiltin\n";
+}
+
+void RVVEmitter::EmitQualTypeFinder(raw_ostream &OS) {
+  OS << R"(
+
+// Convert a RVVTypeStruct type to a QualTypes.
+static void RVV2Qual(Sema &S, const RVVTypeStruct &Ty, QualType &QT) {
+  ASTContext &Context = S.Context;
+)";
+
+  // Step 1.
+  // Start of switch statement over all types.
+  OS << "\n  switch (Ty.ID) {\n";
+
+  // Only insert the plain scalar type; vector information and type qualifiers
+  // are added in step 2.
+  StringMap<bool> TypesSeen;
+  for (const auto &T : TypeMap) {
+    auto *RVVTy = T.first;
+    if (TypesSeen.find(RVVTy->getShortStr()) != TypesSeen.end())
+      continue;
+    TypesSeen.insert(std::make_pair(RVVTy->getShortStr(), true));
+    // Get QualType
+    OS << "    case RVVT_" << RVVTy->getShortStr() << ":\n";
+    OS << "      QT = " << RVVTy->getQualExpr() << ";\n";
+    OS << "      break;\n";
+  }
+  // End of switch statement.
+  OS << "  } // end of switch (Ty.ID)\n\n";
+
+  // Step 2.
+  // Assign the right attributes to the types.
+  OS << R"(
+  if (Ty.IsConst != 0) {
+    QT = Context.getConstType(QT);
+  }
+
+  // Transform the type to a pointer as the last step, if necessary.
+  if (Ty.IsPointer != 0) {
+    QT = Context.getPointerType(QT);
+  }
+)";
+
+  // End of the "RVV2Qual" function.
+  OS << "\n} // RVV2Qual\n";
+}
+
+void RVVEmitter::createSema(raw_ostream &OS) {
+  emitSourceFileHeader("RISC-V Vector Builtin handling", OS);
+
+  OS << "#include \"llvm/ADT/StringRef.h\"\n";
+  OS << "using namespace clang;\n\n";
+
+  // Emit enums and structs.
+  EmitDeclarations(OS);
+
+  // Parse the Records to populate the internal lists.
+  GetOverloads(OS);
+  GroupBySignature(OS);
+
+  // Emit tables.
+  EmitSignatureTable(OS);
+  EmitBuiltinTable(OS);
+  EmitBuiltinMapTable(OS);
+
+  // Emit functions.
+  EmitStringMatcher(OS);
+  EmitQualTypeFinder(OS);
+}
+
 namespace clang {
 void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
   RVVEmitter(Records).createHeader(OS);
@@ -1323,4 +1844,8 @@
   RVVEmitter(Records).createCodeGen(OS);
 }
 
+void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {
+  RVVEmitter(Records).createSema(OS);
+}
+
 } // End namespace clang
Index: clang/lib/Sema/SemaLookup.cpp
===================================================================
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -23,6 +23,8 @@
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/Preprocessor.h"
@@ -48,6 +50,7 @@
 #include <vector>
 
 #include "OpenCLBuiltins.inc"
+#include "clang/Basic/riscv_vector_builtin_sema.inc"
 
 using namespace clang;
 using namespace sema;
@@ -896,6 +899,126 @@
     LR.resolveKind();
 }
 
+static void GetQualTypesForRVVBuiltin(Sema &S, const RVVBuiltinStruct &Builtin,
+                                      QualType &RetType,
+                                      SmallVector<QualType, 5> &ArgTypes) {
+  // Get the QualType instance of the return type.
+  unsigned Sig = RVVSignatureTable[Builtin.SigTableIndex];
+  RVV2Qual(S, RVVTypeTable[Sig], RetType);
+
+  // Get the QualType instances of the arguments.
+  // First type is the return type, skip it.
+  for (unsigned Index = 1; Index < Builtin.NumTypes; Index++) {
+    QualType Ty;
+    RVV2Qual(S, RVVTypeTable[RVVSignatureTable[Builtin.SigTableIndex + Index]],
+             Ty);
+    ArgTypes.push_back(std::move(Ty));
+  }
+}
+
+static void GetRVVBuiltinFuncType(ASTContext &Context,
+                                  QualType &BuiltinFuncType, QualType &RetType,
+                                  SmallVector<QualType, 5> &ArgTypes) {
+  FunctionProtoType::ExtProtoInfo PI(
+      Context.getDefaultCallingConvention(false, false, true));
+  PI.Variadic = false;
+
+  BuiltinFuncType = Context.getFunctionType(RetType, ArgTypes, PI);
+}
+
+static unsigned GetTargetFeatures(const TargetInfo &TI) {
+  bool HasF = TI.hasFeature("f");
+  bool HasD = TI.hasFeature("d");
+  bool HasZfh = TI.hasFeature("experimental-zfh");
+  bool HasZvlsseg = TI.hasFeature("experimental-zvlsseg");
+  unsigned Features = 0;
+  if (HasF)
+    Features |= RISCVFeature_F;
+  if (HasD)
+    Features |= RISCVFeature_D;
+  if (HasZfh)
+    Features |= RISCVFeature_ZFH;
+  if (HasZvlsseg)
+    Features |= RISCVFeature_ZVLSSEG;
+
+  return Features;
+}
+
+static void InsertRVVBuiltinDeclarationsFromTable(
+    Sema &S, LookupResult &LR, IdentifierInfo *II, Preprocessor &PP,
+    const unsigned FctIndex, const unsigned Len, const unsigned BuiltinIndex) {
+
+  // FIXME:
+  // It is hacky here. If we create the implicit funciton declarations, these
+  // overloaded builtins will trigger "call to %0 is ambiguous" error message.
+  // For example,
+  // vint8m1_t vloxei8(const int8_t *, vuint8m1_t, size_t);
+  // vuint8m1_t vloxei8(const uint8_t *, vuint8m1_t, size_t);
+  // The first pointer type is implicitly convertible. These two declarations
+  // are ambiguous.
+  if (II->getName() == "vloxei8" || II->getName() == "vloxei16" ||
+      II->getName() == "vloxei32" || II->getName() == "vloxei64" ||
+      II->getName() == "vluxei8" || II->getName() == "vluxei16" ||
+      II->getName() == "vluxei32" || II->getName() == "vluxei64")
+    return;
+
+  ASTContext &Context = S.Context;
+  unsigned RVVTargetFeatures = GetTargetFeatures(Context.getTargetInfo());
+
+  for (unsigned SignatureIndex = 0; SignatureIndex < Len; SignatureIndex++) {
+    const RVVBuiltinStruct &RVVBuiltin =
+        RVVBuiltinTable[FctIndex + SignatureIndex];
+
+    if ((RVVBuiltin.RequiredExts & RVVTargetFeatures) !=
+        RVVBuiltin.RequiredExts)
+      continue;
+
+    QualType RetType;
+    SmallVector<QualType, 5> ArgTypes;
+    GetQualTypesForRVVBuiltin(S, RVVBuiltin, RetType, ArgTypes);
+
+    QualType BuiltinFuncType;
+    GetRVVBuiltinFuncType(Context, BuiltinFuncType, RetType, ArgTypes);
+
+    SourceLocation Loc = LR.getNameLoc();
+    DeclContext *Parent = Context.getTranslationUnitDecl();
+    FunctionDecl *NewRVVBuiltin = FunctionDecl::Create(
+        Context, Parent, Loc, Loc, II, BuiltinFuncType, /*TInfo=*/nullptr,
+        SC_Extern, S.getCurFPFeatures().isFPConstrained(), false,
+        BuiltinFuncType->isFunctionProtoType());
+    NewRVVBuiltin->setImplicit();
+
+    // Create Decl objects for each parameter, adding them to the
+    // FunctionDecl.
+    const auto *FP = cast<FunctionProtoType>(BuiltinFuncType);
+    SmallVector<ParmVarDecl *, 5> ParmList;
+    for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) {
+      ParmVarDecl *Parm = ParmVarDecl::Create(
+          Context, NewRVVBuiltin, SourceLocation(), SourceLocation(), nullptr,
+          FP->getParamType(IParm), nullptr, SC_None, nullptr);
+      Parm->setScopeInfo(0, IParm);
+      ParmList.push_back(Parm);
+    }
+    NewRVVBuiltin->setParams(ParmList);
+    NewRVVBuiltin->addAttr(OverloadableAttr::CreateImplicit(Context));
+    // Add __clang_builtin_alias__(BuiltinName) attribute.
+    unsigned BuiltinID = BuiltinIndex;
+    // If it is a generic C builtin, find the clang builtin by
+    // (name, signature index).
+    if (Len > 1)
+      BuiltinID = RVVGenericBuiltinMap[std::make_pair(
+          II->getName(), RVVBuiltin.SigTableIndex)];
+    auto &IntrinsicII = PP.getIdentifierTable().get(RVVBuiltinName[BuiltinID]);
+    NewRVVBuiltin->addAttr(
+        BuiltinAliasAttr::CreateImplicit(S.Context, &IntrinsicII));
+
+    LR.addDecl(NewRVVBuiltin);
+  }
+
+  if (Len > 1)
+    LR.resolveKind();
+}
+
 /// Lookup a builtin function, when name lookup would otherwise
 /// fail.
 bool Sema::LookupBuiltin(LookupResult &R) {
@@ -928,6 +1051,17 @@
         }
       }
 
+      // TODO: Find a better way to detect RVV.
+      if (PP.getPredefines() == "#define __riscv_pragma_vector_intrinsics") {
+        unsigned SigIndex, SigSize, BuiltinIndex;
+        std::tie(SigIndex, SigSize, BuiltinIndex) = isRVVBuiltin(II->getName());
+        if (SigIndex) {
+          InsertRVVBuiltinDeclarationsFromTable(*this, R, II, PP, SigIndex - 1,
+                                                SigSize, BuiltinIndex);
+          return true;
+        }
+      }
+
       // If this is a builtin on this (or all) targets, create the decl.
       if (unsigned BuiltinID = II->getBuiltinID()) {
         // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -356,6 +356,16 @@
                     Token &FirstToken) override;
 };
 
+struct PragmaRISCVHandler : public PragmaHandler {
+  PragmaRISCVHandler(Sema &Actions)
+      : PragmaHandler("riscv"), Actions(Actions) {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+                    Token &FirstToken) override;
+
+private:
+  Sema &Actions;
+};
+
 void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
   for (auto &T : Toks)
     T.setFlag(clang::Token::IsReinjected);
@@ -495,6 +505,11 @@
 
   MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
   PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
+
+  if (getTargetInfo().getTriple().isRISCV()) {
+    RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
+    PP.AddPragmaHandler(RISCVPragmaHandler.get());
+  }
 }
 
 void Parser::resetPragmaHandlers() {
@@ -615,6 +630,11 @@
 
   PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
   MaxTokensTotalPragmaHandler.reset();
+
+  if (getTargetInfo().getTriple().isRISCV()) {
+    PP.RemovePragmaHandler(RISCVPragmaHandler.get());
+    RISCVPragmaHandler.reset();
+  }
 }
 
 /// Handle the annotation token produced for #pragma unused(...)
@@ -3798,3 +3818,27 @@
 
   PP.overrideMaxTokens(MaxTokens, Loc);
 }
+
+// Handle '#pragma riscv intrinsic vector'.
+void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
+                                      PragmaIntroducer Introducer,
+                                      Token &FirstToken) {
+  Token Tok;
+  PP.Lex(Tok);
+  IdentifierInfo *II = Tok.getIdentifierInfo();
+  if (!II || (!II->isStr("intrinsic"))) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
+        << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
+    return;
+  }
+
+  PP.Lex(Tok);
+  II = Tok.getIdentifierInfo();
+  if (!II || (!II->isStr("vector"))) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
+        << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'vector'";
+    return;
+  }
+
+  PP.setPredefines("#define __riscv_pragma_vector_intrinsics");
+}
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -212,6 +212,7 @@
   std::unique_ptr<PragmaHandler> AttributePragmaHandler;
   std::unique_ptr<PragmaHandler> MaxTokensHerePragmaHandler;
   std::unique_ptr<PragmaHandler> MaxTokensTotalPragmaHandler;
+  std::unique_ptr<PragmaHandler> RISCVPragmaHandler;
 
   std::unique_ptr<CommentHandler> CommentSemaHandler;
 
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -887,6 +887,9 @@
 // Annotation for the attribute pragma directives - #pragma clang attribute ...
 PRAGMA_ANNOTATION(pragma_attribute)
 
+// Annotation for the riscv pragma directives - #pragma riscv intrinsic ...
+PRAGMA_ANNOTATION(pragma_riscv)
+
 // Annotations for module import translated from #include etc.
 ANNOTATION(module_include)
 ANNOTATION(module_begin)
Index: clang/include/clang/Basic/CMakeLists.txt
===================================================================
--- clang/include/clang/Basic/CMakeLists.txt
+++ clang/include/clang/Basic/CMakeLists.txt
@@ -90,3 +90,6 @@
 clang_tablegen(riscv_vector_builtin_cg.inc -gen-riscv-vector-builtin-codegen
   SOURCE riscv_vector.td
   TARGET ClangRISCVVectorBuiltinCG)
+clang_tablegen(riscv_vector_builtin_sema.inc -gen-riscv-vector-builtin-sema
+  SOURCE riscv_vector.td
+  TARGET ClangRISCVVectorBuiltinSema)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to