[RISCV] Support -target-abi at the MC layer and for codegen
authorAlex Bradbury <asb@lowrisc.org>
Sat, 9 Mar 2019 09:28:06 +0000 (09:28 +0000)
committerAlex Bradbury <asb@lowrisc.org>
Sat, 9 Mar 2019 09:28:06 +0000 (09:28 +0000)
This patch adds proper handling of -target-abi, as accepted by llvm-mc and
llc. Lowering (codegen) for the hard-float ABIs will follow in a subsequent
patch. However, this patch does add MC layer support for the hard float and
RVE ABIs (emission of the appropriate ELF flags
https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#-file-header).

ABI parsing must be shared between codegen and the MC layer, so we add
computeTargetABI to RISCVUtils. A warning will be printed if an invalid or
unrecognized ABI is given.

Differential Revision: https://reviews.llvm.org/D59023

llvm-svn: 355771

14 files changed:
llvm/lib/Target/RISCV/MCTargetDesc/LLVMBuild.txt
llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVSubtarget.cpp
llvm/lib/Target/RISCV/RISCVSubtarget.h
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
llvm/test/CodeGen/RISCV/target-abi-invalid.ll [new file with mode: 0644]
llvm/test/CodeGen/RISCV/target-abi-valid.ll [new file with mode: 0644]
llvm/test/MC/RISCV/target-abi-invalid.s [new file with mode: 0644]
llvm/test/MC/RISCV/target-abi-valid.s [new file with mode: 0644]

index b8952c7..39458d6 100644 (file)
@@ -18,5 +18,5 @@
 type = Library
 name = RISCVDesc
 parent = RISCV
-required_libraries = MC RISCVAsmPrinter RISCVInfo Support
+required_libraries = MC RISCVAsmPrinter RISCVInfo RISCVUtils Support
 add_to_library_groups = RISCV
index c21cd7f..af4ee41 100644 (file)
@@ -356,5 +356,5 @@ MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
                                           const MCTargetOptions &Options) {
   const Triple &TT = STI.getTargetTriple();
   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
-  return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit());
+  return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);
 }
index ff3b5a5..54d5848 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "MCTargetDesc/RISCVFixupKinds.h"
 #include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "Utils/RISCVBaseInfo.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCFixupKindInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
@@ -25,11 +26,17 @@ class RISCVAsmBackend : public MCAsmBackend {
   uint8_t OSABI;
   bool Is64Bit;
   bool ForceRelocs = false;
+  const MCTargetOptions &TargetOptions;
+  RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
 
 public:
-  RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit)
-      : MCAsmBackend(support::little), STI(STI), OSABI(OSABI),
-        Is64Bit(Is64Bit) {}
+  RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
+                  const MCTargetOptions &Options)
+      : MCAsmBackend(support::little), STI(STI), OSABI(OSABI), Is64Bit(Is64Bit),
+        TargetOptions(Options) {
+    TargetABI = RISCVABI::computeTargetABI(
+        STI.getTargetTriple(), STI.getFeatureBits(), Options.getABIName());
+  }
   ~RISCVAsmBackend() override {}
 
   void setForceRelocs() { ForceRelocs = true; }
@@ -118,6 +125,9 @@ public:
 
 
   bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
+
+  const MCTargetOptions &getTargetOptions() const { return TargetOptions; }
+  RISCVABI::ABI getTargetABI() const { return TargetABI; }
 };
 }
 
index f7eae0b..40fa195 100644 (file)
@@ -11,7 +11,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "RISCVELFStreamer.h"
+#include "MCTargetDesc/RISCVAsmBackend.h"
 #include "RISCVMCTargetDesc.h"
