LLVM 23.0.0git
WebAssemblyCallLowering.cpp
Go to the documentation of this file.
1//===-- WebAssemblyCallLowering.cpp - Call lowering for GlobalISel -*- 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
29#include "llvm/IR/DataLayout.h"
30#include "llvm/IR/DebugLoc.h"
31#include "llvm/IR/Value.h"
33
34#define DEBUG_TYPE "wasm-call-lowering"
35
36using namespace llvm;
37
38// Test whether the given calling convention is supported.
40 // We currently support the language-independent target-independent
41 // conventions. We don't yet have a way to annotate calls with properties like
42 // "cold", and we don't have any call-clobbered registers, so these are mostly
43 // all handled the same.
44 return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
45 CallConv == CallingConv::Cold ||
46 CallConv == CallingConv::PreserveMost ||
47 CallConv == CallingConv::PreserveAll ||
48 CallConv == CallingConv::CXX_FAST_TLS ||
50 CallConv == CallingConv::Swift;
51}
52
53static unsigned extendOpFromFlags(ISD::ArgFlagsTy Flags) {
54 if (Flags.isSExt())
55 return TargetOpcode::G_SEXT;
56 if (Flags.isZExt())
57 return TargetOpcode::G_ZEXT;
58 return TargetOpcode::G_ANYEXT;
59}
60
61static LLT getLLTForWasmMVT(MVT Ty, const DataLayout &DL) {
62 if (Ty == MVT::externref) {
63 return LLT::pointer(
65 DL.getPointerSizeInBits(
67 }
68
69 if (Ty == MVT::funcref) {
70 return LLT::pointer(
72 DL.getPointerSizeInBits(
74 }
75
76 return llvm::getLLTForMVT(Ty);
77}
78
82
90
92 const Value *Val,
95 Register SwiftErrorVReg) const {
96 MachineFunction &MF = MIRBuilder.getMF();
97 const WebAssemblySubtarget &Subtarget =
99 const RegisterBankInfo &RBI = *Subtarget.getRegBankInfo();
100 const Function &F = MF.getFunction();
103 const DataLayout &DL = F.getDataLayout();
104
105 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(WebAssembly::RETURN);
106
107 assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
108 "Return value without a vreg or vice versa");
109
110 if (Val) {
111 LLVMContext &Ctx = Val->getType()->getContext();
112
113 if (!FLI.CanLowerReturn) {
114 insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister);
115 } else {
116 SmallVector<EVT, 4> SplitEVTs;
117 ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs);
118 assert(VRegs.size() == SplitEVTs.size() &&
119 "For each split Type there should be exactly one VReg.");
120
121 SmallVector<ArgInfo, 8> SplitRets;
122 CallingConv::ID CallConv = F.getCallingConv();
123
124 unsigned RetIdx = 0;
125 for (EVT SplitEVT : SplitEVTs) {
126 Register CurVReg = VRegs[RetIdx];
127 ArgInfo CurRetInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
128 setArgFlags(CurRetInfo, AttributeList::ReturnIndex, DL, F);
129
130 splitToValueTypes(CurRetInfo, SplitRets, DL, CallConv);
131 ++RetIdx;
132 }
133
134 for (ArgInfo &Ret : SplitRets) {
135 const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
136 const MVT NewVT =
137 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
138 const LLT OrigLLT =
139 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
140 const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);
141
142 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);
143
144 // If we need to split the type over multiple regs, check it's a
145 // scenario we currently support.
146 const unsigned NumParts =
147 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
148
149 const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
150 Ret.Flags.clear();
151
152 for (unsigned Part = 0; Part < NumParts; ++Part) {
153 ISD::ArgFlagsTy Flags = OrigFlags;
154
155 if (Part == 0) {
156 Flags.setSplit();
157 } else {
158 Flags.setOrigAlign(Align(1));
159 if (Part == NumParts - 1)
160 Flags.setSplitEnd();
161 }
162
163 Ret.Flags.push_back(Flags);
164 }
165
166 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
167 if (NumParts != 1 || OrigLLT != NewLLT) {
168 // If we can't directly assign the register, we need one or more
169 // intermediate values.
170 Ret.Regs.resize(NumParts);
171
172 // For each split register, create and assign a vreg that will store
173 // the incoming component of the larger value. These will later be
174 // merged to form the final vreg.
175 for (unsigned Part = 0; Part < NumParts; ++Part) {
176 Register NewOutReg = MRI.createGenericVirtualRegister(NewLLT);
177
178 if (!RBI.constrainGenericRegister(NewOutReg, NewRegClass, MRI))
180 "Couldn't constrain brand-new register?");
181
182 MIB.addUse(NewOutReg);
183
184 Ret.Regs[Part] = NewOutReg;
185 }
186
187 buildCopyToRegs(MIRBuilder, Ret.Regs, Ret.OrigRegs[0], OrigLLT,
188 NewLLT, extendOpFromFlags(Ret.Flags[0]));
189 } else {
190 MIB.addUse(Ret.Regs[0]);
191 }
192 }
193 }
194 }
195
196 if (SwiftErrorVReg) {
198 "Wasm does not `supportSwiftError`, yet SwiftErrorVReg is "
199 "improperly valid.");
200 }
201
202 MIRBuilder.insertInstr(MIB);
203 return true;
204}
205
206static unsigned getWasmArgumentOpcode(MVT ArgType) {
207 switch (ArgType.SimpleTy) {
208 case MVT::i32:
209 return WebAssembly::ARGUMENT_i32;
210 case MVT::i64:
211 return WebAssembly::ARGUMENT_i64;
212 case MVT::f32:
213 return WebAssembly::ARGUMENT_f32;
214 case MVT::f64:
215 return WebAssembly::ARGUMENT_f64;
216
217 case MVT::funcref:
218 return WebAssembly::ARGUMENT_funcref;
219 case MVT::externref:
220 return WebAssembly::ARGUMENT_externref;
221 case MVT::exnref:
222 return WebAssembly::ARGUMENT_exnref;
223
224 case MVT::v16i8:
225 return WebAssembly::ARGUMENT_v16i8;
226 case MVT::v8i16:
227 return WebAssembly::ARGUMENT_v8i16;
228 case MVT::v4i32:
229 return WebAssembly::ARGUMENT_v4i32;
230 case MVT::v2i64:
231 return WebAssembly::ARGUMENT_v2i64;
232 case MVT::v8f16:
233 return WebAssembly::ARGUMENT_v8f16;
234 case MVT::v4f32:
235 return WebAssembly::ARGUMENT_v4f32;
236 case MVT::v2f64:
237 return WebAssembly::ARGUMENT_v2f64;
238 default:
239 break;
240 }
241 llvm_unreachable("Found unexpected type for Wasm argument");
242}
243
245 MachineIRBuilder &MIRBuilder, const Function &F,
247 MachineFunction &MF = MIRBuilder.getMF();
250 const DataLayout &DL = F.getDataLayout();
252 const WebAssemblySubtarget &Subtarget =
254 const WebAssemblyRegisterInfo &TRI = *Subtarget.getRegisterInfo();
255 const WebAssemblyInstrInfo &TII = *Subtarget.getInstrInfo();
256 const RegisterBankInfo &RBI = *Subtarget.getRegBankInfo();
257
258 LLVMContext &Ctx = MIRBuilder.getContext();
259 const CallingConv::ID CallConv = F.getCallingConv();
260
261 if (!callingConvSupported(CallConv)) {
262 return false;
263 }
264
265 MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
266 MF.front().addLiveIn(WebAssembly::ARGUMENTS);
267
268 SmallVector<ArgInfo, 8> SplitArgs;
269
270 if (!FLI.CanLowerReturn) {
271 insertSRetIncomingArgument(F, SplitArgs, FLI.DemoteRegister, MRI, DL);
272 }
273
274 unsigned ArgIdx = 0;
275 bool HasSwiftErrorArg = false;
276 bool HasSwiftSelfArg = false;
277 for (const Argument &Arg : F.args()) {
278 ArgInfo OrigArg{VRegs[ArgIdx], Arg.getType(), ArgIdx};
279 setArgFlags(OrigArg, ArgIdx + AttributeList::FirstArgIndex, DL, F);
280
281 HasSwiftSelfArg |= Arg.hasSwiftSelfAttr();
282 HasSwiftErrorArg |= Arg.hasSwiftErrorAttr();
283 if (Arg.hasInAllocaAttr()) {
284 return false;
285 }
286 if (Arg.hasNestAttr()) {
287 return false;
288 }
289 splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
290 ++ArgIdx;
291 }
292
293 unsigned FinalArgIdx = 0;
294 for (ArgInfo &Arg : SplitArgs) {
295 const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
296 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
297 const LLT OrigLLT =
298 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
299 const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);
300
301 // If we need to split the type over multiple regs, check it's a scenario
302 // we currently support.
303 const unsigned NumParts =
304 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
305
306 const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
307 Arg.Flags.clear();
308
309 for (unsigned Part = 0; Part < NumParts; ++Part) {
310 ISD::ArgFlagsTy Flags = OrigFlags;
311 if (Part == 0) {
312 Flags.setSplit();
313 } else {
314 Flags.setOrigAlign(Align(1));
315 if (Part == NumParts - 1)
316 Flags.setSplitEnd();
317 }
318
319 Arg.Flags.push_back(Flags);
320 }
321
322 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
323 if (NumParts != 1 || OrigLLT != NewLLT) {
324 // If we can't directly assign the register, we need one or more
325 // intermediate values.
326 Arg.Regs.resize(NumParts);
327
328 // For each split register, create and assign a vreg that will store
329 // the incoming component of the larger value. These will later be
330 // merged to form the final vreg.
331 for (unsigned Part = 0; Part < NumParts; ++Part) {
332 Arg.Regs[Part] = MRI.createGenericVirtualRegister(NewLLT);
333 }
334 }
335
336 for (unsigned Part = 0; Part < NumParts; ++Part) {
337 MachineInstrBuilder ArgInst =
338 MIRBuilder.buildInstr(getWasmArgumentOpcode(NewVT))
339 .addDef(Arg.Regs[Part])
340 .addImm(FinalArgIdx);
341
342 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, *ArgInst,
343 ArgInst->getDesc(), ArgInst->getOperand(0), 0);
344 MFI->addParam(NewVT);
345 ++FinalArgIdx;
346 }
347
348 if (OrigVT != NewVT) {
349 buildCopyFromRegs(MIRBuilder, Arg.OrigRegs, Arg.Regs, OrigLLT, NewLLT,
350 Arg.Flags[0]);
351 }
352 }
353
354 // For swiftcc, emit additional swiftself and swifterror arguments
355 // if there aren't. These additional arguments are also added for callee
356 // signature They are necessary to match callee and caller signature for
357 // indirect call.
358 if (CallConv == CallingConv::Swift) {
359 const MVT PtrVT = TLI.getPointerTy(DL);
360
361 if (!HasSwiftSelfArg) {
362 MFI->addParam(PtrVT);
363 }
364 if (!HasSwiftErrorArg) {
365 MFI->addParam(PtrVT);
366 }
367 }
368
369 // Varargs are copied into a buffer allocated by the caller, and a pointer to
370 // the buffer is passed as an argument.
371 if (F.isVarArg()) {
372 const MVT PtrVT = TLI.getPointerTy(DL, 0);
373 const LLT PtrLLT = LLT::pointer(0, DL.getPointerSizeInBits(0));
374 Register VarargVreg = MF.getRegInfo().createGenericVirtualRegister(PtrLLT);
375
376 MFI->setVarargBufferVreg(VarargVreg);
377
378 MachineInstrBuilder ArgInst =
379 MIRBuilder.buildInstr(getWasmArgumentOpcode(PtrVT))
380 .addDef(VarargVreg)
381 .addImm(FinalArgIdx);
382
383 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, *ArgInst,
384 ArgInst->getDesc(), ArgInst->getOperand(0), 0);
385
386 MFI->addParam(PtrVT);
387 ++FinalArgIdx;
388 }
389
390 // Record the number and types of arguments and results.
391 SmallVector<MVT, 4> Params;
394 MF.getFunction(), MF.getTarget(), Params, Results);
395 for (MVT VT : Results)
396 MFI->addResult(VT);
397
398 // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
399 // the param logic here with ComputeSignatureVTs
400 assert(MFI->getParams().size() == Params.size() &&
401 std::equal(MFI->getParams().begin(), MFI->getParams().end(),
402 Params.begin()));
403 return true;
404}
405
407 CallLoweringInfo &Info) const {
408 return false;
409}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static unsigned extendOpFromFlags(llvm::ISD::ArgFlagsTy Flags)
const HexagonInstrInfo * TII
Implement a low-level type suitable for MachineInstr level instruction selection.
#define F(x, y, z)
Definition MD5.cpp:54
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
static bool callingConvSupported(CallingConv::ID CallConv)
static unsigned getWasmArgumentOpcode(MVT ArgType)
static LLT getLLTForWasmMVT(MVT Ty, const DataLayout &DL)
static unsigned extendOpFromFlags(ISD::ArgFlagsTy Flags)
This file describes how to lower LLVM calls to machine code calls.
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG.
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file contains the WebAssembly implementation of the WebAssemblyRegisterInfo class.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file contains the declaration of the WebAssembly-specific utility functions.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:137
void insertSRetIncomingArgument(const Function &F, SmallVectorImpl< ArgInfo > &SplitArgs, Register &DemoteReg, MachineRegisterInfo &MRI, const DataLayout &DL) const
Insert the hidden sret ArgInfo to the beginning of SplitArgs.
void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl< ArgInfo > &SplitArgs, const DataLayout &DL, CallingConv::ID CallConv, SmallVectorImpl< TypeSize > *Offsets=nullptr) const
Break OrigArgInfo into one or more pieces the calling convention can process, returned in SplitArgs.
static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef< Register > DstRegs, Register SrcReg, LLT SrcTy, LLT PartTy, unsigned ExtendOp=TargetOpcode::G_ANYEXT)
Create a sequence of instructions to expand the value in SrcReg (of type SrcTy) to the types in DstRe...
void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy, ArrayRef< Register > VRegs, Register DemoteReg) const
Store the return value given by VRegs into stack starting at the offset specified in DemoteReg.
static void buildCopyFromRegs(MachineIRBuilder &B, ArrayRef< Register > OrigRegs, ArrayRef< Register > Regs, LLT LLTy, LLT PartLLT, const ISD::ArgFlagsTy Flags)
Create a sequence of instructions to combine pieces split into register typed values to the original ...
CallLowering(const TargetLowering *TLI)
const TargetLowering * getTLI() const
Getter for generic TargetLowering class.
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:64
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
bool CanLowerReturn
CanLowerReturn - true iff the function's return value can be lowered to registers.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:211
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Machine Value Type.
SimpleValueType SimpleTy
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)
Insert an existing instruction at the insertion point.
LLVMContext & getContext() const
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
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, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef< Register > VRegs, FunctionLoweringInfo &FLI, Register SwiftErrorVReg) const override
This hook must be implemented to lower outgoing return values, described by Val, into the specified v...
WebAssemblyCallLowering(const WebAssemblyTargetLowering &TLI)
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 canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv, SmallVectorImpl< BaseArgInfo > &Outs, bool IsVarArg) const override
This hook must be implemented to check whether the return values described by Outs can fit into the r...
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,...
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const std::vector< MVT > & getParams() const
const WebAssemblyInstrInfo * getInstrInfo() const override
const WebAssemblyRegisterInfo * getRegisterInfo() const override
const RegisterBankInfo * getRegBankInfo() const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ Swift
Calling convention for Swift.
Definition CallingConv.h:69
@ PreserveMost
Used for runtime calls that preserves most registers.
Definition CallingConv.h:63
@ CXX_FAST_TLS
Used for access functions.
Definition CallingConv.h:72
@ WASM_EmscriptenInvoke
For emscripten __invoke_* functions.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
Definition CallingConv.h:47
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
Definition CallingConv.h:66
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
bool canLowerReturn(size_t ResultSize, const WebAssemblySubtarget *Subtarget)
Returns true if the function's return value(s) can be lowered directly, i.e., not indirectly via a po...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
Definition Utils.cpp:56
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, const Function &ContextFunc, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl< EVT > &ValueVTs, SmallVectorImpl< EVT > *MemVTs=nullptr, SmallVectorImpl< TypeSize > *Offsets=nullptr, TypeSize StartingOffset=TypeSize::getZero())
ComputeValueVTs - Given an LLVM IR type, compute a sequence of EVTs that represent all the individual...
Definition Analysis.cpp:119
LLVM_ABI LLT getLLTForMVT(MVT Ty)
Get a rough equivalent of an LLT for a given MVT.
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL)
Construct a low-level type based on an LLVM type.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.