zixuan-wu updated this revision to Diff 395803.
zixuan-wu edited the summary of this revision.
zixuan-wu added a comment.

Address comments.


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

https://reviews.llvm.org/D115921

Files:
  clang/lib/Basic/Targets/RISCV.cpp
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/test/Driver/riscv-arch.c
  llvm/include/llvm/Support/RISCVISAInfo.h
  llvm/lib/Object/ELFObjectFile.cpp
  llvm/lib/Support/RISCVISAInfo.cpp
  llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
  llvm/lib/Target/RISCV/RISCV.td
  llvm/lib/Target/RISCV/RISCVSubtarget.cpp
  llvm/lib/Target/RISCV/RISCVSubtarget.h
  llvm/test/CodeGen/RISCV/attributes.ll
  llvm/test/MC/RISCV/attribute-arch.s
  llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test

Index: llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
===================================================================
--- llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
+++ llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test
@@ -3,7 +3,7 @@
 ## The expected behavior is to ignore the unrecognized arch feature and
 ## continue to process the following arch features.
 ##
-## The object file has the "rv32i2p0_x1p0_m2p0" arch feature. "x1p0" is an
+## The object file has the "rv32i2p0_y1p0_m2p0" arch feature. "y1p0" is an
 ## unrecognized architecture extension. llvm-objdump will ignore it and decode
 ## "mul" instruction correctly according to "m2p0" in the arch feature.
 ##
@@ -34,5 +34,5 @@
     Content: 3385C502
   - Name:    .riscv.attributes
     Type:    SHT_RISCV_ATTRIBUTES
-## The content is the encoding of the arch feature "rv32i2p0_x1p0_m2p0"
-    Content: 412300000072697363760001190000000572763332693270305F783170305F6D32703000
+## The content is the encoding of the arch feature "rv32i2p0_y1p0_m2p0"
+    Content: 412300000072697363760001190000000572763332693270305F793170305F6D32703000
Index: llvm/test/MC/RISCV/attribute-arch.s
===================================================================
--- llvm/test/MC/RISCV/attribute-arch.s
+++ llvm/test/MC/RISCV/attribute-arch.s
@@ -76,3 +76,6 @@
 
 .attribute arch, "rv32iv0p10zvlsseg0p10"
 # CHECK: attribute      5, "rv32i2p0_v0p10_zvlsseg0p10"
+
+.attribute arch, "rv32iv0p7zvlsseg0p7"
+# CHECK: attribute      5, "rv32i2p0_v0p7_zvlsseg0p7"
Index: llvm/test/CodeGen/RISCV/attributes.ll
===================================================================
--- llvm/test/CodeGen/RISCV/attributes.ll
+++ llvm/test/CodeGen/RISCV/attributes.ll
@@ -17,6 +17,7 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbr %s -o - | FileCheck --check-prefix=RV32ZBR %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbs %s -o - | FileCheck --check-prefix=RV32ZBS %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbt %s -o - | FileCheck --check-prefix=RV32ZBT %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-v0p7 %s -o - | FileCheck --check-prefix=RV32V0P7 %s
 ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefix=RV64M %s
 ; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefix=RV64A %s
 ; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefix=RV64F %s
@@ -34,6 +35,7 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbr %s -o - | FileCheck --check-prefix=RV64ZBR %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbs %s -o - | FileCheck --check-prefix=RV64ZBS %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbt %s -o - | FileCheck --check-prefix=RV64ZBT %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-v0p7 %s -o - | FileCheck --check-prefix=RV64V0P7 %s
 
 ; RV32M: .attribute 5, "rv32i2p0_m2p0"
 ; RV32A: .attribute 5, "rv32i2p0_a2p0"
@@ -53,6 +55,7 @@
 ; RV32ZBR: .attribute 5, "rv32i2p0_zbr0p93"
 ; RV32ZBS: .attribute 5, "rv32i2p0_zbs1p0"
 ; RV32ZBT: .attribute 5, "rv32i2p0_zbt0p93"
+; RV32V0P7: .attribute 5, "rv32i2p0_v0p7_zvlsseg0p7"
 ; RV32COMBINED: .attribute 5, "rv32i2p0_f2p0_v0p10_zfh0p1_zfhmin0p1_zbb1p0_zvlsseg0p10"
 
 ; RV64M: .attribute 5, "rv64i2p0_m2p0"
@@ -73,6 +76,7 @@
 ; RV64ZBS: .attribute 5, "rv64i2p0_zbs1p0"
 ; RV64ZBT: .attribute 5, "rv64i2p0_zbt0p93"
 ; RV64V: .attribute 5, "rv64i2p0_v0p10_zvlsseg0p10"
+; RV64V0P7: .attribute 5, "rv64i2p0_v0p7_zvlsseg0p7"
 ; RV64COMBINED: .attribute 5, "rv64i2p0_f2p0_v0p10_zfh0p1_zfhmin0p1_zbb1p0_zvlsseg0p10"
 
 
Index: llvm/lib/Target/RISCV/RISCVSubtarget.h
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/SelectionDAGTargetInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/Support/RISCVISAInfo.h"
 #include "llvm/Target/TargetMachine.h"
 
 #define GET_SUBTARGETINFO_HEADER