+#include "Utils/RISCVBaseInfo.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 
@@ -22,14 +24,35 @@ RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S,
                                                const MCSubtargetInfo &STI)
     : RISCVTargetStreamer(S) {
   MCAssembler &MCA = getStreamer().getAssembler();
-
   const FeatureBitset &Features = STI.getFeatureBits();
+  auto &MAB = static_cast<RISCVAsmBackend &>(MCA.getBackend());
+  RISCVABI::ABI ABI = MAB.getTargetABI();
+  assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
 
   unsigned EFlags = MCA.getELFHeaderEFlags();
 
   if (Features[RISCV::FeatureStdExtC])
     EFlags |= ELF::EF_RISCV_RVC;
 
+  switch (ABI) {
+  case RISCVABI::ABI_ILP32:
+  case RISCVABI::ABI_LP64:
+    break;
+  case RISCVABI::ABI_ILP32F:
+  case RISCVABI::ABI_LP64F:
+    EFlags |= ELF::EF_RISCV_FLOAT_ABI_SINGLE;
+    break;
+  case RISCVABI::ABI_ILP32D:
+  case RISCVABI::ABI_LP64D:
+    EFlags |= ELF::EF_RISCV_FLOAT_ABI_DOUBLE;
+    break;
+  case RISCVABI::ABI_ILP32E:
+    EFlags |= ELF::EF_RISCV_RVE;
+    break;
+  case RISCVABI::ABI_Unknown:
+    llvm_unreachable("Improperly initialised target ABI");
+  }
+
   MCA.setELFHeaderEFlags(EFlags);
 }
 
index f46a21a..d844a83 100644 (file)
@@ -42,6 +42,12 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
                                          const RISCVSubtarget &STI)
     : TargetLowering(TM), Subtarget(STI) {
 
+  RISCVABI::ABI ABI = Subtarget.getTargetABI();
+  assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
+
+  if (ABI != RISCVABI::ABI_ILP32 && ABI != RISCVABI::ABI_LP64)
+    report_fatal_error("Don't know how to lower this ABI");
+
   MVT XLenVT = Subtarget.getXLenVT();
 
   // Set up the register classes.
index 09ac7fc..0c7355c 100644 (file)
@@ -25,10 +25,10 @@ using namespace llvm;
 
 void RISCVSubtarget::anchor() {}
 
-RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(StringRef CPU,
-                                                                StringRef FS,
-                                                                bool Is64Bit) {
+RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(
+    const Triple &TT, StringRef CPU, StringRef FS, StringRef ABIName) {
   // Determine default and user-specified characteristics
+  bool Is64Bit = TT.isArch64Bit();
   std::string CPUName = CPU;
   if (CPUName.empty())
     CPUName = Is64Bit ? "generic-rv64" : "generic-rv32";
@@ -37,11 +37,13 @@ RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(StringRef CPU,
     XLenVT = MVT::i64;
     XLen = 64;
   }
+
+  TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName);
   return *this;
 }
 
 RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
-                               const TargetMachine &TM)
+                               StringRef ABIName, const TargetMachine &TM)
     : RISCVGenSubtargetInfo(TT, CPU, FS),
-      FrameLowering(initializeSubtargetDependencies(CPU, FS, TT.isArch64Bit())),
+      FrameLowering(initializeSubtargetDependencies(TT, CPU, FS, ABIName)),
       InstrInfo(), RegInfo(getHwMode()), TLInfo(TM, *this) {}
index 0373d54..6c10ee4 100644 (file)
@@ -16,6 +16,7 @@
 #include "RISCVFrameLowering.h"
 #include "RISCVISelLowering.h"
 #include "RISCVInstrInfo.h"
+#include "Utils/RISCVBaseInfo.h"
 #include "llvm/CodeGen/SelectionDAGTargetInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/DataLayout.h"
@@ -38,6 +39,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   bool EnableLinkerRelax = false;
   unsigned XLen = 32;
   MVT XLenVT = MVT::i32;
+  RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
   RISCVFrameLowering FrameLowering;
   RISCVInstrInfo InstrInfo;
   RISCVRegisterInfo RegInfo;
@@ -46,13 +48,14 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
 
   /// Initializes using the passed in CPU and feature strings so that we can
   /// use initializer lists for subtarget initialization.
-  RISCVSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS,
-                                                  bool Is64Bit);
+  RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
+                                                  StringRef CPU, StringRef FS,
+                                                  StringRef ABIName);
 
 public:
   // Initializes the data members to match that of the specified triple.
   RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
-                 const TargetMachine &TM);
+                 StringRef ABIName, const TargetMachine &TM);
 
   // Parses features string setting specified subtarget options. The
   // definition of this function is auto-generated by tblgen.
@@ -80,6 +83,7 @@ public:
   bool enableLinkerRelax() const { return EnableLinkerRelax; }
   MVT getXLenVT() const { return XLenVT; }
   unsigned getXLen() const { return XLen; }
+  RISCVABI::ABI getTargetABI() const { return TargetABI; }
 };
 } // End llvm namespace
 
