LLVM 17.0.0git
RISCVCallLowering.cpp
Go to the documentation of this file.
1//===-- RISCVCallLowering.cpp - Call lowering -------------------*- 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/// \file
10/// This file implements the lowering of LLVM calls to machine code calls for
11/// GlobalISel.
12//
13//===----------------------------------------------------------------------===//
14
15#include "RISCVCallLowering.h"
16#include "RISCVISelLowering.h"
17#include "RISCVSubtarget.h"
20
21using namespace llvm;
22
23namespace {
24
25struct RISCVOutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {
26private:
27 // The function used internally to assign args - we ignore the AssignFn stored
28 // by OutgoingValueAssigner since RISC-V implements its CC using a custom
29 // function with a different signature.
31
32 // Whether this is assigning args for a return.
33 bool IsRet;
34
35public:
36 RISCVOutgoingValueAssigner(
37 RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
38 : CallLowering::OutgoingValueAssigner(nullptr),
39 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
40
41 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
43 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
44 CCState &State) override {
46 const DataLayout &DL = MF.getDataLayout();
47 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
48
49 return RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
50 LocInfo, Flags, State, /*IsFixed=*/true, IsRet,
51 Info.Ty, *Subtarget.getTargetLowering(),
52 /*FirstMaskArgument=*/std::nullopt);
53 }
54};
55
56struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
57 RISCVOutgoingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI,
59 : OutgoingValueHandler(B, MRI), MIB(MIB) {}
60
62
63 Register getStackAddress(uint64_t MemSize, int64_t Offset,
65 ISD::ArgFlagsTy Flags) override {
66 llvm_unreachable("not implemented");
67 }
68
69 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
70 MachinePointerInfo &MPO, CCValAssign &VA) override {
71 llvm_unreachable("not implemented");
72 }
73
74 void assignValueToReg(Register ValVReg, Register PhysReg,
75 CCValAssign VA) override {
76 Register ExtReg = extendRegister(ValVReg, VA);
77 MIRBuilder.buildCopy(PhysReg, ExtReg);
78 MIB.addUse(PhysReg, RegState::Implicit);
79 }
80};
81
82struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
83private:
84 // The function used internally to assign args - we ignore the AssignFn stored
85 // by IncomingValueAssigner since RISC-V implements its CC using a custom
86 // function with a different signature.
88
89 // Whether this is assigning args from a return.
90 bool IsRet;
91
92public:
93 RISCVIncomingValueAssigner(
94 RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
95 : CallLowering::IncomingValueAssigner(nullptr),
96 RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}
97
98 bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
100 const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
101 CCState &State) override {
103 const DataLayout &DL = MF.getDataLayout();
104 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
105
106 return RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
107 LocInfo, Flags, State, /*IsFixed=*/true, IsRet,
108 Info.Ty, *Subtarget.getTargetLowering(),
109 /*FirstMaskArgument=*/std::nullopt);
110 }
111};
112
113struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {
114 RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
115 : IncomingValueHandler(B, MRI) {}
116
117 Register getStackAddress(uint64_t MemSize, int64_t Offset,
119 ISD::ArgFlagsTy Flags) override {
120 llvm_unreachable("not implemented");
121 }
122
123 void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
124 MachinePointerInfo &MPO, CCValAssign &VA) override {
125 llvm_unreachable("not implemented");
126 }
127
128 void assignValueToReg(Register ValVReg, Register PhysReg,
129 CCValAssign VA) override {
130 // Copy argument received in physical register to desired VReg.
131 MIRBuilder.getMBB().addLiveIn(PhysReg);
132 MIRBuilder.buildCopy(ValVReg, PhysReg);
133 }
134};
135
136} // namespace
137
139 : CallLowering(&TLI) {}
140
141bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
142 const Value *Val,
143 ArrayRef<Register> VRegs,
144 MachineInstrBuilder &Ret) const {
145 if (!Val)
146 return true;
147
148 // TODO: Only integer, pointer and aggregate types are supported now.
149 if (!Val->getType()->isIntOrPtrTy() && !Val->getType()->isAggregateType())
150 return false;
151
152 MachineFunction &MF = MIRBuilder.getMF();
153 const DataLayout &DL = MF.getDataLayout();
154 const Function &F = MF.getFunction();
155 CallingConv::ID CC = F.getCallingConv();
156
157 ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);
159
160 SmallVector<ArgInfo, 4> SplitRetInfos;
161 splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC);
162
163 RISCVOutgoingValueAssigner Assigner(
165 /*IsRet=*/true);
166 RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret);
167 return determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,
168 MIRBuilder, CC, F.isVarArg());
169}
170
172 const Value *Val, ArrayRef<Register> VRegs,
173 FunctionLoweringInfo &FLI) const {
174 assert(!Val == VRegs.empty() && "Return value without a vreg");
175 MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(RISCV::PseudoRET);
176
177 if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret))
178 return false;
179
180 MIRBuilder.insertInstr(Ret);
181 return true;
182}
183
185 const Function &F,
187 FunctionLoweringInfo &FLI) const {
188 // Early exit if there are no arguments.
189 if (F.arg_empty())
190 return true;
191
192 // TODO: Support vararg functions.
193 if (F.isVarArg())
194 return false;
195
196 // TODO: Support all argument types.
197 for (auto &Arg : F.args()) {
198 if (Arg.getType()->isIntegerTy())
199 continue;
200 if (Arg.getType()->isPointerTy())
201 continue;
202 return false;
203 }
204
205 MachineFunction &MF = MIRBuilder.getMF();
206 const DataLayout &DL = MF.getDataLayout();
207 CallingConv::ID CC = F.getCallingConv();
208
209 SmallVector<ArgInfo, 32> SplitArgInfos;
210 unsigned Index = 0;
211 for (auto &Arg : F.args()) {
212 // Construct the ArgInfo object from destination register and argument type.
213 ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);
215
216 // Handle any required merging from split value types from physical
217 // registers into the desired VReg. ArgInfo objects are constructed
218 // correspondingly and appended to SplitArgInfos.
219 splitToValueTypes(AInfo, SplitArgInfos, DL, CC);
220
221 ++Index;
222 }
223
224 RISCVIncomingValueAssigner Assigner(
226 /*IsRet=*/false);
227 RISCVIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());
228
229 return determineAndHandleAssignments(Handler, Assigner, SplitArgInfos,
230 MIRBuilder, CC, F.isVarArg());
231}
232
234 CallLoweringInfo &Info) const {
235 return false;
236}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
uint64_t Addr
#define F(x, y, z)
Definition: MD5.cpp:55
This file declares the MachineIRBuilder class.
This file describes how to lower LLVM calls to machine code calls.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:158
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
CCValAssign - Represent assignment of one arg/retval to a location.
bool determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner, SmallVectorImpl< ArgInfo > &Args, MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, bool IsVarArg, ArrayRef< Register > ThisReturnRegs=std::nullopt) const
Invoke ValueAssigner::assignArg on each of the given Args and then use Handler to move them to the as...
void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl< ArgInfo > &SplitArgs, const DataLayout &DL, CallingConv::ID CallConv, SmallVectorImpl< uint64_t > *Offsets=nullptr) const
Break OrigArgInfo into one or more pieces the calling convention can process, returned in SplitArgs.
void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Machine Value Type.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)
Insert an existing instruction at the insertion point.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val, ArrayRef< Register > VRegs, FunctionLoweringInfo &FLI) const override
This hook behaves as the extended lowerReturn function, but for targets that do not support swifterro...
bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override
This hook must be implemented to lower the given call instruction, including argument and return valu...
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef< ArrayRef< Register > > VRegs, FunctionLoweringInfo &FLI) const override
This hook must be implemented to lower the incoming (formal) arguments, described by VRegs,...
RISCVCallLowering(const RISCVTargetLowering &TLI)
RISCVABI::ABI getTargetABI() const
const RISCVTargetLowering * getTargetLowering() const override
bool RISCVCCAssignFn(const DataLayout &DL, RISCVABI::ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, std::optional< unsigned > FirstMaskArgument)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition: Type.h:295
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
Definition: Type.h:244
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:41
bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, std::optional< unsigned > FirstMaskArgument)
bool CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, std::optional< unsigned > FirstMaskArgument)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
Helper struct shared between Function Specialization and SCCP Solver.
Definition: SCCPSolver.h:51
Base class for ValueHandlers used for arguments coming into the current function, or for return value...
Definition: CallLowering.h:317
void assignValueToReg(Register ValVReg, Register PhysReg, CCValAssign VA) override
Provides a default implementation for argument handling.
Base class for ValueHandlers used for arguments passed to a function call, or for return values.
Definition: CallLowering.h:332
virtual bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, const ArgInfo &Info, ISD::ArgFlagsTy Flags, CCState &State)
Wrap call to (typically tablegenerated CCAssignFn).
Definition: CallLowering.h:185
Register extendRegister(Register ValReg, CCValAssign &VA, unsigned MaxSizeBits=0)
Extend a register to the location type given in VA, capped at extending to at most MaxSize bits.
virtual Register getStackAddress(uint64_t MemSize, int64_t Offset, MachinePointerInfo &MPO, ISD::ArgFlagsTy Flags)=0
Materialize a VReg containing the address of the specified stack-based object.
virtual void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, MachinePointerInfo &MPO, CCValAssign &VA)=0
The specified value has been assigned to a stack location.
virtual void assignValueToReg(Register ValVReg, Register PhysReg, CCValAssign VA)=0
The specified value has been assigned to a physical register, handle the appropriate COPY (either to ...
Extended Value Type.
Definition: ValueTypes.h:34
This class contains a discriminated union of information about pointers in memory operands,...