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