index 0603502..519dfb6 100644 (file)
@@ -56,7 +56,7 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
                         getEffectiveRelocModel(TT, RM),
                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
       TLOF(make_unique<RISCVELFTargetObjectFile>()),
-      Subtarget(TT, CPU, FS, *this) {
+      Subtarget(TT, CPU, FS, Options.MCOptions.getABIName(), *this) {
   initAsmInfo();
 }
 
index 964af1f..bb967cb 100644 (file)
@@ -1,9 +1,60 @@
 #include "RISCVBaseInfo.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
 namespace RISCVSysReg {
 #define GET_SysRegsList_IMPL
 #include "RISCVGenSystemOperands.inc"
 } // namespace RISCVSysReg
+
+namespace RISCVABI {
+ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
+                     StringRef ABIName) {
+  auto TargetABI = StringSwitch<ABI>(ABIName)
+                       .Case("ilp32", ABI_ILP32)
+                       .Case("ilp32f", ABI_ILP32F)
+                       .Case("ilp32d", ABI_ILP32D)
+                       .Case("ilp32e", ABI_ILP32E)
+                       .Case("lp64", ABI_LP64)
+                       .Case("lp64f", ABI_LP64F)
+                       .Case("lp64d", ABI_LP64D)
+                       .Default(ABI_Unknown);
+
+  if (!ABIName.empty() && TargetABI == ABI_Unknown) {
+    errs()
+        << "'" << ABIName
+        << "' is not a recognized ABI for this target (ignoring target-abi)\n";
+  } else if (ABIName.startswith("ilp32") && TT.isArch64Bit()) {
+    errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "
+              "target-abi)\n";
+    TargetABI = ABI_Unknown;
+  } else if (ABIName.startswith("lp64") && !TT.isArch64Bit()) {
+    errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
+              "target-abi)\n";
+    TargetABI = ABI_Unknown;
+  } else if (ABIName.endswith("f") && !FeatureBits[RISCV::FeatureStdExtF]) {
+    errs() << "Hard-float 'f' ABI can't be used for a target that "
+              "doesn't support the F instruction set extension (ignoring "
+              "target-abi)\n";
+    TargetABI = ABI_Unknown;
+  } else if (ABIName.endswith("d") && !FeatureBits[RISCV::FeatureStdExtD]) {
+    errs() << "Hard-float 'd' ABI can't be used for a target that "
+              "doesn't support the D instruction set extension (ignoring "
+              "target-abi)\n";
+    TargetABI = ABI_Unknown;
+  }
+
+  // For now, default to the ilp32/lp64 if no explicit ABI is given or an
+  // invalid/unrecognised string is given. In the future, it might be worth
+  // changing this to default to ilp32f/lp64f and ilp32d/lp64d when hardware
+  // support for floating point is present.
+  if (TargetABI == ABI_Unknown) {
+    TargetABI = TT.isArch64Bit() ? ABI_LP64 : ABI_ILP32;
+  }
+
+  return TargetABI;
+}
+} // namespace RISCVABI
 } // namespace llvm
index 49cae3a..4ace9dd 100644 (file)
@@ -152,6 +152,26 @@ struct SysReg {
 #include "RISCVGenSystemOperands.inc"
 } // end namespace RISCVSysReg
 
+namespace RISCVABI {
+
+enum ABI {
+  ABI_ILP32,
+  ABI_ILP32F,
+  ABI_ILP32D,
+  ABI_ILP32E,
+  ABI_LP64,
+  ABI_LP64F,
+  ABI_LP64D,
+  ABI_Unknown
+};
+
+// Returns the target ABI, or else a StringError if the requested ABIName is
+// not supported for the given TT and FeatureBits combination.
+ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
+                     StringRef ABIName);
+
+} // namespace RISCVABI
+
 } // namespace llvm
 
 #endif