@@ -34,27 +35,28 @@
 
 class RISCVSubtarget : public RISCVGenSubtargetInfo {
   virtual void anchor();
-  bool HasStdExtM = false;
-  bool HasStdExtA = false;
-  bool HasStdExtF = false;
-  bool HasStdExtD = false;
-  bool HasStdExtC = false;
-  bool HasStdExtZba = false;
-  bool HasStdExtZbb = false;
-  bool HasStdExtZbc = false;
-  bool HasStdExtZbe = false;
-  bool HasStdExtZbf = false;
-  bool HasStdExtZbm = false;
-  bool HasStdExtZbp = false;
-  bool HasStdExtZbr = false;
-  bool HasStdExtZbs = false;
-  bool HasStdExtZbt = false;
-  bool HasStdExtV = false;
-  bool HasStdExtZvlsseg = false;
-  bool HasStdExtZfhmin = false;
-  bool HasStdExtZfh = false;
+  RISCVExtensionVersion StdExtM = {0, 0};
+  RISCVExtensionVersion StdExtA = {0, 0};
+  RISCVExtensionVersion StdExtF = {0, 0};
+  RISCVExtensionVersion StdExtD = {0, 0};
+  RISCVExtensionVersion StdExtC = {0, 0};
+  RISCVExtensionVersion StdExtZba = {0, 0};
+  RISCVExtensionVersion StdExtZbb = {0, 0};
+  RISCVExtensionVersion StdExtZbc = {0, 0};
+  RISCVExtensionVersion StdExtZbe = {0, 0};
+  RISCVExtensionVersion StdExtZbf = {0, 0};
+  RISCVExtensionVersion StdExtZbm = {0, 0};
+  RISCVExtensionVersion StdExtZbp = {0, 0};
+  RISCVExtensionVersion StdExtZbr = {0, 0};
+  RISCVExtensionVersion StdExtZbs = {0, 0};
+  RISCVExtensionVersion StdExtZbt = {0, 0};
+  RISCVExtensionVersion StdExtV = {0, 0};
+  RISCVExtensionVersion StdExtZvlsseg = {0, 0};
+  RISCVExtensionVersion StdExtZvamo = {0, 0};
+  RISCVExtensionVersion StdExtZfhmin = {0, 0};
+  RISCVExtensionVersion StdExtZfh = {0, 0};
+  RISCVExtensionVersion StdExtE = {0, 0};
   bool HasRV64 = false;
-  bool IsRV32E = false;
   bool EnableLinkerRelax = false;
   bool EnableRVCHintInstrs = true;
   bool EnableSaveRestore = false;
@@ -69,6 +71,7 @@
   RISCVTargetLowering TLInfo;
   SelectionDAGTargetInfo TSInfo;
 
+  void initializeEnvironment();
   /// Initializes using the passed in CPU and feature strings so that we can
   /// use initializer lists for subtarget initialization.
   RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
@@ -100,27 +103,31 @@
     return &TSInfo;
   }
   bool enableMachineScheduler() const override { return true; }
