1//=- RISCVMachineFunctionInfo.cpp - RISC-V machine function info --*- C++ -*-=//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file declares RISCV-specific per-machine-function information.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCVMachineFunctionInfo.h"
14#include "llvm/IR/Module.h"
15
16using namespace llvm;
17
18yaml::RISCVMachineFunctionInfo::RISCVMachineFunctionInfo(
19 const llvm::RISCVMachineFunctionInfo &MFI)
20 : VarArgsFrameIndex(MFI.getVarArgsFrameIndex()),
21 VarArgsSaveSize(MFI.getVarArgsSaveSize()) {}
22
23MachineFunctionInfo *RISCVMachineFunctionInfo::clone(
24 BumpPtrAllocator &Allocator, MachineFunction &DestMF,
25 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
26 const {
27 return DestMF.cloneInfo<RISCVMachineFunctionInfo>(Old: *this);
28}
29
30RISCVMachineFunctionInfo::RISCVMachineFunctionInfo(const Function &F,
31 const RISCVSubtarget *STI) {
32 if (const auto *CFB = mdconst::extract_or_null<ConstantInt>(
33 MD: F.getParent()->getModuleFlag(Key: "cf-protection-branch")))
34 CFProtectionBranch = CFB->getZExtValue() != 0;
35
36 // The default stack probe size is 4096 if the function has no
37 // stack-probe-size attribute. This is a safe default because it is the
38 // smallest possible guard page size.
39 uint64_t ProbeSize = 4096;
40 if (F.hasFnAttribute(Kind: "stack-probe-size"))
41 ProbeSize = F.getFnAttributeAsParsedInteger(Kind: "stack-probe-size");
42 else if (const auto *PS = mdconst::extract_or_null<ConstantInt>(
43 MD: F.getParent()->getModuleFlag(Key: "stack-probe-size")))
44 ProbeSize = PS->getZExtValue();
45 assert(int64_t(ProbeSize) > 0 && "Invalid stack probe size");
46
47 // Round down to the stack alignment.
48 uint64_t StackAlign =
49 STI->getFrameLowering()->getTransientStackAlign().value();
50 ProbeSize = std::max(a: StackAlign, b: alignDown(Value: ProbeSize, Align: StackAlign));
51 StringRef ProbeKind;
52 if (F.hasFnAttribute(Kind: "probe-stack"))
53 ProbeKind = F.getFnAttribute(Kind: "probe-stack").getValueAsString();
54 else if (const auto *PS = dyn_cast_or_null<MDString>(
55 Val: F.getParent()->getModuleFlag(Key: "probe-stack")))
56 ProbeKind = PS->getString();
57 if (ProbeKind.size()) {
58 StackProbeSize = ProbeSize;
59 }
60}
61
62RISCVMachineFunctionInfo::InterruptStackKind
63RISCVMachineFunctionInfo::getInterruptStackKind(
64 const MachineFunction &MF) const {
65 if (!MF.getFunction().hasFnAttribute(Kind: "interrupt"))
66 return InterruptStackKind::None;
67
68 assert(VarArgsSaveSize == 0 &&
69 "Interrupt functions should not having incoming varargs");
70
71 StringRef InterruptVal =
72 MF.getFunction().getFnAttribute(Kind: "interrupt").getValueAsString();
73
74 return StringSwitch<RISCVMachineFunctionInfo::InterruptStackKind>(
75 InterruptVal)
76 .Case(S: "qci-nest", Value: InterruptStackKind::QCINest)
77 .Case(S: "qci-nonest", Value: InterruptStackKind::QCINoNest)
78 .Case(S: "SiFive-CLIC-preemptible",
79 Value: InterruptStackKind::SiFiveCLICPreemptible)
80 .Case(S: "SiFive-CLIC-stack-swap", Value: InterruptStackKind::SiFiveCLICStackSwap)
81 .Case(S: "SiFive-CLIC-preemptible-stack-swap",
82 Value: InterruptStackKind::SiFiveCLICPreemptibleStackSwap)
83 .Default(Value: InterruptStackKind::None);
84}
85
86void yaml::RISCVMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
87 MappingTraits<RISCVMachineFunctionInfo>::mapping(YamlIO, MFI&: *this);
88}
89
90RISCVMachineFunctionInfo::PushPopKind
91RISCVMachineFunctionInfo::getPushPopKind(const MachineFunction &MF) const {
92 // We cannot use fixed locations for the callee saved spill slots if the
93 // function uses a varargs save area.
94 // TODO: Use a separate placement for vararg registers to enable Zcmp.
95 if (VarArgsSaveSize != 0)
96 return PushPopKind::None;
97
98 // SiFive interrupts are not compatible with push/pop.
99 if (useSiFiveInterrupt(MF))
100 return PushPopKind::None;
101
102 // Zcmp is not compatible with the frame pointer convention.
103 if (MF.getSubtarget<RISCVSubtarget>().hasStdExtZcmp() &&
104 !MF.getTarget().Options.DisableFramePointerElim(MF))
105 return PushPopKind::StdExtZcmp;
106
107 // Xqccmp is Zcmp but has a push order compatible with the frame-pointer
108 // convention.
109 if (MF.getSubtarget<RISCVSubtarget>().hasVendorXqccmp())
110 return PushPopKind::VendorXqccmp;
111
112 return PushPopKind::None;
113}
114
115bool RISCVMachineFunctionInfo::hasImplicitFPUpdates(
116 const MachineFunction &MF) const {
117 switch (getInterruptStackKind(MF)) {
118 case InterruptStackKind::QCINest:
119 case InterruptStackKind::QCINoNest:
120 // QC.C.MIENTER and QC.C.MIENTER.NEST both update FP on function entry.
121 return true;
122 default:
123 break;
124 }
125
126 switch (getPushPopKind(MF)) {
127 case PushPopKind::VendorXqccmp:
128 // When using Xqccmp, we will use `QC.CM.PUSHFP` when Frame Pointers are
129 // enabled, which will update FP.
130 return true;
131 default:
132 break;
133 }
134
135 return false;
136}
137
138void RISCVMachineFunctionInfo::initializeBaseYamlFields(
139 const yaml::RISCVMachineFunctionInfo &YamlMFI) {
140 VarArgsFrameIndex = YamlMFI.VarArgsFrameIndex;
141 VarArgsSaveSize = YamlMFI.VarArgsSaveSize;
142}
143
144void RISCVMachineFunctionInfo::addSExt32Register(Register Reg) {
145 SExt32Registers.push_back(Elt: Reg);
146}
147
148bool RISCVMachineFunctionInfo::isSExt32Register(Register Reg) const {
149 return is_contained(Range: SExt32Registers, Element: Reg);
150}
151