diff --git a/llvm/test/CodeGen/RISCV/target-abi-invalid.ll b/llvm/test/CodeGen/RISCV/target-abi-invalid.ll
new file mode 100644 (file)
index 0000000..41c08f1
--- /dev/null
@@ -0,0 +1,58 @@
+; RUN: llc -mtriple=riscv32 -target-abi foo < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32I-FOO %s
+; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32foof < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32IF-ILP32FOOF %s
+
+; RV32I-FOO: 'foo' is not a recognized ABI for this target (ignoring target-abi)
+; RV32IF-ILP32FOOF: 'ilp32foof' is not a recognized ABI for this target (ignoring target-abi)
+
+; RUN: llc -mtriple=riscv64 -target-abi ilp32 < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64I-ILP32 %s
+; RUN: llc -mtriple=riscv64 -mattr=+f -target-abi ilp32f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64IF-ILP32F %s
+; RUN: llc -mtriple=riscv64 -mattr=+d -target-abi ilp32d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64IFD-ILP32D %s
+; RUN: llc -mtriple=riscv64 -target-abi ilp32e < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64I-ILP32E %s
+
+; RV64I-ILP32: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+; RV64IF-ILP32F: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+; RV64IFD-ILP32D: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+; RV64I-ILP32E: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+
+; RUN: llc -mtriple=riscv32 -target-abi lp64 < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32I-LP64 %s
+; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi lp64f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32IF-LP64F %s
+; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi lp64d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32IFD-LP64D %s
+
+; RV32I-LP64: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+; RV32IF-LP64F: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+; RV32IFD-LP64D: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+
+; RUN: llc -mtriple=riscv32 -target-abi ilp32f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32I-ILP32F %s
+; RUN: llc -mtriple=riscv64 -target-abi lp64f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64I-LP64F %s
+
+; RV32I-ILP32F: Hard-float 'f' ABI can't be used for a target that doesn't support the F instruction set extension (ignoring target-abi)
+; RV64I-LP64F: Hard-float 'f' ABI can't be used for a target that doesn't support the F instruction set extension (ignoring target-abi)
+
+; RUN: llc -mtriple=riscv32 -target-abi ilp32d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32I-ILP32D %s
+; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV32IF-ILP32D %s
+; RUN: llc -mtriple=riscv64 -target-abi lp64d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64I-LP64D %s
+; RUN: llc -mtriple=riscv64 -mattr=+f -target-abi lp64d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64IF-LP64D %s
+
+; RV32I-ILP32D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+; RV32IF-ILP32D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+; RV64I-LP64D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+; RV64IF-LP64D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+
+define void @nothing() nounwind {
+  ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/target-abi-valid.ll b/llvm/test/CodeGen/RISCV/target-abi-valid.ll
new file mode 100644 (file)
index 0000000..2223345
--- /dev/null
@@ -0,0 +1,40 @@
+; RUN: llc -mtriple=riscv32 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+; RUN: llc -mtriple=riscv32 -target-abi ilp32 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi ilp32 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+; RUN: llc -mtriple=riscv64 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+; RUN: llc -mtriple=riscv64 -target-abi lp64 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+; RUN: llc -mtriple=riscv64 -mattr=+f -target-abi lp64 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+; RUN: llc -mtriple=riscv64 -mattr=+d -target-abi lp64 < %s \
+; RUN:   | FileCheck -check-prefix=CHECK-IMP %s
+
+define void @nothing() nounwind {
+; CHECK-IMP-LABEL: nothing:
+; CHECK-IMP:       # %bb.0:
+; CHECK-IMP-NEXT:    ret
+  ret void
+}
+
+; RUN: not llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=CHECK-UNIMP %s
+; RUN: not llc -mtriple=riscv32 -mattr=+d -target-abi ilp32f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=CHECK-UNIMP %s
+; RUN: not llc -mtriple=riscv32 -mattr=+d -target-abi ilp32d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=CHECK-UNIMP %s
+; RUN: not llc -mtriple=riscv32 -target-abi ilp32e < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=CHECK-UNIMP %s
+; RUN: not llc -mtriple=riscv64 -mattr=+f -target-abi lp64f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=CHECK-UNIMP %s
+; RUN: not llc -mtriple=riscv64 -mattr=+d -target-abi lp64f < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=CHECK-UNIMP %s
+; RUN: not llc -mtriple=riscv64 -mattr=+d -target-abi lp64d < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=CHECK-UNIMP %s
+
+; CHECK-UNIMP: LLVM ERROR: Don't know how to lower this ABI
diff --git a/llvm/test/MC/RISCV/target-abi-invalid.s b/llvm/test/MC/RISCV/target-abi-invalid.s
new file mode 100644 (file)
index 0000000..16ed941
--- /dev/null
@@ -0,0 +1,56 @@
+# RUN: llvm-mc -triple=riscv32 -target-abi foo < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32I-FOO %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+f -target-abi ilp32foof < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32IF-ILP32FOOF %s
+
+# RV32I-FOO: 'foo' is not a recognized ABI for this target (ignoring target-abi)
+# RV32IF-ILP32FOOF: 'ilp32foof' is not a recognized ABI for this target (ignoring target-abi)
+
+# RUN: llvm-mc -triple=riscv64 -target-abi ilp32 < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64I-ILP32 %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+f -target-abi ilp32f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64IF-ILP32F %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+d -target-abi ilp32d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64IFD-ILP32D %s
+# RUN: llvm-mc -triple=riscv64 -target-abi ilp32e < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64I-ILP32E %s
+
+# RV64I-ILP32: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+# RV64IF-ILP32F: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+# RV64IFD-ILP32D: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+# RV64I-ILP32E: 32-bit ABIs are not supported for 64-bit targets (ignoring target-abi)
+
+# RUN: llvm-mc -triple=riscv32 -target-abi lp64 < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32I-LP64 %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+f -target-abi lp64f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32IF-LP64F %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+d -target-abi lp64d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32IFD-LP64D %s
+
+# RV32I-LP64: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+# RV32IF-LP64F: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+# RV32IFD-LP64D: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+
+# RUN: llvm-mc -triple=riscv32 -target-abi ilp32f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32I-ILP32F %s
+# RUN: llvm-mc -triple=riscv64 -target-abi lp64f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64I-LP64F %s
+
+# RV32I-ILP32F: Hard-float 'f' ABI can't be used for a target that doesn't support the F instruction set extension (ignoring target-abi)
+# RV64I-LP64F: Hard-float 'f' ABI can't be used for a target that doesn't support the F instruction set extension (ignoring target-abi)
+
+# RUN: llvm-mc -triple=riscv32 -target-abi ilp32d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32I-ILP32D %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+f -target-abi ilp32d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32IF-ILP32D %s
+# RUN: llvm-mc -triple=riscv64 -target-abi lp64d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64I-LP64D %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+f -target-abi lp64d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV64IF-LP64D %s
+
+# RV32I-ILP32D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+# RV32IF-ILP32D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+# RV64I-LP64D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+# RV64IF-LP64D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
+
+nop
diff --git a/llvm/test/MC/RISCV/target-abi-valid.s b/llvm/test/MC/RISCV/target-abi-valid.s
new file mode 100644 (file)
index 0000000..985d174
--- /dev/null
@@ -0,0 +1,65 @@
+# RUN: llvm-mc -triple=riscv32 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+# RUN: llvm-mc -triple=riscv32 -target-abi ilp32 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+f -target-abi ilp32 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+d -target-abi ilp32 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+# RUN: llvm-mc -triple=riscv64 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+# RUN: llvm-mc -triple=riscv64 -target-abi lp64 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+f -target-abi lp64 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+d -target-abi lp64 -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-NONE %s
+
+# RUN: llvm-mc -triple=riscv32 -mattr=+f -target-abi ilp32f -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-FLOAT-SINGLE %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+d -target-abi ilp32f -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-FLOAT-SINGLE %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+f -target-abi lp64f -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-FLOAT-SINGLE %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+d -target-abi lp64f -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-FLOAT-SINGLE %s
+
+# RUN: llvm-mc -triple=riscv32 -mattr=+d -target-abi ilp32d -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-FLOAT-DOUBLE %s
+# RUN: llvm-mc -triple=riscv64 -mattr=+d -target-abi lp64d -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-FLOAT-DOUBLE %s
+
+# RUN: llvm-mc -triple=riscv32 -target-abi ilp32e -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-RVE %s
+
+# CHECK-NONE:               Flags [ (0x0)
+# CHECK-NONE-NEXT:          ]
+
+# CHECK-FLOAT-SINGLE:       Flags [ (0x2)
+# CHECK-FLOAT-SINGLE-NEXT:    EF_RISCV_FLOAT_ABI_SINGLE (0x2)
+# CHECK-FLOAT-SINGLE-NEXT:  ]
+
+# CHECK-FLOAT-DOUBLE:       Flags [ (0x4)
+# CHECK-FLOAT-DOUBLE-NEXT:    EF_RISCV_FLOAT_ABI_DOUBLE (0x4)
+# CHECK-FLOAT-DOUBLE-NEXT:  ]
+
+# CHECK-RVE:                Flags [ (0x8)
+# CHECK-RVE-NEXT:             EF_RISCV_RVE (0x8)
+# CHECK-RVE-NEXT:           ]
+
+nop