-  bool hasStdExtM() const { return HasStdExtM; }
-  bool hasStdExtA() const { return HasStdExtA; }
-  bool hasStdExtF() const { return HasStdExtF; }
-  bool hasStdExtD() const { return HasStdExtD; }
-  bool hasStdExtC() const { return HasStdExtC; }
-  bool hasStdExtZba() const { return HasStdExtZba; }
-  bool hasStdExtZbb() const { return HasStdExtZbb; }
-  bool hasStdExtZbc() const { return HasStdExtZbc; }
-  bool hasStdExtZbe() const { return HasStdExtZbe; }
-  bool hasStdExtZbf() const { return HasStdExtZbf; }
-  bool hasStdExtZbm() const { return HasStdExtZbm; }
-  bool hasStdExtZbp() const { return HasStdExtZbp; }
-  bool hasStdExtZbr() const { return HasStdExtZbr; }
-  bool hasStdExtZbs() const { return HasStdExtZbs; }
-  bool hasStdExtZbt() const { return HasStdExtZbt; }
-  bool hasStdExtV() const { return HasStdExtV; }
-  bool hasStdExtZvlsseg() const { return HasStdExtZvlsseg; }
-  bool hasStdExtZfhmin() const { return HasStdExtZfhmin; }
-  bool hasStdExtZfh() const { return HasStdExtZfh; }
+  bool hasStdExtM() const { return StdExtM != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtA() const { return StdExtA != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtF() const { return StdExtF != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtD() const { return StdExtD != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtC() const { return StdExtC != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZba() const { return StdExtZba != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbb() const { return StdExtZbb != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbc() const { return StdExtZbc != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbe() const { return StdExtZbe != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbf() const { return StdExtZbf != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbm() const { return StdExtZbm != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbp() const { return StdExtZbp != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbr() const { return StdExtZbr != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbs() const { return StdExtZbs != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZbt() const { return StdExtZbt != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtV() const { return StdExtV != RISCVExtensionVersion{0, 0}; }
+  bool hasStdExtZvlsseg() const {
+    return StdExtZvlsseg != RISCVExtensionVersion{0, 0};
+  }
+  bool hasStdExtZfhmin() const {
+    return StdExtZfhmin != RISCVExtensionVersion{0, 0};
+  }
+  bool hasStdExtZfh() const { return StdExtZfh != RISCVExtensionVersion{0, 0}; }
   bool is64Bit() const { return HasRV64; }
-  bool isRV32E() const { return IsRV32E; }
+  bool isRV32E() const { return StdExtE != RISCVExtensionVersion{0, 0}; }
   bool enableLinkerRelax() const { return EnableLinkerRelax; }
   bool enableRVCHintInstrs() const { return EnableRVCHintInstrs; }
   bool enableSaveRestore() const { return EnableSaveRestore; }
@@ -133,11 +140,21 @@
   }
 
   // Vector codegen related methods.
-  bool hasVInstructions() const { return HasStdExtV; }
-  bool hasVInstructionsI64() const { return HasStdExtV; }
-  bool hasVInstructionsF16() const { return HasStdExtV && hasStdExtZfh(); }
-  bool hasVInstructionsF32() const { return HasStdExtV && hasStdExtF(); }
-  bool hasVInstructionsF64() const { return HasStdExtV && hasStdExtD(); }
+  bool hasVInstructions() const {
+    return StdExtV != RISCVExtensionVersion{0, 0};
+  }
+  bool hasVInstructionsI64() const {
+    return StdExtV != RISCVExtensionVersion{0, 0};
+  }
+  bool hasVInstructionsF16() const {
+    return StdExtV != RISCVExtensionVersion{0, 0} && hasStdExtZfh();
+  }
+  bool hasVInstructionsF32() const {
+    return StdExtV != RISCVExtensionVersion{0, 0} && hasStdExtF();
+  }
+  bool hasVInstructionsF64() const {
+    return StdExtV != RISCVExtensionVersion{0, 0} && hasStdExtD();
+  }
   // F16 and F64 both require F32.
   bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
   unsigned getMaxInterleaveFactor() const {
Index: llvm/lib/Target/RISCV/RISCVSubtarget.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -52,10 +52,43 @@
 
 void RISCVSubtarget::anchor() {}
 
+void RISCVSubtarget::initializeEnvironment() {
+  StdExtM = {0, 0};
+  StdExtA = {0, 0};
+  StdExtF = {0, 0};
+  StdExtD = {0, 0};
+  StdExtC = {0, 0};
+  StdExtZba = {0, 0};
+  StdExtZbb = {0, 0};
+  StdExtZbc = {0, 0};
+  StdExtZbe = {0, 0};
+  StdExtZbf = {0, 0};
+  StdExtZbm = {0, 0};
+  StdExtZbp = {0, 0};
+  StdExtZbr = {0, 0};
+  StdExtZbs = {0, 0};
+  StdExtZbt = {0, 0};
+  StdExtV = {0, 0};
+  StdExtZvlsseg = {0, 0};
+  StdExtZvamo = {0, 0};
+  StdExtZfhmin = {0, 0};
+  StdExtZfh = {0, 0};
+  StdExtE = {0, 0};
+  HasRV64 = false;
+  EnableLinkerRelax = false;
+  EnableRVCHintInstrs = true;
+  EnableSaveRestore = false;
+  XLen = 32;
+  XLenVT = MVT::i32;
+  MaxInterleaveFactor = 2;
+  TargetABI = RISCVABI::ABI_Unknown;
+}
+
 RISCVSubtarget &
 RISCVSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef CPU,
                                                 StringRef TuneCPU, StringRef FS,
                                                 StringRef ABIName) {
+  initializeEnvironment();
   // Determine default and user-specified characteristics
   bool Is64Bit = TT.isArch64Bit();
   if (CPU.empty())
@@ -66,7 +99,6 @@
 
   if (TuneCPU.empty())
     TuneCPU = CPU;
-
   ParseSubtargetFeatures(CPU, TuneCPU, FS);
   if (Is64Bit) {
     XLenVT = MVT::i64;
Index: llvm/lib/Target/RISCV/RISCV.td
===================================================================
--- llvm/lib/Target/RISCV/RISCV.td
+++ llvm/lib/Target/RISCV/RISCV.td
@@ -13,28 +13,28 @@
 //===----------------------------------------------------------------------===//
 
 def FeatureStdExtM
-    : SubtargetFeature<"m", "HasStdExtM", "true",
+    : SubtargetFeature<"m", "StdExtM", "RISCVExtensionVersion{2, 0}",
                        "'M' (Integer Multiplication and Division)">;
 def HasStdExtM : Predicate<"Subtarget->hasStdExtM()">,
                            AssemblerPredicate<(all_of FeatureStdExtM),
                            "'M' (Integer Multiplication and Division)">;
 
 def FeatureStdExtA
-    : SubtargetFeature<"a", "HasStdExtA", "true",
+    : SubtargetFeature<"a", "StdExtA", "RISCVExtensionVersion{2, 0}",
                        "'A' (Atomic Instructions)">;
 def HasStdExtA : Predicate<"Subtarget->hasStdExtA()">,
                            AssemblerPredicate<(all_of FeatureStdExtA),
                            "'A' (Atomic Instructions)">;
 
 def FeatureStdExtF
-    : SubtargetFeature<"f", "HasStdExtF", "true",
+    : SubtargetFeature<"f", "StdExtF", "RISCVExtensionVersion{2, 0}",
                        "'F' (Single-Precision Floating-Point)">;
 def HasStdExtF : Predicate<"Subtarget->hasStdExtF()">,
                            AssemblerPredicate<(all_of FeatureStdExtF),
                            "'F' (Single-Precision Floating-Point)">;
 
 def FeatureStdExtD
-    : SubtargetFeature<"d", "HasStdExtD", "true",
+    : SubtargetFeature<"d", "StdExtD", "RISCVExtensionVersion{2, 0}",
                        "'D' (Double-Precision Floating-Point)",
                        [FeatureStdExtF]>;
 def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">,
@@ -42,7 +42,8 @@
                            "'D' (Double-Precision Floating-Point)">;
 
 def FeatureStdExtZfhmin
-    : SubtargetFeature<"experimental-zfhmin", "HasStdExtZfhmin", "true",
+    : SubtargetFeature<"experimental-zfhmin", "StdExtZfhmin",
+                       "RISCVExtensionVersion{0, 1}",
                        "'Zfhmin' (Half-Precision Floating-Point Minimal)",
                        [FeatureStdExtF]>;
 def HasStdExtZfhmin : Predicate<"Subtarget->hasStdExtZfhmin()">,
@@ -50,7 +51,8 @@
                              "'Zfhmin' (Half-Precision Floating-Point Minimal)">;
 
 def FeatureStdExtZfh
-    : SubtargetFeature<"experimental-zfh", "HasStdExtZfh", "true",
+    : SubtargetFeature<"experimental-zfh", "StdExtZfh",
+                       "RISCVExtensionVersion{0, 1}",
                        "'Zfh' (Half-Precision Floating-Point)",
                        [FeatureStdExtZfhmin, FeatureStdExtF]>;
 def HasStdExtZfh : Predicate<"Subtarget->hasStdExtZfh()">,
@@ -58,14 +60,15 @@
                              "'Zfh' (Half-Precision Floating-Point)">;
 
 def FeatureStdExtC
-    : SubtargetFeature<"c", "HasStdExtC", "true",
+    : SubtargetFeature<"c", "StdExtC", "RISCVExtensionVersion{2, 0}",
                        "'C' (Compressed Instructions)">;
 def HasStdExtC : Predicate<"Subtarget->hasStdExtC()">,
                            AssemblerPredicate<(all_of FeatureStdExtC),
                            "'C' (Compressed Instructions)">;
 
 def FeatureStdExtZba
-    : SubtargetFeature<"experimental-zba", "HasStdExtZba", "true",
+    : SubtargetFeature<"experimental-zba", "StdExtZba",
+                       "RISCVExtensionVersion{1, 0}",
                        "'Zba' (Address calculation 'B' Instructions)">;
 def HasStdExtZba : Predicate<"Subtarget->hasStdExtZba()">,
                              AssemblerPredicate<(all_of FeatureStdExtZba),
@@ -73,63 +76,72 @@
 def NotHasStdExtZba : Predicate<"!Subtarget->hasStdExtZba()">;
 
 def FeatureStdExtZbb
-    : SubtargetFeature<"experimental-zbb", "HasStdExtZbb", "true",
+    : SubtargetFeature<"experimental-zbb", "StdExtZbb",
+                       "RISCVExtensionVersion{1, 0}",
                        "'Zbb' (Base 'B' Instructions)">;
 def HasStdExtZbb : Predicate<"Subtarget->hasStdExtZbb()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbb),
                              "'Zbb' (Base 'B' Instructions)">;
 
 def FeatureStdExtZbc
-    : SubtargetFeature<"experimental-zbc", "HasStdExtZbc", "true",
+    : SubtargetFeature<"experimental-zbc", "StdExtZbc",
+                       "RISCVExtensionVersion{1, 0}",
                        "'Zbc' (Carry-Less 'B' Instructions)">;
 def HasStdExtZbc : Predicate<"Subtarget->hasStdExtZbc()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbc),
                              "'Zbc' (Carry-Less 'B' Instructions)">;
 
 def FeatureStdExtZbe
-    : SubtargetFeature<"experimental-zbe", "HasStdExtZbe", "true",
+    : SubtargetFeature<"experimental-zbe", "StdExtZbe",
+                        "RISCVExtensionVersion{0, 93}",
                        "'Zbe' (Extract-Deposit 'B' Instructions)">;
 def HasStdExtZbe : Predicate<"Subtarget->hasStdExtZbe()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbe),
                              "'Zbe' (Extract-Deposit 'B' Instructions)">;
 
 def FeatureStdExtZbf
-    : SubtargetFeature<"experimental-zbf", "HasStdExtZbf", "true",
+    : SubtargetFeature<"experimental-zbf", "StdExtZbf",
+                       "RISCVExtensionVersion{0, 93}",
                        "'Zbf' (Bit-Field 'B' Instructions)">;
 def HasStdExtZbf : Predicate<"Subtarget->hasStdExtZbf()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbf),
                              "'Zbf' (Bit-Field 'B' Instructions)">;
 
 def FeatureStdExtZbm
-    : SubtargetFeature<"experimental-zbm", "HasStdExtZbm", "true",
+    : SubtargetFeature<"experimental-zbm", "StdExtZbm",
+                       "RISCVExtensionVersion{0, 93}",
                        "'Zbm' (Matrix 'B' Instructions)">;
 def HasStdExtZbm : Predicate<"Subtarget->hasStdExtZbm()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbm),
                              "'Zbm' (Matrix 'B' Instructions)">;
 
 def FeatureStdExtZbp
-    : SubtargetFeature<"experimental-zbp", "HasStdExtZbp", "true",
+    : SubtargetFeature<"experimental-zbp", "StdExtZbp",
+                       "RISCVExtensionVersion{0, 93}",
                        "'Zbp' (Permutation 'B' Instructions)">;
 def HasStdExtZbp : Predicate<"Subtarget->hasStdExtZbp()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbp),
                              "'Zbp' (Permutation 'B' Instructions)">;
 
 def FeatureStdExtZbr
-    : SubtargetFeature<"experimental-zbr", "HasStdExtZbr", "true",
+    : SubtargetFeature<"experimental-zbr", "StdExtZbr",
+                       "RISCVExtensionVersion{0, 93}",
                        "'Zbr' (Polynomial Reduction 'B' Instructions)">;
 def HasStdExtZbr : Predicate<"Subtarget->hasStdExtZbr()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbr),
                              "'Zbr' (Polynomial Reduction 'B' Instructions)">;
 
 def FeatureStdExtZbs
-    : SubtargetFeature<"experimental-zbs", "HasStdExtZbs", "true",
+    : SubtargetFeature<"experimental-zbs", "StdExtZbs",
+                       "RISCVExtensionVersion{1, 0}",
                        "'Zbs' (Single-Bit 'B' Instructions)">;
 def HasStdExtZbs : Predicate<"Subtarget->hasStdExtZbs()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbs),
                              "'Zbs' (Single-Bit 'B' Instructions)">;
 
 def FeatureStdExtZbt
-    : SubtargetFeature<"experimental-zbt", "HasStdExtZbt", "true",
+    : SubtargetFeature<"experimental-zbt", "StdExtZbt",
+                       "RISCVExtensionVersion{0, 93}",
                        "'Zbt' (Ternary 'B' Instructions)">;
 def HasStdExtZbt : Predicate<"Subtarget->hasStdExtZbt()">,
                              AssemblerPredicate<(all_of FeatureStdExtZbt),
@@ -151,22 +163,37 @@
                                       "RVC Hint Instructions">;
 
 def FeatureStdExtV
-    : SubtargetFeature<"experimental-v", "HasStdExtV", "true",
+    : SubtargetFeature<"experimental-v", "StdExtV",
+                       "RISCVExtensionVersion{0, 10}",
                        "'V' (Vector Instructions)">;
-def HasStdExtV : Predicate<"Subtarget->hasStdExtV()">,
-                           AssemblerPredicate<(all_of FeatureStdExtV),
-                           "'V' (Vector Instructions)">;
+def FeatureStdExtV0P7
+    : SubtargetFeature<"experimental-v0p7", "StdExtV",
+                       "RISCVExtensionVersion{0, 7}",
+                       "'V' (Vector Instructions)">;
+
+def HasStdExtV
+    : Predicate<"Subtarget->hasStdExtV()">,
+                 AssemblerPredicate<(any_of FeatureStdExtV, FeatureStdExtV0P7),
+                 "'V' (Vector Instructions)">;
 
 def HasVInstructions    : Predicate<"Subtarget->hasVInstructions()">;
 def HasVInstructionsAnyF : Predicate<"Subtarget->hasVInstructionsAnyF()">;
 
 def FeatureStdExtZvlsseg
-    : SubtargetFeature<"experimental-zvlsseg", "HasStdExtZvlsseg", "true",
+    : SubtargetFeature<"experimental-zvlsseg", "StdExtZvlsseg",
+                       "RISCVExtensionVersion{0, 10}",
                        "'Zvlsseg' (Vector segment load/store instructions)",
                        [FeatureStdExtV]>;
-def HasStdExtZvlsseg : Predicate<"Subtarget->hasStdExtZvlsseg()">,
-                                 AssemblerPredicate<(all_of FeatureStdExtZvlsseg),
-                                 "'Zvlsseg' (Vector segment load/store instructions)">;
+def FeatureStdExtZvlsseg0P7
+    : SubtargetFeature<"experimental-zvlsseg0p7", "StdExtZvlsseg",
+                       "RISCVExtensionVersion{0, 7}",
+                       "'Zvlsseg' (Vector segment load/store instructions)",
+                       [FeatureStdExtV0P7]>;
+
+def HasStdExtZvlsseg
+    : Predicate<"Subtarget->hasStdExtZvlsseg()">,
+                 AssemblerPredicate<(any_of FeatureStdExtZvlsseg, FeatureStdExtZvlsseg0P7),
+                 "'Zvlsseg' (Vector segment load/store instructions)">;
 
 def Feature64Bit
     : SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">;
@@ -181,7 +208,7 @@
 def RV64           : HwMode<"+64bit">;
 
 def FeatureRV32E
-    : SubtargetFeature<"e", "IsRV32E", "true",
+    : SubtargetFeature<"e", "StdExtE", "RISCVExtensionVersion{1, 9}",
                        "Implements RV32E (provides 16 rather than 32 GPRs)">;
 def IsRV32E : Predicate<"Subtarget->isRV32E()">,
                         AssemblerPredicate<(all_of FeatureRV32E)>;
Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
===================================================================
--- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -2153,9 +2153,10 @@
     }
     auto &ISAInfo = *ParseResult;
 
-    for (auto Feature : RISCVFeatureKV)
-      if (ISAInfo->hasExtension(Feature.Key))
+    for (auto Feature : RISCVFeatureKV) {
+      if (ISAInfo->hasExtensionWithVersion(Feature.Key))
         setFeatureBits(Feature.Value, Feature.Key);
+    }
 
     if (ISAInfo->getXLen() == 32)
       clearFeatureBits(RISCV::Feature64Bit, "64bit");
Index: llvm/lib/Support/RISCVISAInfo.cpp
===================================================================
--- llvm/lib/Support/RISCVISAInfo.cpp
+++ llvm/lib/Support/RISCVISAInfo.cpp
@@ -22,11 +22,6 @@
 using namespace llvm;
 
 namespace {
-/// Represents the major and version number components of a RISC-V extension
-struct RISCVExtensionVersion {
-  unsigned Major;
-  unsigned Minor;
-};
 
 struct RISCVSupportedExtension {
   const char *Name;
@@ -50,6 +45,7 @@
 
 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
     {"v", RISCVExtensionVersion{0, 10}},
+    {"v", RISCVExtensionVersion{0, 7}},
     {"zba", RISCVExtensionVersion{1, 0}},
     {"zbb", RISCVExtensionVersion{1, 0}},
     {"zbc", RISCVExtensionVersion{1, 0}},
@@ -62,11 +58,17 @@
     {"zbt", RISCVExtensionVersion{0, 93}},
 
     {"zvlsseg", RISCVExtensionVersion{0, 10}},
+    {"zvlsseg", RISCVExtensionVersion{0, 7}},
 
     {"zfhmin", RISCVExtensionVersion{0, 1}},
     {"zfh", RISCVExtensionVersion{0, 1}},
 };
 
+static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
+                                 unsigned &Minor, unsigned &ConsumeLength,
+                                 bool EnableExperimentalExtension,
+                                 bool ExperimentalExtensionVersionCheck);
+
 static bool stripExperimentalPrefix(StringRef &Ext) {
   return Ext.consume_front("experimental-");
 }
@@ -120,8 +122,8 @@
                                 unsigned MinorVersion) {
   RISCVExtensionInfo Ext;
   Ext.ExtName = ExtName.str();
-  Ext.MajorVersion = MajorVersion;
-  Ext.MinorVersion = MinorVersion;
+  Ext.Version.Major = MajorVersion;
+  Ext.Version.Minor = MinorVersion;
   Exts[ExtName.str()] = Ext;
 }
 
@@ -149,22 +151,46 @@
   return StringRef();
 }
 
-static Optional<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) {
-  auto ExtIterator =
-      llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext));
-  if (ExtIterator == std::end(SupportedExperimentalExtensions))
-    return None;
+static std::vector<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) {
+  std::vector<RISCVExtensionVersion> Result;
 
-  return ExtIterator->Version;
+  for (auto& Extension : SupportedExperimentalExtensions) {
+    if (Extension.Name == Ext)
+      Result.push_back(Extension.Version);
+  }
+
+  return Result;
 }
 
-bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
-  bool IsExperimental = stripExperimentalPrefix(Ext);
+Optional<RISCVExtensionInfo>
+RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
+  stripExperimentalPrefix(Ext);
 
-  if (IsExperimental)
-    return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
-  else
-    return llvm::any_of(SupportedExtensions, FindByName(Ext));
+  auto Pos = findFirstNonVersionCharacter(Ext) + 1;
+  StringRef Name(Ext.substr(0, Pos));
+  StringRef Vers(Ext.substr(Pos));
+
+  unsigned Major, Minor, ConsumeLength;
+  if (Vers.empty()) {
+    auto Version = findDefaultVersion(Name);
+    if (!Version)
+      return None;
+
+    Major = Version->Major;
+    Minor = Version->Minor;
+
+  } else if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
+                                   true, false)) {
+    // Not all features is related to ISA extension, like `relax` or
+    // `save-restore`, skip those feature.
+    consumeError(std::move(E));
+    return None;
+  }
+
+  if (!isSupportedExtension(Name, Major, Minor))
+    return None;
+
+  return RISCVExtensionInfo{Name.str(), Major, Minor};
 }
 
 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
@@ -191,6 +217,20 @@
   return Exts.count(Ext.str()) != 0;
 }
 
+bool RISCVISAInfo::hasExtensionWithVersion(StringRef Ext) const{
+  auto Info = isSupportedExtensionFeature(Ext);
+  if(!Info)
+    return false;
+
+  auto ExtInfoIt = Exts.find(Info->ExtName);
+
+  if (ExtInfoIt == Exts.end())
+    return false;
+
+  return ExtInfoIt->second.Version.Major == Info->Version.Major &&
+         ExtInfoIt->second.Version.Minor == Info->Version.Minor;
+}
+
 // Get the rank for single-letter extension, lower value meaning higher
 // priority.
 static int singleLetterExtensionRank(char Ext) {
@@ -273,22 +313,36 @@
   return LHS < RHS;
 }
 
-void RISCVISAInfo::toFeatures(
-    std::vector<StringRef> &Features,
-    std::function<StringRef(const Twine &)> StrAlloc) const {
+static std::string addVersionSuffix(StringRef Suffix,
+                                    StringRef ExtName, unsigned Major,
+                                    unsigned Minor) {
+  if (auto DefaultVersion = findDefaultVersion(ExtName))
+    if (DefaultVersion->Major == Major && DefaultVersion->Minor == Minor)
+      return (Twine(Suffix) + ExtName).str();
+
+  return (Suffix + ExtName + Twine(Major) + "p" + Twine(Minor)).str();
+}
+
+void RISCVISAInfo::toFeatures(std::vector<std::string> &Features) const {
+
   for (auto &Ext : Exts) {
     StringRef ExtName = Ext.first;
+    auto Extension = Ext.second;
+    unsigned Major = Ext.second.Version.Major;
+    unsigned Minor = Ext.second.Version.Minor;
 
     if (ExtName == "i")
       continue;
 
     if (ExtName == "zvlsseg") {
-      Features.push_back("+experimental-v");
-      Features.push_back("+experimental-zvlsseg");
-    } else if (isExperimentalExtension(ExtName)) {
-      Features.push_back(StrAlloc("+experimental-" + ExtName));
+      Features.push_back(addVersionSuffix("experimental-", "v", Major, Minor));
+      Features.push_back(
+          addVersionSuffix("experimental-", "zvlsseg", Major, Minor));
+    } else if (isExperimentalExtension(ExtName).size()) {
+      Features.push_back(
+          addVersionSuffix("experimental-", ExtName, Major, Minor));
     } else {
-      Features.push_back(StrAlloc("+" + ExtName));
+      Features.push_back(addVersionSuffix("", ExtName, Major, Minor));
     }
   }
 }
@@ -346,7 +400,8 @@
   }
 
   // If experimental extension, require use of current version number number
-  if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
+  auto ExperimentalExtension = isExperimentalExtension(Ext);
+  if (ExperimentalExtension.size()) {
     if (!EnableExperimentalExtension) {
       std::string Error = "requires '-menable-experimental-extensions' for "
                           "experimental extension '" +
@@ -362,18 +417,27 @@
       return createStringError(errc::invalid_argument, Error);
     }
 
-    auto SupportedVers = *ExperimentalExtension;
-    if (ExperimentalExtensionVersionCheck &&
-        (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
-      std::string Error = "unsupported version number " + MajorStr.str();
-      if (!MinorStr.empty())
-        Error += "." + MinorStr.str();
-      Error += " for experimental extension '" + Ext.str() +
-               "'(this compiler supports " + utostr(SupportedVers.Major) + "." +
-               utostr(SupportedVers.Minor) + ")";
-      return createStringError(errc::invalid_argument, Error);
+    for (auto Version : ExperimentalExtension) {
+      if (Major == Version.Major && Minor == Version.Minor)
+        return Error::success();
     }
-    return Error::success();
+
+    if (!ExperimentalExtensionVersionCheck)
+      return Error::success();
+
+    std::string Error = "unsupported version number " + MajorStr.str();
+    if (!MinorStr.empty())
+      Error += "." + MinorStr.str();
+    Error += " for experimental extension '" + Ext.str() +
+             "'(this compiler supports ";
+
+    ListSeparator LS;
+    for (auto Version : ExperimentalExtension) {
+      Error += LS;
+      Error += (utostr(Version.Major) + "." + utostr(Version.Minor));
+    }
+    Error += ")";
+    return createStringError(errc::invalid_argument, Error);
   }
 
   // Exception rule for `g`, we don't have clear version scheme for that on
@@ -409,27 +473,19 @@
 
   for (auto &Feature : Features) {
     StringRef ExtName = Feature;
-    bool Experimental = false;
     assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
     bool Add = ExtName[0] == '+';
     ExtName = ExtName.drop_front(1); // Drop '+' or '-'
-    Experimental = stripExperimentalPrefix(ExtName);
-    auto ExtensionInfos = Experimental
-                              ? makeArrayRef(SupportedExperimentalExtensions)
-                              : makeArrayRef(SupportedExtensions);
-    auto ExtensionInfoIterator =
-        llvm::find_if(ExtensionInfos, FindByName(ExtName));
 
-    // Not all features is related to ISA extension, like `relax` or
-    // `save-restore`, skip those feature.
-    if (ExtensionInfoIterator == ExtensionInfos.end())
+    auto Info = isSupportedExtensionFeature(ExtName);
+    if(!Info)
       continue;
 
     if (Add)
-      ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
-                            ExtensionInfoIterator->Version.Minor);
+      ISAInfo->addExtension(Info->ExtName, Info->Version.Major,
+                            Info->Version.Minor);
     else
-      ISAInfo->Exts.erase(ExtName.str());
+      ISAInfo->Exts.erase(Info->ExtName);
   }
 
   ISAInfo->updateImplication();
@@ -443,7 +499,8 @@
 
 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
-                              bool ExperimentalExtensionVersionCheck) {
+                              bool ExperimentalExtensionVersionCheck,
+                              bool IgnoreUnknownExtension) {
   // RISC-V ISA strings must be lowercase.
   if (llvm::any_of(Arch, isupper)) {
     return createStringError(errc::invalid_argument,
@@ -544,9 +601,9 @@
             "standard user-level extension not given in canonical order '%c'",
             C);
       }
-
-      return createStringError(errc::invalid_argument,
-                               "invalid standard user-level extension '%c'", C);
+      if (!IgnoreUnknownExtension)
+        return createStringError(errc::invalid_argument,
+                                 "invalid standard user-level extension '%c'", C);
     }
 
     // Move to next char to prevent repeated letter.
@@ -558,18 +615,23 @@
       Next = std::string(std::next(I), E);
     if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor,
                                      ConsumeLength, EnableExperimentalExtension,
-                                     ExperimentalExtensionVersionCheck))
-      return std::move(E);
-
-    // The order is OK, then push it into features.
-    // TODO: Use version number when setting target features
-    // Currently LLVM supports only "mafdcbv".
-    StringRef SupportedStandardExtension = "mafdcbv";
-    if (SupportedStandardExtension.find(C) == StringRef::npos)
-      return createStringError(errc::invalid_argument,
-                               "unsupported standard user-level extension '%c'",
-                               C);
-    ISAInfo->addExtension(std::string(1, C), Major, Minor);
+                                     ExperimentalExtensionVersionCheck)) {
+      if (IgnoreUnknownExtension)
+        consumeError(std::move(E));
+      else
+        return std::move(E);
+    } else {
+      // The order is OK, then push it into features.
+      // TODO: Use version number when setting target features
+      // Currently LLVM supports only "mafdcbv".
+      StringRef SupportedStandardExtension = "mafdcbv";
+      if (SupportedStandardExtension.find(C) != StringRef::npos)
+        ISAInfo->addExtension(std::string(1, C), Major, Minor);
+      else if (!IgnoreUnknownExtension)
+          return createStringError(errc::invalid_argument,
+                                   "unsupported standard user-level extension '%c'",
+                                   C);
+    }
 
     // Consume full extension name and version, including any optional '_'
     // between this extension and the next
@@ -724,10 +786,9 @@
   for (auto &Ext : Exts) {
     auto I = llvm::lower_bound(ImpliedExts, Ext.first);
     if (I != std::end(ImpliedExts) && I->Name == Ext.first) {
-      for (auto &ImpliedExt : I->Exts) {
-        auto Version = findDefaultVersion(ImpliedExt);
-        addExtension(ImpliedExt, Version->Major, Version->Minor);
-      }
+      for (auto &ImpliedExt : I->Exts)
+        addExtension(ImpliedExt,
+                     Ext.second.Version.Major, Ext.second.Version.Minor);
     }
   }
 }
@@ -752,7 +813,8 @@
     StringRef ExtName = Ext.first;
     auto ExtInfo = Ext.second;
     Arch << LS << ExtName;
-    Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
+    Arch << ExtInfo.Version.Major
+         << "p" << ExtInfo.Version.Minor;
   }
 
   return Arch.str();
