Index: lib/Basic/Targets/RISCV.h =================================================================== --- lib/Basic/Targets/RISCV.h +++ lib/Basic/Targets/RISCV.h @@ -26,10 +26,16 @@ class RISCVTargetInfo : public TargetInfo { protected: std::string ABI; + bool HasM; + bool HasA; + bool HasF; + bool HasD; + bool HasC; public: RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &) - : TargetInfo(Triple) { + : TargetInfo(Triple), HasM(false), HasA(false), HasF(false), + HasD(false), HasC(false) { TLSSupported = false; LongDoubleWidth = 128; LongDoubleAlign = 128; @@ -59,6 +65,11 @@ TargetInfo::ConstraintInfo &Info) const override { return false; } + + bool hasFeature(StringRef Feature) const override; + + bool handleTargetFeatures(std::vector &Features, + DiagnosticsEngine &Diags) override; }; class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { public: Index: lib/Basic/Targets/RISCV.cpp =================================================================== --- lib/Basic/Targets/RISCV.cpp +++ lib/Basic/Targets/RISCV.cpp @@ -49,4 +49,60 @@ // TODO: modify when more code models and ABIs are supported. Builder.defineMacro("__riscv_cmodel_medlow"); Builder.defineMacro("__riscv_float_abi_soft"); + + if (HasM) { + Builder.defineMacro("__riscv_mul"); + Builder.defineMacro("__riscv_div"); + Builder.defineMacro("__riscv_muldiv"); + } + + if (HasC) + Builder.defineMacro("__riscv_compressed"); + + if (HasD) + Builder.defineMacro("__riscv_flen", "64"); + else if (HasF) + Builder.defineMacro("__riscv_flen", "32"); + + if (HasF || HasD) { + Builder.defineMacro("__riscv_fdiv"); + Builder.defineMacro("__riscv_fsqrt"); + } + + if (HasA) + Builder.defineMacro("__riscv_atomic"); +} + +/// Return true if has this feature, need to sync with handleTargetFeatures. +bool RISCVTargetInfo::hasFeature(StringRef Feature) const { + bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; + return llvm::StringSwitch(Feature) + .Case("riscv", true) + .Case("riscv32", !Is64Bit) + .Case("riscv64", Is64Bit) + .Case("m", HasM) + .Case("a", HasA) + .Case("f", HasF) + .Case("d", HasD) + .Case("c", HasC) + .Default(false); +} + +/// Perform initialization based on the user configured set of features. +bool RISCVTargetInfo::handleTargetFeatures(std::vector &Features, + DiagnosticsEngine &Diags) { + for (const auto &Feature : Features) { + if (Feature == "+m") + HasM = true; + else if (Feature == "+a") + HasA = true; + else if (Feature == "+f") + HasF = true; + else if (Feature == "+d") + HasD = true; + else if (Feature == "+c") + HasC = true; + } + + return true; } Index: test/Preprocessor/riscv-target-features.c =================================================================== --- /dev/null +++ test/Preprocessor/riscv-target-features.c @@ -0,0 +1,49 @@ +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32i -x c -E -dM %s \ +// RUN: -o - | FileCheck %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64i -x c -E -dM %s \ +// RUN: -o - | FileCheck %s + +// CHECK-NOT: __riscv_div +// CHECK-NOT: __riscv_mul +// CHECK-NOT: __riscv_muldiv +// CHECK-NOT: __riscv_compressed +// CHECK-NOT: __riscv_flen +// CHECK-NOT: __riscv_fdiv +// CHECK-NOT: __riscv_fsqrt +// CHECK-NOT: __riscv_atomic + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32im -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-M-EXT %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64im -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-M-EXT %s +// CHECK-M-EXT: __riscv_div 1 +// CHECK-M-EXT: __riscv_mul 1 +// CHECK-M-EXT: __riscv_muldiv 1 + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ia -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-A-EXT %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ia -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-A-EXT %s +// CHECK-A-EXT: __riscv_atomic 1 + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32if -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-F-EXT %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64if -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-F-EXT %s +// CHECK-F-EXT: __riscv_fdiv 1 +// CHECK-F-EXT: __riscv_flen 32 +// CHECK-F-EXT: __riscv_fsqrt 1 + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-D-EXT %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-D-EXT %s +// CHECK-D-EXT: __riscv_fdiv 1 +// CHECK-D-EXT: __riscv_flen 64 +// CHECK-D-EXT: __riscv_fsqrt 1 + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ic -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-C-EXT %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ic -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-C-EXT %s +// CHECK-C-EXT: __riscv_compressed 1