181ad6265SDimitry Andric //===--- SPIRVCallLowering.cpp - Call lowering ------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file implements the lowering of LLVM calls to machine code calls for 1081ad6265SDimitry Andric // GlobalISel. 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #include "SPIRVCallLowering.h" 1581ad6265SDimitry Andric #include "MCTargetDesc/SPIRVBaseInfo.h" 1681ad6265SDimitry Andric #include "SPIRV.h" 1781ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h" 1881ad6265SDimitry Andric #include "SPIRVISelLowering.h" 1981ad6265SDimitry Andric #include "SPIRVRegisterInfo.h" 2081ad6265SDimitry Andric #include "SPIRVSubtarget.h" 2181ad6265SDimitry Andric #include "SPIRVUtils.h" 2281ad6265SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h" 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric using namespace llvm; 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric SPIRVCallLowering::SPIRVCallLowering(const SPIRVTargetLowering &TLI, 2781ad6265SDimitry Andric SPIRVGlobalRegistry *GR) 28*fcaf7f86SDimitry Andric : CallLowering(&TLI), GR(GR) {} 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric bool SPIRVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 3181ad6265SDimitry Andric const Value *Val, ArrayRef<Register> VRegs, 3281ad6265SDimitry Andric FunctionLoweringInfo &FLI, 3381ad6265SDimitry Andric Register SwiftErrorVReg) const { 3481ad6265SDimitry Andric // Currently all return types should use a single register. 3581ad6265SDimitry Andric // TODO: handle the case of multiple registers. 3681ad6265SDimitry Andric if (VRegs.size() > 1) 3781ad6265SDimitry Andric return false; 38*fcaf7f86SDimitry Andric if (Val) { 39*fcaf7f86SDimitry Andric const auto &STI = MIRBuilder.getMF().getSubtarget(); 4081ad6265SDimitry Andric return MIRBuilder.buildInstr(SPIRV::OpReturnValue) 4181ad6265SDimitry Andric .addUse(VRegs[0]) 42*fcaf7f86SDimitry Andric .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 43*fcaf7f86SDimitry Andric *STI.getRegBankInfo()); 44*fcaf7f86SDimitry Andric } 4581ad6265SDimitry Andric MIRBuilder.buildInstr(SPIRV::OpReturn); 4681ad6265SDimitry Andric return true; 4781ad6265SDimitry Andric } 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric // Based on the LLVM function attributes, get a SPIR-V FunctionControl. 5081ad6265SDimitry Andric static uint32_t getFunctionControl(const Function &F) { 5181ad6265SDimitry Andric uint32_t FuncControl = static_cast<uint32_t>(SPIRV::FunctionControl::None); 5281ad6265SDimitry Andric if (F.hasFnAttribute(Attribute::AttrKind::AlwaysInline)) { 5381ad6265SDimitry Andric FuncControl |= static_cast<uint32_t>(SPIRV::FunctionControl::Inline); 5481ad6265SDimitry Andric } 5581ad6265SDimitry Andric if (F.hasFnAttribute(Attribute::AttrKind::ReadNone)) { 5681ad6265SDimitry Andric FuncControl |= static_cast<uint32_t>(SPIRV::FunctionControl::Pure); 5781ad6265SDimitry Andric } 5881ad6265SDimitry Andric if (F.hasFnAttribute(Attribute::AttrKind::ReadOnly)) { 5981ad6265SDimitry Andric FuncControl |= static_cast<uint32_t>(SPIRV::FunctionControl::Const); 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric if (F.hasFnAttribute(Attribute::AttrKind::NoInline)) { 6281ad6265SDimitry Andric FuncControl |= static_cast<uint32_t>(SPIRV::FunctionControl::DontInline); 6381ad6265SDimitry Andric } 6481ad6265SDimitry Andric return FuncControl; 6581ad6265SDimitry Andric } 6681ad6265SDimitry Andric 67*fcaf7f86SDimitry Andric static ConstantInt *getConstInt(MDNode *MD, unsigned NumOp) { 68*fcaf7f86SDimitry Andric if (MD->getNumOperands() > NumOp) { 69*fcaf7f86SDimitry Andric auto *CMeta = dyn_cast<ConstantAsMetadata>(MD->getOperand(NumOp)); 70*fcaf7f86SDimitry Andric if (CMeta) 71*fcaf7f86SDimitry Andric return dyn_cast<ConstantInt>(CMeta->getValue()); 72*fcaf7f86SDimitry Andric } 73*fcaf7f86SDimitry Andric return nullptr; 74*fcaf7f86SDimitry Andric } 75*fcaf7f86SDimitry Andric 76*fcaf7f86SDimitry Andric // This code restores function args/retvalue types for composite cases 77*fcaf7f86SDimitry Andric // because the final types should still be aggregate whereas they're i32 78*fcaf7f86SDimitry Andric // during the translation to cope with aggregate flattening etc. 79*fcaf7f86SDimitry Andric static FunctionType *getOriginalFunctionType(const Function &F) { 80*fcaf7f86SDimitry Andric auto *NamedMD = F.getParent()->getNamedMetadata("spv.cloned_funcs"); 81*fcaf7f86SDimitry Andric if (NamedMD == nullptr) 82*fcaf7f86SDimitry Andric return F.getFunctionType(); 83*fcaf7f86SDimitry Andric 84*fcaf7f86SDimitry Andric Type *RetTy = F.getFunctionType()->getReturnType(); 85*fcaf7f86SDimitry Andric SmallVector<Type *, 4> ArgTypes; 86*fcaf7f86SDimitry Andric for (auto &Arg : F.args()) 87*fcaf7f86SDimitry Andric ArgTypes.push_back(Arg.getType()); 88*fcaf7f86SDimitry Andric 89*fcaf7f86SDimitry Andric auto ThisFuncMDIt = 90*fcaf7f86SDimitry Andric std::find_if(NamedMD->op_begin(), NamedMD->op_end(), [&F](MDNode *N) { 91*fcaf7f86SDimitry Andric return isa<MDString>(N->getOperand(0)) && 92*fcaf7f86SDimitry Andric cast<MDString>(N->getOperand(0))->getString() == F.getName(); 93*fcaf7f86SDimitry Andric }); 94*fcaf7f86SDimitry Andric // TODO: probably one function can have numerous type mutations, 95*fcaf7f86SDimitry Andric // so we should support this. 96*fcaf7f86SDimitry Andric if (ThisFuncMDIt != NamedMD->op_end()) { 97*fcaf7f86SDimitry Andric auto *ThisFuncMD = *ThisFuncMDIt; 98*fcaf7f86SDimitry Andric MDNode *MD = dyn_cast<MDNode>(ThisFuncMD->getOperand(1)); 99*fcaf7f86SDimitry Andric assert(MD && "MDNode operand is expected"); 100*fcaf7f86SDimitry Andric ConstantInt *Const = getConstInt(MD, 0); 101*fcaf7f86SDimitry Andric if (Const) { 102*fcaf7f86SDimitry Andric auto *CMeta = dyn_cast<ConstantAsMetadata>(MD->getOperand(1)); 103*fcaf7f86SDimitry Andric assert(CMeta && "ConstantAsMetadata operand is expected"); 104*fcaf7f86SDimitry Andric assert(Const->getSExtValue() >= -1); 105*fcaf7f86SDimitry Andric // Currently -1 indicates return value, greater values mean 106*fcaf7f86SDimitry Andric // argument numbers. 107*fcaf7f86SDimitry Andric if (Const->getSExtValue() == -1) 108*fcaf7f86SDimitry Andric RetTy = CMeta->getType(); 109*fcaf7f86SDimitry Andric else 110*fcaf7f86SDimitry Andric ArgTypes[Const->getSExtValue()] = CMeta->getType(); 111*fcaf7f86SDimitry Andric } 112*fcaf7f86SDimitry Andric } 113*fcaf7f86SDimitry Andric 114*fcaf7f86SDimitry Andric return FunctionType::get(RetTy, ArgTypes, F.isVarArg()); 115*fcaf7f86SDimitry Andric } 116*fcaf7f86SDimitry Andric 11781ad6265SDimitry Andric bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 11881ad6265SDimitry Andric const Function &F, 11981ad6265SDimitry Andric ArrayRef<ArrayRef<Register>> VRegs, 12081ad6265SDimitry Andric FunctionLoweringInfo &FLI) const { 12181ad6265SDimitry Andric assert(GR && "Must initialize the SPIRV type registry before lowering args."); 122753f127fSDimitry Andric GR->setCurrentFunc(MIRBuilder.getMF()); 12381ad6265SDimitry Andric 12481ad6265SDimitry Andric // Assign types and names to all args, and store their types for later. 125*fcaf7f86SDimitry Andric FunctionType *FTy = getOriginalFunctionType(F); 126*fcaf7f86SDimitry Andric SmallVector<SPIRVType *, 4> ArgTypeVRegs; 12781ad6265SDimitry Andric if (VRegs.size() > 0) { 12881ad6265SDimitry Andric unsigned i = 0; 12981ad6265SDimitry Andric for (const auto &Arg : F.args()) { 13081ad6265SDimitry Andric // Currently formal args should use single registers. 13181ad6265SDimitry Andric // TODO: handle the case of multiple registers. 13281ad6265SDimitry Andric if (VRegs[i].size() > 1) 13381ad6265SDimitry Andric return false; 134*fcaf7f86SDimitry Andric Type *ArgTy = FTy->getParamType(i); 135*fcaf7f86SDimitry Andric SPIRV::AccessQualifier AQ = SPIRV::AccessQualifier::ReadWrite; 136*fcaf7f86SDimitry Andric MDNode *Node = F.getMetadata("kernel_arg_access_qual"); 137*fcaf7f86SDimitry Andric if (Node && i < Node->getNumOperands()) { 138*fcaf7f86SDimitry Andric StringRef AQString = cast<MDString>(Node->getOperand(i))->getString(); 139*fcaf7f86SDimitry Andric if (AQString.compare("read_only") == 0) 140*fcaf7f86SDimitry Andric AQ = SPIRV::AccessQualifier::ReadOnly; 141*fcaf7f86SDimitry Andric else if (AQString.compare("write_only") == 0) 142*fcaf7f86SDimitry Andric AQ = SPIRV::AccessQualifier::WriteOnly; 143*fcaf7f86SDimitry Andric } 144*fcaf7f86SDimitry Andric auto *SpirvTy = GR->assignTypeToVReg(ArgTy, VRegs[i][0], MIRBuilder, AQ); 145*fcaf7f86SDimitry Andric ArgTypeVRegs.push_back(SpirvTy); 14681ad6265SDimitry Andric 14781ad6265SDimitry Andric if (Arg.hasName()) 14881ad6265SDimitry Andric buildOpName(VRegs[i][0], Arg.getName(), MIRBuilder); 14981ad6265SDimitry Andric if (Arg.getType()->isPointerTy()) { 15081ad6265SDimitry Andric auto DerefBytes = static_cast<unsigned>(Arg.getDereferenceableBytes()); 15181ad6265SDimitry Andric if (DerefBytes != 0) 15281ad6265SDimitry Andric buildOpDecorate(VRegs[i][0], MIRBuilder, 15381ad6265SDimitry Andric SPIRV::Decoration::MaxByteOffset, {DerefBytes}); 15481ad6265SDimitry Andric } 15581ad6265SDimitry Andric if (Arg.hasAttribute(Attribute::Alignment)) { 156*fcaf7f86SDimitry Andric auto Alignment = static_cast<unsigned>( 157*fcaf7f86SDimitry Andric Arg.getAttribute(Attribute::Alignment).getValueAsInt()); 15881ad6265SDimitry Andric buildOpDecorate(VRegs[i][0], MIRBuilder, SPIRV::Decoration::Alignment, 159*fcaf7f86SDimitry Andric {Alignment}); 16081ad6265SDimitry Andric } 16181ad6265SDimitry Andric if (Arg.hasAttribute(Attribute::ReadOnly)) { 16281ad6265SDimitry Andric auto Attr = 16381ad6265SDimitry Andric static_cast<unsigned>(SPIRV::FunctionParameterAttribute::NoWrite); 16481ad6265SDimitry Andric buildOpDecorate(VRegs[i][0], MIRBuilder, 16581ad6265SDimitry Andric SPIRV::Decoration::FuncParamAttr, {Attr}); 16681ad6265SDimitry Andric } 16781ad6265SDimitry Andric if (Arg.hasAttribute(Attribute::ZExt)) { 16881ad6265SDimitry Andric auto Attr = 16981ad6265SDimitry Andric static_cast<unsigned>(SPIRV::FunctionParameterAttribute::Zext); 17081ad6265SDimitry Andric buildOpDecorate(VRegs[i][0], MIRBuilder, 17181ad6265SDimitry Andric SPIRV::Decoration::FuncParamAttr, {Attr}); 17281ad6265SDimitry Andric } 173*fcaf7f86SDimitry Andric if (Arg.hasAttribute(Attribute::NoAlias)) { 174*fcaf7f86SDimitry Andric auto Attr = 175*fcaf7f86SDimitry Andric static_cast<unsigned>(SPIRV::FunctionParameterAttribute::NoAlias); 176*fcaf7f86SDimitry Andric buildOpDecorate(VRegs[i][0], MIRBuilder, 177*fcaf7f86SDimitry Andric SPIRV::Decoration::FuncParamAttr, {Attr}); 178*fcaf7f86SDimitry Andric } 179*fcaf7f86SDimitry Andric Node = F.getMetadata("kernel_arg_type_qual"); 180*fcaf7f86SDimitry Andric if (Node && i < Node->getNumOperands()) { 181*fcaf7f86SDimitry Andric StringRef TypeQual = cast<MDString>(Node->getOperand(i))->getString(); 182*fcaf7f86SDimitry Andric if (TypeQual.compare("volatile") == 0) 183*fcaf7f86SDimitry Andric buildOpDecorate(VRegs[i][0], MIRBuilder, SPIRV::Decoration::Volatile, 184*fcaf7f86SDimitry Andric {}); 185*fcaf7f86SDimitry Andric } 186*fcaf7f86SDimitry Andric Node = F.getMetadata("spirv.ParameterDecorations"); 187*fcaf7f86SDimitry Andric if (Node && i < Node->getNumOperands() && 188*fcaf7f86SDimitry Andric isa<MDNode>(Node->getOperand(i))) { 189*fcaf7f86SDimitry Andric MDNode *MD = cast<MDNode>(Node->getOperand(i)); 190*fcaf7f86SDimitry Andric for (const MDOperand &MDOp : MD->operands()) { 191*fcaf7f86SDimitry Andric MDNode *MD2 = dyn_cast<MDNode>(MDOp); 192*fcaf7f86SDimitry Andric assert(MD2 && "Metadata operand is expected"); 193*fcaf7f86SDimitry Andric ConstantInt *Const = getConstInt(MD2, 0); 194*fcaf7f86SDimitry Andric assert(Const && "MDOperand should be ConstantInt"); 195*fcaf7f86SDimitry Andric auto Dec = static_cast<SPIRV::Decoration>(Const->getZExtValue()); 196*fcaf7f86SDimitry Andric std::vector<uint32_t> DecVec; 197*fcaf7f86SDimitry Andric for (unsigned j = 1; j < MD2->getNumOperands(); j++) { 198*fcaf7f86SDimitry Andric ConstantInt *Const = getConstInt(MD2, j); 199*fcaf7f86SDimitry Andric assert(Const && "MDOperand should be ConstantInt"); 200*fcaf7f86SDimitry Andric DecVec.push_back(static_cast<uint32_t>(Const->getZExtValue())); 201*fcaf7f86SDimitry Andric } 202*fcaf7f86SDimitry Andric buildOpDecorate(VRegs[i][0], MIRBuilder, Dec, DecVec); 203*fcaf7f86SDimitry Andric } 204*fcaf7f86SDimitry Andric } 20581ad6265SDimitry Andric ++i; 20681ad6265SDimitry Andric } 20781ad6265SDimitry Andric } 20881ad6265SDimitry Andric 20981ad6265SDimitry Andric // Generate a SPIR-V type for the function. 21081ad6265SDimitry Andric auto MRI = MIRBuilder.getMRI(); 21181ad6265SDimitry Andric Register FuncVReg = MRI->createGenericVirtualRegister(LLT::scalar(32)); 21281ad6265SDimitry Andric MRI->setRegClass(FuncVReg, &SPIRV::IDRegClass); 213753f127fSDimitry Andric if (F.isDeclaration()) 214753f127fSDimitry Andric GR->add(&F, &MIRBuilder.getMF(), FuncVReg); 215*fcaf7f86SDimitry Andric SPIRVType *RetTy = GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder); 216*fcaf7f86SDimitry Andric SPIRVType *FuncTy = GR->getOrCreateOpTypeFunctionWithArgs( 217*fcaf7f86SDimitry Andric FTy, RetTy, ArgTypeVRegs, MIRBuilder); 21881ad6265SDimitry Andric 21981ad6265SDimitry Andric // Build the OpTypeFunction declaring it. 22081ad6265SDimitry Andric uint32_t FuncControl = getFunctionControl(F); 22181ad6265SDimitry Andric 22281ad6265SDimitry Andric MIRBuilder.buildInstr(SPIRV::OpFunction) 22381ad6265SDimitry Andric .addDef(FuncVReg) 224*fcaf7f86SDimitry Andric .addUse(GR->getSPIRVTypeID(RetTy)) 22581ad6265SDimitry Andric .addImm(FuncControl) 22681ad6265SDimitry Andric .addUse(GR->getSPIRVTypeID(FuncTy)); 22781ad6265SDimitry Andric 22881ad6265SDimitry Andric // Add OpFunctionParameters. 229*fcaf7f86SDimitry Andric int i = 0; 230*fcaf7f86SDimitry Andric for (const auto &Arg : F.args()) { 23181ad6265SDimitry Andric assert(VRegs[i].size() == 1 && "Formal arg has multiple vregs"); 23281ad6265SDimitry Andric MRI->setRegClass(VRegs[i][0], &SPIRV::IDRegClass); 23381ad6265SDimitry Andric MIRBuilder.buildInstr(SPIRV::OpFunctionParameter) 23481ad6265SDimitry Andric .addDef(VRegs[i][0]) 235*fcaf7f86SDimitry Andric .addUse(GR->getSPIRVTypeID(ArgTypeVRegs[i])); 236753f127fSDimitry Andric if (F.isDeclaration()) 237*fcaf7f86SDimitry Andric GR->add(&Arg, &MIRBuilder.getMF(), VRegs[i][0]); 238*fcaf7f86SDimitry Andric i++; 23981ad6265SDimitry Andric } 24081ad6265SDimitry Andric // Name the function. 24181ad6265SDimitry Andric if (F.hasName()) 24281ad6265SDimitry Andric buildOpName(FuncVReg, F.getName(), MIRBuilder); 24381ad6265SDimitry Andric 24481ad6265SDimitry Andric // Handle entry points and function linkage. 24581ad6265SDimitry Andric if (F.getCallingConv() == CallingConv::SPIR_KERNEL) { 24681ad6265SDimitry Andric auto MIB = MIRBuilder.buildInstr(SPIRV::OpEntryPoint) 24781ad6265SDimitry Andric .addImm(static_cast<uint32_t>(SPIRV::ExecutionModel::Kernel)) 24881ad6265SDimitry Andric .addUse(FuncVReg); 24981ad6265SDimitry Andric addStringImm(F.getName(), MIB); 25081ad6265SDimitry Andric } else if (F.getLinkage() == GlobalValue::LinkageTypes::ExternalLinkage || 25181ad6265SDimitry Andric F.getLinkage() == GlobalValue::LinkOnceODRLinkage) { 25281ad6265SDimitry Andric auto LnkTy = F.isDeclaration() ? SPIRV::LinkageType::Import 25381ad6265SDimitry Andric : SPIRV::LinkageType::Export; 25481ad6265SDimitry Andric buildOpDecorate(FuncVReg, MIRBuilder, SPIRV::Decoration::LinkageAttributes, 25581ad6265SDimitry Andric {static_cast<uint32_t>(LnkTy)}, F.getGlobalIdentifier()); 25681ad6265SDimitry Andric } 25781ad6265SDimitry Andric 25881ad6265SDimitry Andric return true; 25981ad6265SDimitry Andric } 26081ad6265SDimitry Andric 26181ad6265SDimitry Andric bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 26281ad6265SDimitry Andric CallLoweringInfo &Info) const { 26381ad6265SDimitry Andric // Currently call returns should have single vregs. 26481ad6265SDimitry Andric // TODO: handle the case of multiple registers. 26581ad6265SDimitry Andric if (Info.OrigRet.Regs.size() > 1) 26681ad6265SDimitry Andric return false; 267*fcaf7f86SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 268*fcaf7f86SDimitry Andric GR->setCurrentFunc(MF); 269*fcaf7f86SDimitry Andric FunctionType *FTy = nullptr; 270*fcaf7f86SDimitry Andric const Function *CF = nullptr; 27181ad6265SDimitry Andric 27281ad6265SDimitry Andric // Emit a regular OpFunctionCall. If it's an externally declared function, 273*fcaf7f86SDimitry Andric // be sure to emit its type and function declaration here. It will be hoisted 274*fcaf7f86SDimitry Andric // globally later. 27581ad6265SDimitry Andric if (Info.Callee.isGlobal()) { 276*fcaf7f86SDimitry Andric CF = dyn_cast_or_null<const Function>(Info.Callee.getGlobal()); 27781ad6265SDimitry Andric // TODO: support constexpr casts and indirect calls. 27881ad6265SDimitry Andric if (CF == nullptr) 27981ad6265SDimitry Andric return false; 280*fcaf7f86SDimitry Andric FTy = getOriginalFunctionType(*CF); 281*fcaf7f86SDimitry Andric } 282*fcaf7f86SDimitry Andric 283*fcaf7f86SDimitry Andric Register ResVReg = 284*fcaf7f86SDimitry Andric Info.OrigRet.Regs.empty() ? Register(0) : Info.OrigRet.Regs[0]; 285*fcaf7f86SDimitry Andric if (CF && CF->isDeclaration() && 286*fcaf7f86SDimitry Andric !GR->find(CF, &MIRBuilder.getMF()).isValid()) { 28781ad6265SDimitry Andric // Emit the type info and forward function declaration to the first MBB 28881ad6265SDimitry Andric // to ensure VReg definition dependencies are valid across all MBBs. 289*fcaf7f86SDimitry Andric MachineIRBuilder FirstBlockBuilder; 290*fcaf7f86SDimitry Andric FirstBlockBuilder.setMF(MF); 291*fcaf7f86SDimitry Andric FirstBlockBuilder.setMBB(*MF.getBlockNumbered(0)); 29281ad6265SDimitry Andric 29381ad6265SDimitry Andric SmallVector<ArrayRef<Register>, 8> VRegArgs; 29481ad6265SDimitry Andric SmallVector<SmallVector<Register, 1>, 8> ToInsert; 29581ad6265SDimitry Andric for (const Argument &Arg : CF->args()) { 29681ad6265SDimitry Andric if (MIRBuilder.getDataLayout().getTypeStoreSize(Arg.getType()).isZero()) 29781ad6265SDimitry Andric continue; // Don't handle zero sized types. 298*fcaf7f86SDimitry Andric ToInsert.push_back( 299*fcaf7f86SDimitry Andric {MIRBuilder.getMRI()->createGenericVirtualRegister(LLT::scalar(32))}); 30081ad6265SDimitry Andric VRegArgs.push_back(ToInsert.back()); 30181ad6265SDimitry Andric } 302*fcaf7f86SDimitry Andric // TODO: Reuse FunctionLoweringInfo 30381ad6265SDimitry Andric FunctionLoweringInfo FuncInfo; 304*fcaf7f86SDimitry Andric lowerFormalArguments(FirstBlockBuilder, *CF, VRegArgs, FuncInfo); 30581ad6265SDimitry Andric } 30681ad6265SDimitry Andric 30781ad6265SDimitry Andric // Make sure there's a valid return reg, even for functions returning void. 308*fcaf7f86SDimitry Andric if (!ResVReg.isValid()) 30981ad6265SDimitry Andric ResVReg = MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass); 31081ad6265SDimitry Andric SPIRVType *RetType = 311*fcaf7f86SDimitry Andric GR->assignTypeToVReg(FTy->getReturnType(), ResVReg, MIRBuilder); 31281ad6265SDimitry Andric 31381ad6265SDimitry Andric // Emit the OpFunctionCall and its args. 31481ad6265SDimitry Andric auto MIB = MIRBuilder.buildInstr(SPIRV::OpFunctionCall) 31581ad6265SDimitry Andric .addDef(ResVReg) 31681ad6265SDimitry Andric .addUse(GR->getSPIRVTypeID(RetType)) 31781ad6265SDimitry Andric .add(Info.Callee); 31881ad6265SDimitry Andric 31981ad6265SDimitry Andric for (const auto &Arg : Info.OrigArgs) { 32081ad6265SDimitry Andric // Currently call args should have single vregs. 32181ad6265SDimitry Andric if (Arg.Regs.size() > 1) 32281ad6265SDimitry Andric return false; 32381ad6265SDimitry Andric MIB.addUse(Arg.Regs[0]); 32481ad6265SDimitry Andric } 325*fcaf7f86SDimitry Andric const auto &STI = MF.getSubtarget(); 326*fcaf7f86SDimitry Andric return MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), 327*fcaf7f86SDimitry Andric *STI.getRegBankInfo()); 32881ad6265SDimitry Andric } 329