type = Library
name = RISCVDesc
parent = RISCV
-required_libraries = MC RISCVAsmPrinter RISCVInfo Support
+required_libraries = MC RISCVAsmPrinter RISCVInfo RISCVUtils Support
add_to_library_groups = RISCV
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);
}
#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"
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; }
bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
+
+ const MCTargetOptions &getTargetOptions() const { return TargetOptions; }
+ RISCVABI::ABI getTargetABI() const { return TargetABI; }
};
}
//===----------------------------------------------------------------------===//
#include "RISCVELFStreamer.h"
+#include "MCTargetDesc/RISCVAsmBackend.h"
#include "RISCVMCTargetDesc.h"
+#include "Utils/RISCVBaseInfo.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCSubtargetInfo.h"
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);
}
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.
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";
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) {}
#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"
bool EnableLinkerRelax = false;
unsigned XLen = 32;
MVT XLenVT = MVT::i32;
+ RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
RISCVFrameLowering FrameLowering;
RISCVInstrInfo InstrInfo;
RISCVRegisterInfo RegInfo;
/// 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.
bool enableLinkerRelax() const { return EnableLinkerRelax; }
MVT getXLenVT() const { return XLenVT; }
unsigned getXLen() const { return XLen; }
+ RISCVABI::ABI getTargetABI() const { return TargetABI; }
};
} // End llvm namespace
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();
}
#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
#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
--- /dev/null
+; 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
+}
--- /dev/null
+; 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
--- /dev/null
+# 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
--- /dev/null
+# 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