diff --git a/CHANGELOG.md b/CHANGELOG.md index 26a0cd92927..b90c785e78e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ #### Platform support - Supports LLVM 11.0 - 16.0. +- 64-bit RISC-V: Now defaults to `-mattr=+m,+a,+f,+d,+c` ('rv64gc' ABI) for non-bare-metal targets, i.e., if the target triple includes a valid operating system. (#4390) #### Bug fixes - Fix function pointers/delegates on Harvard architectures (e.g., AVR). (#4432, #4465) diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index 3f16e20813c..b454fa2c8e1 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -57,7 +57,20 @@ static llvm::cl::opt preserveDwarfLineSection( llvm::cl::init(false)); #endif -const char *getABI(const llvm::Triple &triple) { +// Returns true if 'feature' is enabled and false otherwise. Handles the +// case where the feature is specified multiple times ('+m,-m'), and +// takes the last occurrence. +bool isFeatureEnabled(const llvm::SmallVectorImpl &features, + llvm::StringRef feature) { + for (auto it = features.rbegin(), end = features.rend(); it != end; ++it) { + if (it->substr(1) == feature) { + return (*it)[0] == '+'; + } + } + return false; +}; + +const char *getABI(const llvm::Triple &triple, const llvm::SmallVectorImpl &features) { llvm::StringRef ABIName(opts::mABI); if (ABIName != "") { switch (triple.getArch()) { @@ -120,6 +133,10 @@ const char *getABI(const llvm::Triple &triple) { case llvm::Triple::ppc64le: return "elfv2"; case llvm::Triple::riscv64: + if (isFeatureEnabled(features, "d")) + return "lp64d"; + if (isFeatureEnabled(features, "f")) + return "lp64f"; return "lp64"; case llvm::Triple::riscv32: return "ilp32"; @@ -441,6 +458,16 @@ createTargetMachine(const std::string targetTriple, const std::string arch, features.push_back("+cx16"); } + // For a hosted RISC-V 64-bit target default to rv64gc if nothing has + // been selected + if (triple.getArch() == llvm::Triple::riscv64 && features.empty()) { + const llvm::StringRef os = triple.getOSName(); + const bool isFreeStanding = os.empty() || os == "unknown" || os == "none"; + if (!isFreeStanding) { + features = {"+m", "+a", "+f", "+d", "+c"}; + } + } + // Handle cases where LLVM picks wrong default relocModel #if LDC_LLVM_VER >= 1600 if (relocModel.has_value()) {} @@ -478,7 +505,7 @@ createTargetMachine(const std::string targetTriple, const std::string arch, opts::InitTargetOptionsFromCodeGenFlags(triple); if (targetOptions.MCOptions.ABIName.empty()) - targetOptions.MCOptions.ABIName = getABI(triple); + targetOptions.MCOptions.ABIName = getABI(triple, features); if (floatABI == FloatABI::Default) { switch (triple.getArch()) { diff --git a/driver/targetmachine.h b/driver/targetmachine.h index 17e664a2bf8..66e1a20be8e 100644 --- a/driver/targetmachine.h +++ b/driver/targetmachine.h @@ -15,6 +15,8 @@ #pragma once #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/CodeGen.h" #include #include @@ -73,4 +75,8 @@ MipsABI::Type getMipsABI(); const llvm::Target *lookupTarget(const std::string &arch, llvm::Triple &triple, std::string &errorMsg); -const char *getABI(const llvm::Triple &triple); +const char *getABI(const llvm::Triple &triple, + const llvm::SmallVectorImpl &features); + +bool isFeatureEnabled(const llvm::SmallVectorImpl &features, + llvm::StringRef feature); diff --git a/driver/tool.cpp b/driver/tool.cpp index 806e365996e..dea42d05a58 100644 --- a/driver/tool.cpp +++ b/driver/tool.cpp @@ -121,62 +121,45 @@ void appendTargetArgsForGcc(std::vector &args) { } return; - case Triple::riscv64: - { - std::string mabi = getABI(triple); - args.push_back("-mabi=" + mabi); - - extern llvm::TargetMachine* gTargetMachine; - auto featuresStr = gTargetMachine->getTargetFeatureString(); - llvm::SmallVector features; - featuresStr.split(features, ",", -1, false); - - // Returns true if 'feature' is enabled and false otherwise. Handles the - // case where the feature is specified multiple times ('+m,-m'), and - // takes the last occurrence. - auto hasFeature = [&features](llvm::StringRef feature) { - for (int i = features.size() - 1; i >= 0; i--) { - auto f = features[i]; - if (f.substr(1) == feature) { - return f[0] == '+'; - } - } - return false; - }; - - std::string march; - if (triple.isArch64Bit()) - march = "rv64"; - else - march = "rv32"; - bool m = hasFeature("m"); - bool a = hasFeature("a"); - bool f = hasFeature("f"); - bool d = hasFeature("d"); - bool c = hasFeature("c"); - bool g = false; - - if (m && a && f && d) { - march += "g"; - g = true; - } else { - march += "i"; - if (m) - march += "m"; - if (a) - march += "a"; - if (f) - march += "f"; - if (d) - march += "d"; - } - if (c) - march += "c"; - if (!g) - march += "_zicsr_zifencei"; - args.push_back("-march=" + march); + case Triple::riscv64: { + extern llvm::TargetMachine* gTargetMachine; + const auto featuresStr = gTargetMachine->getTargetFeatureString(); + llvm::SmallVector features; + featuresStr.split(features, ",", -1, false); + + const std::string mabi = getABI(triple, features); + args.push_back("-mabi=" + mabi); + + std::string march = triple.isArch64Bit() ? "rv64" : "rv32"; + const bool m = isFeatureEnabled(features, "m"); + const bool a = isFeatureEnabled(features, "a"); + const bool f = isFeatureEnabled(features, "f"); + const bool d = isFeatureEnabled(features, "d"); + const bool c = isFeatureEnabled(features, "c"); + bool g = false; + + if (m && a && f && d) { + march += "g"; + g = true; + } else { + march += "i"; + if (m) + march += "m"; + if (a) + march += "a"; + if (f) + march += "f"; + if (d) + march += "d"; } + if (c) + march += "c"; + if (!g) + march += "_zicsr_zifencei"; + args.push_back("-march=" + march); return; + } + default: break; } diff --git a/tests/driver/riscv_abi4.d b/tests/driver/riscv_abi4.d new file mode 100644 index 00000000000..a5c93bab615 --- /dev/null +++ b/tests/driver/riscv_abi4.d @@ -0,0 +1,6 @@ +// REQUIRES: target_RISCV + +// RUN: %ldc %s -mtriple=riscv64-unknown-linux --gcc=echo > %t && FileCheck %s < %t +// CHECK: -mabi=lp64d -march=rv64gc + +void main() {} diff --git a/tests/driver/riscv_abi5.d b/tests/driver/riscv_abi5.d new file mode 100644 index 00000000000..11cd97c41c5 --- /dev/null +++ b/tests/driver/riscv_abi5.d @@ -0,0 +1,6 @@ +// REQUIRES: target_RISCV + +// RUN: %ldc %s -mtriple=riscv64-unknown-linux -mattr=+m,+a,+f,-d --gcc=echo > %t && FileCheck %s < %t +// CHECK: -mabi=lp64f -march=rv64imaf_zicsr_zifencei + +void main() {}