Index: clang/lib/Driver/ToolChains/Arch/RISCV.h =================================================================== --- clang/lib/Driver/ToolChains/Arch/RISCV.h +++ clang/lib/Driver/ToolChains/Arch/RISCV.h @@ -23,6 +23,8 @@ std::vector &Features); StringRef getRISCVABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); +void addGoldOptions(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs); } // end namespace riscv } // namespace tools } // end namespace driver Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -383,3 +383,42 @@ // expanded to select ilp32f, ilp32d, lp64f, lp64d when appropriate. return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64"; } + +void riscv::addGoldOptions(const ToolChain &ToolChain, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) { + const Driver &D = ToolChain.getDriver(); + // Pass the features to linker. + std::vector Features; + getRISCVTargetFeatures(D, Args, Features); + + // Find the last of each feature. + llvm::StringMap LastOpt; + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + StringRef Name = Features[I]; + assert(Name[0] == '-' || Name[0] == '+'); + LastOpt[Name.drop_front(1)] = I; + } + + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + // If this feature was overridden, + // ignore it. + StringRef Name = Features[I]; + llvm::StringMap::iterator LastI = + LastOpt.find(Name.drop_front(1)); + assert(LastI != LastOpt.end()); + unsigned Last = LastI->second; + if (Last != I) + continue; + + CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=--" + "mattr=") + + Name)); + } + + // Pass the ABIName to linker. + StringRef ABIName = riscv::getRISCVABI(Args, ToolChain.getTriple()); + CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=-target-" + "abi=") + + ABIName)); +} Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -514,6 +514,15 @@ assert(!Inputs.empty() && "Must have at least one input."); AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], D.getLTOMode() == LTOK_Thin); + switch (ToolChain.getArch()) { + default: + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: { + tools::riscv::addGoldOptions(ToolChain, Args, CmdArgs); + break; + } + } } if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) Index: clang/lib/Driver/ToolChains/RISCVToolchain.h =================================================================== --- clang/lib/Driver/ToolChains/RISCVToolchain.h +++ clang/lib/Driver/ToolChains/RISCVToolchain.h @@ -25,6 +25,7 @@ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind) const override; + bool HasNativeLLVMSupport() const override { return true; } void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; Index: clang/lib/Driver/ToolChains/RISCVToolchain.cpp =================================================================== --- clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RISCVToolchain.h" +#include "Arch/RISCV.h" #include "CommonArgs.h" #include "InputInfo.h" #include "clang/Driver/Compilation.h" @@ -100,6 +101,13 @@ std::string Linker = getToolChain().GetProgramPath(getShortName()); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + tools::riscv::addGoldOptions(ToolChain, Args, CmdArgs); + } + bool WantCRTs = !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); Index: clang/test/Driver/gold-lto.c =================================================================== --- clang/test/Driver/gold-lto.c +++ clang/test/Driver/gold-lto.c @@ -26,3 +26,21 @@ // RUN: %clang -target i686-linux-android -### %t.o -flto 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-X86-ANDROID // CHECK-X86-ANDROID: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}" +// +// RUN: %clang -target riscv64-unknown-elf -### %t.o -flto 2>&1 \ +// RUN: -march=rv64imf -mabi=lp64f \ +// RUN: | FileCheck %s --check-prefix=CHECK-RISCV-BAREMETAL +// CHECK-RISCV-BAREMETAL: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=--mattr=+m" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=--mattr=+f" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=--mattr=+relax" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=-target-abi=lp64f" +// +// RUN: %clang -target riscv64-unknown-linux-gnu -### %t.o -flto 2>&1 \ +// RUN: -march=rv64imf -mabi=lp64f \ +// RUN: | FileCheck %s --check-prefix=CHECK-RISCV-LINUX +// CHECK-RISCV-LINUX: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}" +// CHECK-RISCV-LINUX: "-plugin-opt=--mattr=+m" +// CHECK-RISCV-LINUX: "-plugin-opt=--mattr=+f" +// CHECK-RISCV-LINUX: "-plugin-opt=--mattr=+relax" +// CHECK-RISCV-LINUX: "-plugin-opt=-target-abi=lp64f"