diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.h b/clang/lib/Driver/ToolChains/Arch/RISCV.h --- a/clang/lib/Driver/ToolChains/Arch/RISCV.h +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.h @@ -24,6 +24,8 @@ std::vector &Features); StringRef getRISCVABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); +StringRef getRISCVArch(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); } // end namespace riscv } // namespace tools } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -357,14 +357,9 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, std::vector &Features) { - llvm::Optional MArch; - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) - MArch = A->getValue(); - else if (Triple.getOS() == llvm::Triple::Linux) - // RISC-V Linux defaults to rv{32,64}gc. - MArch = Triple.getArch() == llvm::Triple::riscv32 ? "rv32gc" : "rv64gc"; + StringRef MArch = getRISCVArch(Args, Triple); - if (MArch.hasValue() && !getArchFeatures(D, *MArch, Features, Args)) + if (!getArchFeatures(D, MArch, Features, Args)) return; // Handle features corresponding to "-ffixed-X" options @@ -455,12 +450,91 @@ Triple.getArch() == llvm::Triple::riscv64) && "Unexpected triple"); + // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not + // configured using `--with-abi=`, then the logic for the default choice is + // defined in config.gcc. + // + // This logic uses the following, in order: + // 1. Explicit choices using `--with-abi=` + // 2. A default based on `--with-arch=`, if provided + // 3. A default based on the target triple's arch + // + // This logic in config.gcc is a little circular but it is not inconsistent. + // + // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` + // and `-mabi=` respectively instead. + + // 1. If `-mabi=` is specified, use it. if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) return A->getValue(); - // RISC-V Linux defaults to ilp32d/lp64d - if (Triple.getOS() == llvm::Triple::Linux) - return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32d" : "lp64d"; + // 2. Choose a default based on `-march=` + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + StringRef MArch = A->getValue(); + + if (MArch.startswith_lower("rv32")) { + if (MArch.substr(4).contains_lower("d") || + MArch.startswith_lower("rv32g")) + return "ilp32d"; + else if (MArch.startswith_lower("rv32e")) + return "ilp32e"; + else + return "ilp32"; + } else if (MArch.startswith_lower("rv64")) { + if (MArch.substr(4).contains_lower("d") || + MArch.startswith_lower("rv64g")) + return "lp64d"; + else + return "lp64"; + } + } + + // 3. Choose a default based on the triple + if (Triple.getArch() == llvm::Triple::riscv32) + return "ilp32d"; + else + return "lp64d"; +} + +StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple) { + assert((Triple.getArch() == llvm::Triple::riscv32 || + Triple.getArch() == llvm::Triple::riscv64) && + "Unexpected triple"); + + // GCC's logic around choosing a default `-march=` is complex. If GCC is not + // configured using `--with-arch=`, then the logic for the default choice is + // defined in config.gcc. + // + // This logic uses the following, in order: + // 1. Explicit choices using `--with-arch=` + // 2. A default based on `--with-abi=`, if provided + // 3. A default based on the target triple's arch + // + // This logic in config.gcc is a little circular but it is not inconsistent. + // + // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` + // and `-mabi=` respectively instead. + + // 1. If `-march=` is specified, use it. + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + return A->getValue(); + + // 2. Choose a default based on `-mabi=` + if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + StringRef MABI = A->getValue(); + + if (MABI.equals_lower("ilp32e")) + return "rv32e"; + else if (MABI.startswith_lower("ilp32")) + return "rv32gc"; + else if (MABI.startswith_lower("lp64")) + return "rv64gc"; + } + + // 3. Choose a default based on the triple + if (Triple.getArch() == llvm::Triple::riscv32) + return "rv32gc"; else - return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64"; + return "rv64gc"; } diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -709,11 +709,9 @@ StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple()); CmdArgs.push_back("-mabi"); CmdArgs.push_back(ABIName.data()); - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - StringRef MArch = A->getValue(); - CmdArgs.push_back("-march"); - CmdArgs.push_back(MArch.data()); - } + StringRef MArchName = riscv::getRISCVArch(Args, getToolChain().getTriple()); + CmdArgs.push_back("-march"); + CmdArgs.push_back(MArchName.data()); break; } case llvm::Triple::sparc: diff --git a/clang/test/Driver/riscv-abi.c b/clang/test/Driver/riscv-abi.c --- a/clang/test/Driver/riscv-abi.c +++ b/clang/test/Driver/riscv-abi.c @@ -1,9 +1,5 @@ -// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-ILP32 %s // RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -mabi=ilp32 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ILP32 %s -// RUN: %clang -target riscv32-unknown-elf -x assembler %s -### -o %t.o 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-ILP32 %s // RUN: %clang -target riscv32-unknown-elf -x assembler %s -### -o %t.o \ // RUN: -mabi=ilp32 2>&1 | FileCheck -check-prefix=CHECK-ILP32 %s @@ -14,6 +10,10 @@ // CHECK-ILP32F: "-target-abi" "ilp32f" +// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ILP32D %s +// RUN: %clang -target riscv32-unknown-elf -x assembler %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ILP32D %s // RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -march=rv32ifd -mabi=ilp32d 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ILP32D %s @@ -24,12 +24,8 @@ // CHECK-RV32-LP64: error: unknown target ABI 'lp64' -// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-LP64 %s // RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -mabi=lp64 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-LP64 %s -// RUN: %clang -target riscv64-unknown-elf -x assembler %s -### -o %t.o 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-LP64 %s // RUN: %clang -target riscv64-unknown-elf -x assembler %s -### -o %t.o \ // RUN: -mabi=lp64 2>&1 | FileCheck -check-prefix=CHECK-LP64 %s @@ -40,6 +36,10 @@ // CHECK-LP64F: "-target-abi" "lp64f" +// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-LP64D %s +// RUN: %clang -target riscv64-unknown-elf -x assembler %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-LP64D %s // RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -march=rv64d -mabi=lp64d 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-LP64D %s diff --git a/clang/test/Driver/riscv-gnutools.c b/clang/test/Driver/riscv-gnutools.c --- a/clang/test/Driver/riscv-gnutools.c +++ b/clang/test/Driver/riscv-gnutools.c @@ -1,19 +1,19 @@ // Check gnutools are invoked with propagated values for -mabi and -march. // RUN: %clang -target riscv32 -fno-integrated-as %s -### -c \ -// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32 %s +// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32D %s // RUN: %clang -target riscv32 -fno-integrated-as -march=rv32g %s -### -c \ -// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32-MARCH-G %s +// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32D-MARCH-G %s // RUN: %clang -target riscv64 -fno-integrated-as %s -### -c \ -// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64 %s +// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64D %s // RUN: %clang -target riscv64 -fno-integrated-as -march=rv64g %s -### -c \ -// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64-MARCH-G %s +// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64D-MARCH-G %s -// MABI-ILP32: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32" -// MABI-ILP32-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32" "-march" "rv32g" +// MABI-ILP32D: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32d" "-march" "rv32gc" +// MABI-ILP32D-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32d" "-march" "rv32g" -// MABI-ILP64: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64" -// MABI-ILP64-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64" "-march" "rv64g" +// MABI-ILP64D: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64d" +// MABI-ILP64D-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64d" "-march" "rv64g"