Index: llvm/lib/Object/ELFObjectFile.cpp
===================================================================
--- llvm/lib/Object/ELFObjectFile.cpp
+++ llvm/lib/Object/ELFObjectFile.cpp
@@ -26,6 +26,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/RISCVAttributeParser.h"
 #include "llvm/Support/RISCVAttributes.h"
+#include "llvm/Support/RISCVISAInfo.h"
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
@@ -309,35 +310,27 @@
     // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)*
     // Version string pattern is (major)p(minor). Major and minor are optional.
     // For example, a version number could be 2p0, 2, or p92.
-    StringRef Arch = Attr.getValue();
-    if (Arch.consume_front("rv32"))
+    auto ParseResult =
+        llvm::RISCVISAInfo::parseArchString(Attr.getValue(), true, true, true);
+    if (!ParseResult)
+      return Features;
+
+    auto &ISAInfo = *ParseResult;
+
+    if (ISAInfo->getXLen() == 32)
       Features.AddFeature("64bit", false);
-    else if (Arch.consume_front("rv64"))
+    else if (ISAInfo->getXLen() == 64)
       Features.AddFeature("64bit");
 
-    while (!Arch.empty()) {
-      switch (Arch[0]) {
-      default:
-        break; // Ignore unexpected features.
-      case 'i':
-        Features.AddFeature("e", false);
-        break;
-      case 'd':
-        Features.AddFeature("f"); // D-ext will imply F-ext.
-        LLVM_FALLTHROUGH;
-      case 'e':
-      case 'm':
-      case 'a':
-      case 'f':
-      case 'c':
-        Features.AddFeature(Arch.take_front());
-        break;
-      }
-
-      // FIXME: Handle version numbers.
-      Arch = Arch.drop_until([](char c) { return c == '_' || c == '\0'; });
-      Arch = Arch.drop_while([](char c) { return c == '_'; });
+    if (PlatformFlags & ELF::EF_RISCV_RVC) {
+      Features.AddFeature("c", false);
     }
+
+    std::vector<std::string> ToFeatures;
+    ISAInfo->toFeatures(ToFeatures);
+
+    for (const auto &Feature : ToFeatures)
+      Features.AddFeature(Feature);
   }
 
   return Features;
