diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index fcd5396ccfdbc..5f1976117e01e 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -190,6 +190,8 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node { static Function *Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N, Module &M); + StringRef getDefaultTargetFeatures(const StringRef TargetABI); + /// Creates a function with some attributes recorded in llvm.module.flags /// and the LLVMContext applied. /// diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 12b50fc506516..3368184af4103 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -1065,6 +1065,9 @@ class LLVM_ABI Module { /// Set the target variant version build SDK version metadata. void setDarwinTargetVariantSDKVersion(VersionTuple Version); + + /// Returns target-abi from MDString, null if target-abi is absent. + StringRef getTargetABIFromMD(); }; /// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index e6f0d64d071ba..e344bd478d831 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -48,6 +48,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ModRef.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -387,6 +388,26 @@ Function *Function::Create(FunctionType *Ty, LinkageTypes Linkage, return Create(Ty, Linkage, M.getDataLayout().getProgramAddressSpace(), N, &M); } +StringRef Function::getDefaultTargetFeatures(const StringRef TargetABI) { + Triple T(getParent()->getTargetTriple()); + StringRef Attr = ""; + if (T.isRISCV64()) { + if (TargetABI.equals_insensitive("lp64d")) + Attr = "+d"; + else if (TargetABI.equals_insensitive("lp64f")) + Attr = "+f"; + } else if (T.isRISCV32()) { + if (TargetABI.equals_insensitive("ilp32d")) + Attr = "+d"; + else if (TargetABI.equals_insensitive("ilp32f")) + Attr = "+f"; + } else if (T.isARM() || T.isThumb()) { + Attr = "+thumb-mode"; + } + + return Attr; +} + Function *Function::createWithDefaultAttr(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N, diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index c7b9f8744d8d3..3ee53528a825e 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -915,3 +915,11 @@ VersionTuple Module::getDarwinTargetVariantSDKVersion() const { void Module::setDarwinTargetVariantSDKVersion(VersionTuple Version) { addSDKVersionMD(Version, *this, "darwin.target_variant.SDK Version"); } + +StringRef Module::getTargetABIFromMD() { + StringRef TargetABI = ""; + if (auto *TargetABIMD = + dyn_cast_or_null(getModuleFlag("target-abi"))) + TargetABI = TargetABIMD->getString(); + return TargetABI; +} diff --git a/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp b/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp index 2d884078940cc..92b9ece7484a6 100644 --- a/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp +++ b/llvm/lib/Transforms/IPO/CrossDSOCFI.cpp @@ -86,14 +86,20 @@ void CrossDSOCFI::buildCFICheck(Module &M) { "__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx), PointerType::getUnqual(Ctx), PointerType::getUnqual(Ctx)); Function *F = cast(C.getCallee()); + std::string DefaultFeatures = + F->getContext().getDefaultTargetFeatures().str(); // Take over the existing function. The frontend emits a weak stub so that the // linker knows about the symbol; this pass replaces the function body. F->deleteBody(); F->setAlignment(Align(4096)); - Triple T(M.getTargetTriple()); - if (T.isARM() || T.isThumb()) - F->addFnAttr("target-features", "+thumb-mode"); + // Set existing target-features. + if (!DefaultFeatures.empty()) + F->addFnAttr("target-features", DefaultFeatures); + + DefaultFeatures = F->getDefaultTargetFeatures(M.getTargetABIFromMD()); + if (!DefaultFeatures.empty()) + F->addFnAttr("target-features", DefaultFeatures); auto args = F->arg_begin(); Value &CallSiteTypeId = *(args++); diff --git a/llvm/test/Transforms/CrossDSOCFI/riscv.ll b/llvm/test/Transforms/CrossDSOCFI/riscv.ll new file mode 100644 index 0000000000000..9427ff5e8cf0e --- /dev/null +++ b/llvm/test/Transforms/CrossDSOCFI/riscv.ll @@ -0,0 +1,19 @@ +; RUN: opt -S -passes=cross-dso-cfi < %s | FileCheck --check-prefix=RISCV64 %s + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "riscv64-unknown-linux-gnu" + +define signext i8 @f() !type !0 !type !1 { +entry: + ret i8 1 +} + +!llvm.module.flags = !{!2, !3} + +!0 = !{i64 0, !"_ZTSFcvE"} +!1 = !{i64 0, i64 111} +!2 = !{i32 4, !"Cross-DSO CFI", i32 1} +!3 = !{i32 1, !"target-abi", !"lp64d"} + +; RISCV64: define void @__cfi_check({{.*}} #[[A:.*]] align 4096 +; RISCV64: attributes #[[A]] = { {{.*}}"target-features"="+d"