xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMMachineFunctionInfo.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- ARMMachineFunctionInfo.cpp - ARM machine function info ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h"
100b57cec5SDimitry Andric #include "ARMSubtarget.h"
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric using namespace llvm;
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric void ARMFunctionInfo::anchor() {}
150b57cec5SDimitry Andric 
16*5f757f3fSDimitry Andric yaml::ARMFunctionInfo::ARMFunctionInfo(const llvm::ARMFunctionInfo &MFI)
17*5f757f3fSDimitry Andric     : LRSpilled(MFI.isLRSpilled()) {}
18*5f757f3fSDimitry Andric 
19*5f757f3fSDimitry Andric void yaml::ARMFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
20*5f757f3fSDimitry Andric   MappingTraits<ARMFunctionInfo>::mapping(YamlIO, *this);
21*5f757f3fSDimitry Andric }
22*5f757f3fSDimitry Andric 
23*5f757f3fSDimitry Andric void ARMFunctionInfo::initializeBaseYamlFields(
24*5f757f3fSDimitry Andric     const yaml::ARMFunctionInfo &YamlMFI) {
25*5f757f3fSDimitry Andric   LRSpilled = YamlMFI.LRSpilled;
26*5f757f3fSDimitry Andric }
27*5f757f3fSDimitry Andric 
28bdd1243dSDimitry Andric static bool GetBranchTargetEnforcement(const Function &F,
29bdd1243dSDimitry Andric                                        const ARMSubtarget *Subtarget) {
30bdd1243dSDimitry Andric   if (!Subtarget->isMClass() || !Subtarget->hasV7Ops())
314824e7fdSDimitry Andric     return false;
324824e7fdSDimitry Andric 
334824e7fdSDimitry Andric   if (!F.hasFnAttribute("branch-target-enforcement")) {
344824e7fdSDimitry Andric     if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
354824e7fdSDimitry Andric             F.getParent()->getModuleFlag("branch-target-enforcement")))
364824e7fdSDimitry Andric       return BTE->getZExtValue();
374824e7fdSDimitry Andric     return false;
384824e7fdSDimitry Andric   }
394824e7fdSDimitry Andric 
404824e7fdSDimitry Andric   const StringRef BTIEnable =
414824e7fdSDimitry Andric       F.getFnAttribute("branch-target-enforcement").getValueAsString();
42*5f757f3fSDimitry Andric   assert(BTIEnable == "true" || BTIEnable == "false");
43*5f757f3fSDimitry Andric   return BTIEnable == "true";
444824e7fdSDimitry Andric }
454824e7fdSDimitry Andric 
464824e7fdSDimitry Andric // The pair returns values for the ARMFunctionInfo members
474824e7fdSDimitry Andric // SignReturnAddress and SignReturnAddressAll respectively.
484824e7fdSDimitry Andric static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
494824e7fdSDimitry Andric   if (!F.hasFnAttribute("sign-return-address")) {
504824e7fdSDimitry Andric     const Module &M = *F.getParent();
514824e7fdSDimitry Andric     if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
524824e7fdSDimitry Andric             M.getModuleFlag("sign-return-address"))) {
534824e7fdSDimitry Andric       if (Sign->getZExtValue()) {
544824e7fdSDimitry Andric         if (const auto *All = mdconst::extract_or_null<ConstantInt>(
554824e7fdSDimitry Andric                 M.getModuleFlag("sign-return-address-all")))
564824e7fdSDimitry Andric           return {true, All->getZExtValue()};
574824e7fdSDimitry Andric         return {true, false};
584824e7fdSDimitry Andric       }
594824e7fdSDimitry Andric     }
604824e7fdSDimitry Andric     return {false, false};
614824e7fdSDimitry Andric   }
624824e7fdSDimitry Andric 
634824e7fdSDimitry Andric   StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
644824e7fdSDimitry Andric   if (Scope.equals("none"))
654824e7fdSDimitry Andric     return {false, false};
664824e7fdSDimitry Andric 
674824e7fdSDimitry Andric   if (Scope.equals("all"))
684824e7fdSDimitry Andric     return {true, true};
694824e7fdSDimitry Andric 
704824e7fdSDimitry Andric   assert(Scope.equals("non-leaf"));
714824e7fdSDimitry Andric   return {true, false};
724824e7fdSDimitry Andric }
734824e7fdSDimitry Andric 
74bdd1243dSDimitry Andric ARMFunctionInfo::ARMFunctionInfo(const Function &F,
75bdd1243dSDimitry Andric                                  const ARMSubtarget *Subtarget)
76bdd1243dSDimitry Andric     : isThumb(Subtarget->isThumb()), hasThumb2(Subtarget->hasThumb2()),
77bdd1243dSDimitry Andric       IsCmseNSEntry(F.hasFnAttribute("cmse_nonsecure_entry")),
78bdd1243dSDimitry Andric       IsCmseNSCall(F.hasFnAttribute("cmse_nonsecure_call")),
79bdd1243dSDimitry Andric       BranchTargetEnforcement(GetBranchTargetEnforcement(F, Subtarget)) {
80bdd1243dSDimitry Andric   if (Subtarget->isMClass() && Subtarget->hasV7Ops())
81bdd1243dSDimitry Andric     std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
824824e7fdSDimitry Andric }
8381ad6265SDimitry Andric 
8481ad6265SDimitry Andric MachineFunctionInfo *
8581ad6265SDimitry Andric ARMFunctionInfo::clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
8681ad6265SDimitry Andric                        const DenseMap<MachineBasicBlock *, MachineBasicBlock *>
8781ad6265SDimitry Andric                            &Src2DstMBB) const {
8881ad6265SDimitry Andric   return DestMF.cloneInfo<ARMFunctionInfo>(*this);
8981ad6265SDimitry Andric }
90