Index: llvm/include/llvm/Support/RISCVISAInfo.h
===================================================================
--- llvm/include/llvm/Support/RISCVISAInfo.h
+++ llvm/include/llvm/Support/RISCVISAInfo.h
@@ -19,10 +19,29 @@
 #include <vector>
 
 namespace llvm {
+
+/// Represents the major and version number components of a RISC-V extension
+struct RISCVExtensionVersion {
+  unsigned Major;
+  unsigned Minor;
+
+  bool operator==(const RISCVExtensionVersion &Version) const {
+    return Major == Version.Major && Minor == Version.Minor;
+  }
+
+  bool operator!=(const RISCVExtensionVersion &Version) const {
+    return !operator==(Version);
+  }
+
+  bool operator<(const RISCVExtensionVersion &Version) const {
+    return (Major < Version.Major) ||
+           (Major == Version.Major && Minor < Version.Minor);
+  }
+};
+
 struct RISCVExtensionInfo {
   std::string ExtName;
-  unsigned MajorVersion;
-  unsigned MinorVersion;
+  RISCVExtensionVersion Version;
 };
 
 class RISCVISAInfo {
@@ -47,15 +66,15 @@
   /// Parse RISCV ISA info from arch string.
   static llvm::Expected<std::unique_ptr<RISCVISAInfo>>
   parseArchString(StringRef Arch, bool EnableExperimentalExtension,
-                  bool ExperimentalExtensionVersionCheck = true);
+                  bool ExperimentalExtensionVersionCheck = true,
+                  bool IgnoreUnknownExtension = false);
 
   /// Parse RISCV ISA info from feature vector.
   static llvm::Expected<std::unique_ptr<RISCVISAInfo>>
   parseFeatures(unsigned XLen, const std::vector<std::string> &Features);
 
   /// Convert RISCV ISA info to a feature vector.
-  void toFeatures(std::vector<StringRef> &Features,
-                  std::function<StringRef(const Twine &)> StrAlloc) const;
+  void toFeatures(std::vector<std::string> &Features) const;
 
   const OrderedExtensionMap &getExtensions() const { return Exts; };
 
@@ -63,9 +82,11 @@
   unsigned getFLen() const { return FLen; };
 
   bool hasExtension(StringRef Ext) const;
+  bool hasExtensionWithVersion(StringRef Ext) const;
   std::string toString() const;
 
-  static bool isSupportedExtensionFeature(StringRef Ext);
+  static Optional<RISCVExtensionInfo>
+    isSupportedExtensionFeature(StringRef Ext);
   static bool isSupportedExtension(StringRef Ext);
   static bool isSupportedExtension(StringRef Ext, unsigned MajorVersion,
                                    unsigned MinorVersion);
Index: clang/test/Driver/riscv-arch.c
===================================================================
--- clang/test/Driver/riscv-arch.c
+++ clang/test/Driver/riscv-arch.c
@@ -453,3 +453,7 @@
 // RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg0p10 -menable-experimental-extensions -### %s -c 2>&1 | \
 // RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVLSSEG-GOODVERS %s
 // RV32-EXPERIMENTAL-ZVLSSEG-GOODVERS: "-target-feature" "+experimental-zvlsseg"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p7 -menable-experimental-extensions -### %s -c 2>&1 | \
+// RUN:   FileCheck -check-prefix=RV32-EXPERIMENTAL-V07 %s
+// RV32-EXPERIMENTAL-V07: "-target-feature" "+experimental-v0p7"
\ No newline at end of file
Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -41,8 +41,12 @@
     return false;
   }
 
-  (*ISAInfo)->toFeatures(
-      Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); });
+  std::vector<std::string> ToFeatures;
+  (*ISAInfo)->toFeatures(ToFeatures);
+
+  for (const auto &Feature : ToFeatures)
+    Features.push_back(Args.MakeArgString("+" + Feature));
+
   return true;
 }
 
Index: clang/lib/Basic/Targets/RISCV.cpp
===================================================================
--- clang/lib/Basic/Targets/RISCV.cpp
+++ clang/lib/Basic/Targets/RISCV.cpp
@@ -150,7 +150,8 @@
     auto ExtName = Extension.first;
     auto ExtInfo = Extension.second;
     unsigned Version =
-        (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
+        (ExtInfo.Version.Major * 1000000) +
+        (ExtInfo.Version.Minor * 1000);
 
     Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
   }
@@ -223,10 +224,7 @@
   if (Result.hasValue())
     return Result.getValue();
 
-  if (ISAInfo->isSupportedExtensionFeature(Feature))
-    return ISAInfo->hasExtension(Feature);
-
-  return false;
+  return ISAInfo->hasExtensionWithVersion(Feature);
 }
 
 /// Perform initialization based on the user configured set of features.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to