diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -15,6 +15,7 @@ #include "RISCVTargetObjectFile.h" #include "RISCVTargetTransformInfo.h" #include "TargetInfo/RISCVTargetInfo.h" +#include "Utils/RISCVBaseInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/GlobalISel/IRTranslator.h" @@ -89,8 +90,17 @@ // creation will depend on the TM and the code generation flags on the // function that reside in TargetOptions. resetTargetOptions(F); - I = std::make_unique(TargetTriple, CPU, FS, - Options.MCOptions.getABIName(), *this); + auto ABIName = Options.MCOptions.getABIName(); + if (const MDString *ModuleTargetABI = dyn_cast_or_null( + F.getParent()->getModuleFlag("target-abi"))) { + auto TargetABI = RISCVABI::getTargetABI(ABIName); + if (TargetABI != RISCVABI::ABI_Unknown && + ModuleTargetABI->getString() != ABIName) { + report_fatal_error("-target-abi option != target-abi module flag"); + } + ABIName = ModuleTargetABI->getString(); + } + I = std::make_unique(TargetTriple, CPU, FS, ABIName, *this); } return I.get(); } diff --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -202,6 +202,8 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, StringRef ABIName); +ABI getTargetABI(StringRef ABIName); + // Returns the register used to hold the stack pointer after realignment. Register getBPReg(); diff --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp --- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp +++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp @@ -12,16 +12,7 @@ namespace RISCVABI { ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, StringRef ABIName) { - auto TargetABI = StringSwitch(ABIName) - .Case("ilp32", ABI_ILP32) - .Case("ilp32f", ABI_ILP32F) - .Case("ilp32d", ABI_ILP32D) - .Case("ilp32e", ABI_ILP32E) - .Case("lp64", ABI_LP64) - .Case("lp64f", ABI_LP64F) - .Case("lp64d", ABI_LP64D) - .Default(ABI_Unknown); - + auto TargetABI = getTargetABI(ABIName); bool IsRV64 = TT.isArch64Bit(); bool IsRV32E = FeatureBits[RISCV::FeatureRV32E]; @@ -67,6 +58,19 @@ return ABI_ILP32; } +ABI getTargetABI(StringRef ABIName) { + auto TargetABI = StringSwitch(ABIName) + .Case("ilp32", ABI_ILP32) + .Case("ilp32f", ABI_ILP32F) + .Case("ilp32d", ABI_ILP32D) + .Case("ilp32e", ABI_ILP32E) + .Case("lp64", ABI_LP64) + .Case("lp64f", ABI_LP64F) + .Case("lp64d", ABI_LP64D) + .Default(ABI_Unknown); + return TargetABI; +} + // To avoid the BP value clobbered by a function call, we need to choose a // callee saved register to save the value. RV32E only has X8 and X9 as callee // saved registers and X8 will be used as fp. So we choose X9 as bp. diff --git a/llvm/test/CodeGen/RISCV/module-target-abi.ll b/llvm/test/CodeGen/RISCV/module-target-abi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/module-target-abi.ll @@ -0,0 +1,24 @@ +; RUN: llc -mtriple=riscv32 < %s 2>&1 \ +; RUN: | FileCheck -check-prefix=DEFAULT %s +; RUN: llc -mtriple=riscv32 -target-abi ilp32 < %s 2>&1 \ +; RUN: | FileCheck -check-prefix=RV32IF-ILP32 %s +; RUN: not llc -mtriple=riscv32 -target-abi ilp32f < %s 2>&1 \ +; RUN: | FileCheck -check-prefix=RV32IF-ILP32F %s +; RUN: llc -mtriple=riscv32 -filetype=obj < %s | llvm-readelf -h - | FileCheck -check-prefixes=FLAGS %s + +; RV32IF-ILP32F: -target-abi option != target-abi module flag + +; FLAGS: Flags: 0x0 + +define float @foo(i32 %a) nounwind #0 { +; DEFAULT: # %bb.0: +; DEFAULT: fmv.x.w a0, ft0 +; RV32IF-ILP32: # %bb.0: +; RV32IF-ILP32: fmv.x.w a0, ft0 + %conv = sitofp i32 %a to float + ret float %conv +} + +attributes #0 = { "target-features"="+f"} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32"} diff --git a/llvm/test/CodeGen/RISCV/module-target-abi2.ll b/llvm/test/CodeGen/RISCV/module-target-abi2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/module-target-abi2.ll @@ -0,0 +1,27 @@ +; RUN: llc -mtriple=riscv32 < %s 2>&1 \ +; RUN: | FileCheck -check-prefix=DEFAULT %s +; RUN: not llc -mtriple=riscv32 -target-abi ilp32 < %s 2>&1 \ +; RUN: | FileCheck -check-prefix=RV32IF-ILP32 %s +; RUN: llc -mtriple=riscv32 -target-abi ilp32f < %s 2>&1 \ +; RUN: | FileCheck -check-prefix=RV32IF-ILP32F %s +; RUN: llc -mtriple=riscv32 -filetype=obj < %s | llvm-readelf -h - | FileCheck -check-prefixes=FLAGS %s + +; RV32IF-ILP32: -target-abi option != target-abi module flag + +; FLAGS: Flags: 0x0 +; // this should be "Flags :0x2, single-float ABI", it will be fixed later. + +define float @foo(i32 %a) nounwind #0 { +; DEFAULT: # %bb.0: +; DEFAULT-NEXT: fcvt.s.w fa0, a0 +; DEFAULT-NEXT: ret +; RV32IF-ILP32F: # %bb.0: +; RV32IF-ILP32F: fcvt.s.w fa0, a0 +; RV32IF-ILP32F: ret + %conv = sitofp i32 %a to float + ret float %conv +} + +attributes #0 = { "target-features"="+f"} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"ilp32f"}