[flang][RISCV] Add target-abi ModuleFlag. (#126188)

This is needed to generate proper ABI flags in the ELF header for LTO
builds. If these flags aren't set correctly, we can't link with objects
that were built with the correct flags.

For non-LTO builds the mcpu/mattr in the TargetMachine will cause the
backend to infer an ABI. For LTO builds the mcpu/mattr aren't set.

I've only added lp64, lp64f, and lp64d ABIs. ilp32* requires riscv32
which is not yet supported in flang. lp64e requires a different
DataLayout string and would need additional plumbing.

Fixes #115679
This commit is contained in:
Craig Topper 2025-02-13 08:08:09 -08:00 committed by GitHub
parent 21811818d6
commit 8da8ff8768
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 44 additions and 2 deletions

View File

@ -261,11 +261,18 @@ void Flang::AddPPCTargetArgs(const ArgList &Args,
void Flang::AddRISCVTargetArgs(const ArgList &Args, void Flang::AddRISCVTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const { ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
const llvm::Triple &Triple = getToolChain().getTriple(); const llvm::Triple &Triple = getToolChain().getTriple();
StringRef ABIName = riscv::getRISCVABI(Args, Triple);
if (ABIName == "lp64" || ABIName == "lp64f" || ABIName == "lp64d")
CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName));
else
D.Diag(diag::err_drv_unsupported_option_argument) << "-mabi=" << ABIName;
// Handle -mrvv-vector-bits=<bits> // Handle -mrvv-vector-bits=<bits>
if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) { if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) {
StringRef Val = A->getValue(); StringRef Val = A->getValue();
const Driver &D = getToolChain().getDriver();
// Get minimum VLen from march. // Get minimum VLen from march.
unsigned MinVLen = 0; unsigned MinVLen = 0;

View File

@ -35,6 +35,9 @@ public:
/// If given, the name of the target CPU to tune code for. /// If given, the name of the target CPU to tune code for.
std::string cpuToTuneFor; std::string cpuToTuneFor;
/// If given, the name of the target ABI to use.
std::string abi;
/// The list of target specific features to enable or disable, as written on /// The list of target specific features to enable or disable, as written on
/// the command line. /// the command line.
std::vector<std::string> featuresAsWritten; std::vector<std::string> featuresAsWritten;

View File

@ -464,6 +464,7 @@ static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) {
if (const llvm::opt::Arg *a = if (const llvm::opt::Arg *a =
args.getLastArg(clang::driver::options::OPT_mabi_EQ)) { args.getLastArg(clang::driver::options::OPT_mabi_EQ)) {
opts.abi = a->getValue();
llvm::StringRef V = a->getValue(); llvm::StringRef V = a->getValue();
if (V == "vec-extabi") { if (V == "vec-extabi") {
opts.EnableAIXExtendedAltivecABI = true; opts.EnableAIXExtendedAltivecABI = true;

View File

@ -920,16 +920,23 @@ void CodeGenAction::generateLLVMIR() {
static_cast<llvm::PIELevel::Level>(opts.PICLevel)); static_cast<llvm::PIELevel::Level>(opts.PICLevel));
} }
const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts();
const llvm::Triple triple(targetOpts.triple);
// Set mcmodel level LLVM module flags // Set mcmodel level LLVM module flags
std::optional<llvm::CodeModel::Model> cm = getCodeModel(opts.CodeModel); std::optional<llvm::CodeModel::Model> cm = getCodeModel(opts.CodeModel);
if (cm.has_value()) { if (cm.has_value()) {
const llvm::Triple triple(ci.getInvocation().getTargetOpts().triple);
llvmModule->setCodeModel(*cm); llvmModule->setCodeModel(*cm);
if ((cm == llvm::CodeModel::Medium || cm == llvm::CodeModel::Large) && if ((cm == llvm::CodeModel::Medium || cm == llvm::CodeModel::Large) &&
triple.getArch() == llvm::Triple::x86_64) { triple.getArch() == llvm::Triple::x86_64) {
llvmModule->setLargeDataThreshold(opts.LargeDataThreshold); llvmModule->setLargeDataThreshold(opts.LargeDataThreshold);
} }
} }
if (triple.isRISCV() && !targetOpts.abi.empty())
llvmModule->addModuleFlag(
llvm::Module::Error, "target-abi",
llvm::MDString::get(llvmModule->getContext(), targetOpts.abi));
} }
static std::unique_ptr<llvm::raw_pwrite_stream> static std::unique_ptr<llvm::raw_pwrite_stream>

View File

@ -0,0 +1,14 @@
! RUN: not %flang -c --target=riscv64-unknown-linux -mabi=ilp32 %s -### 2>&1 | FileCheck --check-prefix=INVALID1 %s
! RUN: not %flang -c --target=riscv64-unknown-linux -mabi=lp64e %s -### 2>&1 | FileCheck --check-prefix=INVALID2 %s
! RUN: %flang -c --target=riscv64-unknown-linux -mabi=lp64 %s -### 2>&1 | FileCheck --check-prefix=ABI1 %s
! RUN: %flang -c --target=riscv64-unknown-linux -mabi=lp64f %s -### 2>&1 | FileCheck --check-prefix=ABI2 %s
! RUN: %flang -c --target=riscv64-unknown-linux -mabi=lp64d %s -### 2>&1 | FileCheck --check-prefix=ABI3 %s
! RUN: %flang -c --target=riscv64-unknown-linux %s -### 2>&1 | FileCheck --check-prefix=ABI3 %s
! INVALID1: error: unsupported argument 'ilp32' to option '-mabi='
! INVALID2: error: unsupported argument 'lp64e' to option '-mabi='
! ABI1: "-mabi=lp64"
! ABI2: "-mabi=lp64f"
! ABI3: "-mabi=lp64d"

View File

@ -0,0 +1,10 @@
! REQUIRES: riscv-registered-target
! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -mabi=lp64 -emit-llvm -o - %s | FileCheck %s --check-prefix=LP64
! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -mabi=lp64f -emit-llvm -o - %s | FileCheck %s --check-prefix=LP64F
! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -mabi=lp64d -emit-llvm -o - %s | FileCheck %s --check-prefix=LP64D
! LP64: !{{[0-9]+}} = !{i32 1, !"target-abi", !"lp64"}
! LP64F: !{{[0-9]+}} = !{i32 1, !"target-abi", !"lp64f"}
! LP64D: !{{[0-9]+}} = !{i32 1, !"target-abi", !"lp64d"}
subroutine func
end subroutine func