15ffd83dbSDimitry Andric //===-- lib/CodeGen/GlobalISel/InlineAsmLowering.cpp ----------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric /// 95ffd83dbSDimitry Andric /// \file 105ffd83dbSDimitry Andric /// This file implements the lowering from LLVM IR inline asm to MIR INLINEASM 115ffd83dbSDimitry Andric /// 125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 135ffd83dbSDimitry Andric 145ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h" 155ffd83dbSDimitry Andric #include "llvm/CodeGen/Analysis.h" 165ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 175ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h" 185ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 195ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 205ffd83dbSDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 215ffd83dbSDimitry Andric #include "llvm/IR/DataLayout.h" 225ffd83dbSDimitry Andric #include "llvm/IR/Instructions.h" 235ffd83dbSDimitry Andric #include "llvm/IR/LLVMContext.h" 245ffd83dbSDimitry Andric #include "llvm/IR/Module.h" 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric #define DEBUG_TYPE "inline-asm-lowering" 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric using namespace llvm; 295ffd83dbSDimitry Andric 305ffd83dbSDimitry Andric void InlineAsmLowering::anchor() {} 315ffd83dbSDimitry Andric 325ffd83dbSDimitry Andric namespace { 335ffd83dbSDimitry Andric 345ffd83dbSDimitry Andric /// GISelAsmOperandInfo - This contains information for each constraint that we 355ffd83dbSDimitry Andric /// are lowering. 365ffd83dbSDimitry Andric class GISelAsmOperandInfo : public TargetLowering::AsmOperandInfo { 375ffd83dbSDimitry Andric public: 385ffd83dbSDimitry Andric /// Regs - If this is a register or register class operand, this 395ffd83dbSDimitry Andric /// contains the set of assigned registers corresponding to the operand. 405ffd83dbSDimitry Andric SmallVector<Register, 1> Regs; 415ffd83dbSDimitry Andric 425ffd83dbSDimitry Andric explicit GISelAsmOperandInfo(const TargetLowering::AsmOperandInfo &Info) 435ffd83dbSDimitry Andric : TargetLowering::AsmOperandInfo(Info) {} 445ffd83dbSDimitry Andric }; 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric using GISelAsmOperandInfoVector = SmallVector<GISelAsmOperandInfo, 16>; 475ffd83dbSDimitry Andric 485ffd83dbSDimitry Andric class ExtraFlags { 495ffd83dbSDimitry Andric unsigned Flags = 0; 505ffd83dbSDimitry Andric 515ffd83dbSDimitry Andric public: 525ffd83dbSDimitry Andric explicit ExtraFlags(const CallBase &CB) { 535ffd83dbSDimitry Andric const InlineAsm *IA = cast<InlineAsm>(CB.getCalledOperand()); 545ffd83dbSDimitry Andric if (IA->hasSideEffects()) 555ffd83dbSDimitry Andric Flags |= InlineAsm::Extra_HasSideEffects; 565ffd83dbSDimitry Andric if (IA->isAlignStack()) 575ffd83dbSDimitry Andric Flags |= InlineAsm::Extra_IsAlignStack; 585ffd83dbSDimitry Andric if (CB.isConvergent()) 595ffd83dbSDimitry Andric Flags |= InlineAsm::Extra_IsConvergent; 605ffd83dbSDimitry Andric Flags |= IA->getDialect() * InlineAsm::Extra_AsmDialect; 615ffd83dbSDimitry Andric } 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric void update(const TargetLowering::AsmOperandInfo &OpInfo) { 645ffd83dbSDimitry Andric // Ideally, we would only check against memory constraints. However, the 655ffd83dbSDimitry Andric // meaning of an Other constraint can be target-specific and we can't easily 665ffd83dbSDimitry Andric // reason about it. Therefore, be conservative and set MayLoad/MayStore 675ffd83dbSDimitry Andric // for Other constraints as well. 685ffd83dbSDimitry Andric if (OpInfo.ConstraintType == TargetLowering::C_Memory || 695ffd83dbSDimitry Andric OpInfo.ConstraintType == TargetLowering::C_Other) { 705ffd83dbSDimitry Andric if (OpInfo.Type == InlineAsm::isInput) 715ffd83dbSDimitry Andric Flags |= InlineAsm::Extra_MayLoad; 725ffd83dbSDimitry Andric else if (OpInfo.Type == InlineAsm::isOutput) 735ffd83dbSDimitry Andric Flags |= InlineAsm::Extra_MayStore; 745ffd83dbSDimitry Andric else if (OpInfo.Type == InlineAsm::isClobber) 755ffd83dbSDimitry Andric Flags |= (InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore); 765ffd83dbSDimitry Andric } 775ffd83dbSDimitry Andric } 785ffd83dbSDimitry Andric 795ffd83dbSDimitry Andric unsigned get() const { return Flags; } 805ffd83dbSDimitry Andric }; 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric } // namespace 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric /// Assign virtual/physical registers for the specified register operand. 855ffd83dbSDimitry Andric static void getRegistersForValue(MachineFunction &MF, 865ffd83dbSDimitry Andric MachineIRBuilder &MIRBuilder, 875ffd83dbSDimitry Andric GISelAsmOperandInfo &OpInfo, 885ffd83dbSDimitry Andric GISelAsmOperandInfo &RefOpInfo) { 895ffd83dbSDimitry Andric 905ffd83dbSDimitry Andric const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering(); 915ffd83dbSDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric // No work to do for memory operations. 945ffd83dbSDimitry Andric if (OpInfo.ConstraintType == TargetLowering::C_Memory) 955ffd83dbSDimitry Andric return; 965ffd83dbSDimitry Andric 975ffd83dbSDimitry Andric // If this is a constraint for a single physreg, or a constraint for a 985ffd83dbSDimitry Andric // register class, find it. 995ffd83dbSDimitry Andric Register AssignedReg; 1005ffd83dbSDimitry Andric const TargetRegisterClass *RC; 1015ffd83dbSDimitry Andric std::tie(AssignedReg, RC) = TLI.getRegForInlineAsmConstraint( 1025ffd83dbSDimitry Andric &TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT); 1035ffd83dbSDimitry Andric // RC is unset only on failure. Return immediately. 1045ffd83dbSDimitry Andric if (!RC) 1055ffd83dbSDimitry Andric return; 1065ffd83dbSDimitry Andric 1075ffd83dbSDimitry Andric // No need to allocate a matching input constraint since the constraint it's 1085ffd83dbSDimitry Andric // matching to has already been allocated. 1095ffd83dbSDimitry Andric if (OpInfo.isMatchingInputConstraint()) 1105ffd83dbSDimitry Andric return; 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric // Initialize NumRegs. 1135ffd83dbSDimitry Andric unsigned NumRegs = 1; 1145ffd83dbSDimitry Andric if (OpInfo.ConstraintVT != MVT::Other) 1155ffd83dbSDimitry Andric NumRegs = 1165ffd83dbSDimitry Andric TLI.getNumRegisters(MF.getFunction().getContext(), OpInfo.ConstraintVT); 1175ffd83dbSDimitry Andric 1185ffd83dbSDimitry Andric // If this is a constraint for a specific physical register, but the type of 1195ffd83dbSDimitry Andric // the operand requires more than one register to be passed, we allocate the 1205ffd83dbSDimitry Andric // required amount of physical registers, starting from the selected physical 1215ffd83dbSDimitry Andric // register. 1225ffd83dbSDimitry Andric // For this, first retrieve a register iterator for the given register class 1235ffd83dbSDimitry Andric TargetRegisterClass::iterator I = RC->begin(); 1245ffd83dbSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 1255ffd83dbSDimitry Andric 1265ffd83dbSDimitry Andric // Advance the iterator to the assigned register (if set) 1275ffd83dbSDimitry Andric if (AssignedReg) { 1285ffd83dbSDimitry Andric for (; *I != AssignedReg; ++I) 1295ffd83dbSDimitry Andric assert(I != RC->end() && "AssignedReg should be a member of provided RC"); 1305ffd83dbSDimitry Andric } 1315ffd83dbSDimitry Andric 1325ffd83dbSDimitry Andric // Finally, assign the registers. If the AssignedReg isn't set, create virtual 1335ffd83dbSDimitry Andric // registers with the provided register class 1345ffd83dbSDimitry Andric for (; NumRegs; --NumRegs, ++I) { 1355ffd83dbSDimitry Andric assert(I != RC->end() && "Ran out of registers to allocate!"); 1365ffd83dbSDimitry Andric Register R = AssignedReg ? Register(*I) : RegInfo.createVirtualRegister(RC); 1375ffd83dbSDimitry Andric OpInfo.Regs.push_back(R); 1385ffd83dbSDimitry Andric } 1395ffd83dbSDimitry Andric } 1405ffd83dbSDimitry Andric 1415ffd83dbSDimitry Andric /// Return an integer indicating how general CT is. 1425ffd83dbSDimitry Andric static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { 1435ffd83dbSDimitry Andric switch (CT) { 1445ffd83dbSDimitry Andric case TargetLowering::C_Immediate: 1455ffd83dbSDimitry Andric case TargetLowering::C_Other: 1465ffd83dbSDimitry Andric case TargetLowering::C_Unknown: 1475ffd83dbSDimitry Andric return 0; 1485ffd83dbSDimitry Andric case TargetLowering::C_Register: 1495ffd83dbSDimitry Andric return 1; 1505ffd83dbSDimitry Andric case TargetLowering::C_RegisterClass: 1515ffd83dbSDimitry Andric return 2; 1525ffd83dbSDimitry Andric case TargetLowering::C_Memory: 1535ffd83dbSDimitry Andric return 3; 1545ffd83dbSDimitry Andric } 1555ffd83dbSDimitry Andric llvm_unreachable("Invalid constraint type"); 1565ffd83dbSDimitry Andric } 1575ffd83dbSDimitry Andric 1585ffd83dbSDimitry Andric static void chooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, 1595ffd83dbSDimitry Andric const TargetLowering *TLI) { 1605ffd83dbSDimitry Andric assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options"); 1615ffd83dbSDimitry Andric unsigned BestIdx = 0; 1625ffd83dbSDimitry Andric TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown; 1635ffd83dbSDimitry Andric int BestGenerality = -1; 1645ffd83dbSDimitry Andric 1655ffd83dbSDimitry Andric // Loop over the options, keeping track of the most general one. 1665ffd83dbSDimitry Andric for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) { 1675ffd83dbSDimitry Andric TargetLowering::ConstraintType CType = 1685ffd83dbSDimitry Andric TLI->getConstraintType(OpInfo.Codes[i]); 1695ffd83dbSDimitry Andric 1705ffd83dbSDimitry Andric // Indirect 'other' or 'immediate' constraints are not allowed. 1715ffd83dbSDimitry Andric if (OpInfo.isIndirect && !(CType == TargetLowering::C_Memory || 1725ffd83dbSDimitry Andric CType == TargetLowering::C_Register || 1735ffd83dbSDimitry Andric CType == TargetLowering::C_RegisterClass)) 1745ffd83dbSDimitry Andric continue; 1755ffd83dbSDimitry Andric 1765ffd83dbSDimitry Andric // If this is an 'other' or 'immediate' constraint, see if the operand is 1775ffd83dbSDimitry Andric // valid for it. For example, on X86 we might have an 'rI' constraint. If 1785ffd83dbSDimitry Andric // the operand is an integer in the range [0..31] we want to use I (saving a 1795ffd83dbSDimitry Andric // load of a register), otherwise we must use 'r'. 1805ffd83dbSDimitry Andric if (CType == TargetLowering::C_Other || 1815ffd83dbSDimitry Andric CType == TargetLowering::C_Immediate) { 1825ffd83dbSDimitry Andric assert(OpInfo.Codes[i].size() == 1 && 1835ffd83dbSDimitry Andric "Unhandled multi-letter 'other' constraint"); 1845ffd83dbSDimitry Andric // FIXME: prefer immediate constraints if the target allows it 1855ffd83dbSDimitry Andric } 1865ffd83dbSDimitry Andric 1875ffd83dbSDimitry Andric // Things with matching constraints can only be registers, per gcc 1885ffd83dbSDimitry Andric // documentation. This mainly affects "g" constraints. 1895ffd83dbSDimitry Andric if (CType == TargetLowering::C_Memory && OpInfo.hasMatchingInput()) 1905ffd83dbSDimitry Andric continue; 1915ffd83dbSDimitry Andric 1925ffd83dbSDimitry Andric // This constraint letter is more general than the previous one, use it. 1935ffd83dbSDimitry Andric int Generality = getConstraintGenerality(CType); 1945ffd83dbSDimitry Andric if (Generality > BestGenerality) { 1955ffd83dbSDimitry Andric BestType = CType; 1965ffd83dbSDimitry Andric BestIdx = i; 1975ffd83dbSDimitry Andric BestGenerality = Generality; 1985ffd83dbSDimitry Andric } 1995ffd83dbSDimitry Andric } 2005ffd83dbSDimitry Andric 2015ffd83dbSDimitry Andric OpInfo.ConstraintCode = OpInfo.Codes[BestIdx]; 2025ffd83dbSDimitry Andric OpInfo.ConstraintType = BestType; 2035ffd83dbSDimitry Andric } 2045ffd83dbSDimitry Andric 2055ffd83dbSDimitry Andric static void computeConstraintToUse(const TargetLowering *TLI, 2065ffd83dbSDimitry Andric TargetLowering::AsmOperandInfo &OpInfo) { 2075ffd83dbSDimitry Andric assert(!OpInfo.Codes.empty() && "Must have at least one constraint"); 2085ffd83dbSDimitry Andric 2095ffd83dbSDimitry Andric // Single-letter constraints ('r') are very common. 2105ffd83dbSDimitry Andric if (OpInfo.Codes.size() == 1) { 2115ffd83dbSDimitry Andric OpInfo.ConstraintCode = OpInfo.Codes[0]; 2125ffd83dbSDimitry Andric OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode); 2135ffd83dbSDimitry Andric } else { 2145ffd83dbSDimitry Andric chooseConstraint(OpInfo, TLI); 2155ffd83dbSDimitry Andric } 2165ffd83dbSDimitry Andric 2175ffd83dbSDimitry Andric // 'X' matches anything. 2185ffd83dbSDimitry Andric if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) { 2195ffd83dbSDimitry Andric // Labels and constants are handled elsewhere ('X' is the only thing 2205ffd83dbSDimitry Andric // that matches labels). For Functions, the type here is the type of 2215ffd83dbSDimitry Andric // the result, which is not what we want to look at; leave them alone. 2225ffd83dbSDimitry Andric Value *Val = OpInfo.CallOperandVal; 2235ffd83dbSDimitry Andric if (isa<BasicBlock>(Val) || isa<ConstantInt>(Val) || isa<Function>(Val)) 2245ffd83dbSDimitry Andric return; 2255ffd83dbSDimitry Andric 2265ffd83dbSDimitry Andric // Otherwise, try to resolve it to something we know about by looking at 2275ffd83dbSDimitry Andric // the actual operand type. 2285ffd83dbSDimitry Andric if (const char *Repl = TLI->LowerXConstraint(OpInfo.ConstraintVT)) { 2295ffd83dbSDimitry Andric OpInfo.ConstraintCode = Repl; 2305ffd83dbSDimitry Andric OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode); 2315ffd83dbSDimitry Andric } 2325ffd83dbSDimitry Andric } 2335ffd83dbSDimitry Andric } 2345ffd83dbSDimitry Andric 2355ffd83dbSDimitry Andric static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx) { 2365ffd83dbSDimitry Andric unsigned Flag = I.getOperand(OpIdx).getImm(); 2375ffd83dbSDimitry Andric return InlineAsm::getNumOperandRegisters(Flag); 2385ffd83dbSDimitry Andric } 2395ffd83dbSDimitry Andric 2405ffd83dbSDimitry Andric static bool buildAnyextOrCopy(Register Dst, Register Src, 2415ffd83dbSDimitry Andric MachineIRBuilder &MIRBuilder) { 2425ffd83dbSDimitry Andric const TargetRegisterInfo *TRI = 2435ffd83dbSDimitry Andric MIRBuilder.getMF().getSubtarget().getRegisterInfo(); 2445ffd83dbSDimitry Andric MachineRegisterInfo *MRI = MIRBuilder.getMRI(); 2455ffd83dbSDimitry Andric 2465ffd83dbSDimitry Andric auto SrcTy = MRI->getType(Src); 2475ffd83dbSDimitry Andric if (!SrcTy.isValid()) { 2485ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Source type for copy is not valid\n"); 2495ffd83dbSDimitry Andric return false; 2505ffd83dbSDimitry Andric } 2515ffd83dbSDimitry Andric unsigned SrcSize = TRI->getRegSizeInBits(Src, *MRI); 2525ffd83dbSDimitry Andric unsigned DstSize = TRI->getRegSizeInBits(Dst, *MRI); 2535ffd83dbSDimitry Andric 2545ffd83dbSDimitry Andric if (DstSize < SrcSize) { 2555ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Input can't fit in destination reg class\n"); 2565ffd83dbSDimitry Andric return false; 2575ffd83dbSDimitry Andric } 2585ffd83dbSDimitry Andric 2595ffd83dbSDimitry Andric // Attempt to anyext small scalar sources. 2605ffd83dbSDimitry Andric if (DstSize > SrcSize) { 2615ffd83dbSDimitry Andric if (!SrcTy.isScalar()) { 2625ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Can't extend non-scalar input to size of" 2635ffd83dbSDimitry Andric "destination register class\n"); 2645ffd83dbSDimitry Andric return false; 2655ffd83dbSDimitry Andric } 2665ffd83dbSDimitry Andric Src = MIRBuilder.buildAnyExt(LLT::scalar(DstSize), Src).getReg(0); 2675ffd83dbSDimitry Andric } 2685ffd83dbSDimitry Andric 2695ffd83dbSDimitry Andric MIRBuilder.buildCopy(Dst, Src); 2705ffd83dbSDimitry Andric return true; 2715ffd83dbSDimitry Andric } 2725ffd83dbSDimitry Andric 2735ffd83dbSDimitry Andric bool InlineAsmLowering::lowerInlineAsm( 2745ffd83dbSDimitry Andric MachineIRBuilder &MIRBuilder, const CallBase &Call, 2755ffd83dbSDimitry Andric std::function<ArrayRef<Register>(const Value &Val)> GetOrCreateVRegs) 2765ffd83dbSDimitry Andric const { 2775ffd83dbSDimitry Andric const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand()); 2785ffd83dbSDimitry Andric 2795ffd83dbSDimitry Andric /// ConstraintOperands - Information about all of the constraints. 2805ffd83dbSDimitry Andric GISelAsmOperandInfoVector ConstraintOperands; 2815ffd83dbSDimitry Andric 2825ffd83dbSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 2835ffd83dbSDimitry Andric const Function &F = MF.getFunction(); 2845ffd83dbSDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 2855ffd83dbSDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 2865ffd83dbSDimitry Andric 2875ffd83dbSDimitry Andric MachineRegisterInfo *MRI = MIRBuilder.getMRI(); 2885ffd83dbSDimitry Andric 2895ffd83dbSDimitry Andric TargetLowering::AsmOperandInfoVector TargetConstraints = 2905ffd83dbSDimitry Andric TLI->ParseConstraints(DL, TRI, Call); 2915ffd83dbSDimitry Andric 2925ffd83dbSDimitry Andric ExtraFlags ExtraInfo(Call); 2935ffd83dbSDimitry Andric unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. 2945ffd83dbSDimitry Andric unsigned ResNo = 0; // ResNo - The result number of the next output. 2955ffd83dbSDimitry Andric for (auto &T : TargetConstraints) { 2965ffd83dbSDimitry Andric ConstraintOperands.push_back(GISelAsmOperandInfo(T)); 2975ffd83dbSDimitry Andric GISelAsmOperandInfo &OpInfo = ConstraintOperands.back(); 2985ffd83dbSDimitry Andric 2995ffd83dbSDimitry Andric // Compute the value type for each operand. 3005ffd83dbSDimitry Andric if (OpInfo.Type == InlineAsm::isInput || 3015ffd83dbSDimitry Andric (OpInfo.Type == InlineAsm::isOutput && OpInfo.isIndirect)) { 3025ffd83dbSDimitry Andric 3035ffd83dbSDimitry Andric OpInfo.CallOperandVal = const_cast<Value *>(Call.getArgOperand(ArgNo++)); 3045ffd83dbSDimitry Andric 3055ffd83dbSDimitry Andric if (isa<BasicBlock>(OpInfo.CallOperandVal)) { 3065ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Basic block input operands not supported yet\n"); 3075ffd83dbSDimitry Andric return false; 3085ffd83dbSDimitry Andric } 3095ffd83dbSDimitry Andric 3105ffd83dbSDimitry Andric Type *OpTy = OpInfo.CallOperandVal->getType(); 3115ffd83dbSDimitry Andric 3125ffd83dbSDimitry Andric // If this is an indirect operand, the operand is a pointer to the 3135ffd83dbSDimitry Andric // accessed type. 3145ffd83dbSDimitry Andric if (OpInfo.isIndirect) { 3155ffd83dbSDimitry Andric PointerType *PtrTy = dyn_cast<PointerType>(OpTy); 3165ffd83dbSDimitry Andric if (!PtrTy) 3175ffd83dbSDimitry Andric report_fatal_error("Indirect operand for inline asm not a pointer!"); 3185ffd83dbSDimitry Andric OpTy = PtrTy->getElementType(); 3195ffd83dbSDimitry Andric } 3205ffd83dbSDimitry Andric 3215ffd83dbSDimitry Andric // FIXME: Support aggregate input operands 3225ffd83dbSDimitry Andric if (!OpTy->isSingleValueType()) { 3235ffd83dbSDimitry Andric LLVM_DEBUG( 3245ffd83dbSDimitry Andric dbgs() << "Aggregate input operands are not supported yet\n"); 3255ffd83dbSDimitry Andric return false; 3265ffd83dbSDimitry Andric } 3275ffd83dbSDimitry Andric 3285ffd83dbSDimitry Andric OpInfo.ConstraintVT = TLI->getValueType(DL, OpTy, true).getSimpleVT(); 3295ffd83dbSDimitry Andric 3305ffd83dbSDimitry Andric } else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect) { 3315ffd83dbSDimitry Andric assert(!Call.getType()->isVoidTy() && "Bad inline asm!"); 3325ffd83dbSDimitry Andric if (StructType *STy = dyn_cast<StructType>(Call.getType())) { 3335ffd83dbSDimitry Andric OpInfo.ConstraintVT = 3345ffd83dbSDimitry Andric TLI->getSimpleValueType(DL, STy->getElementType(ResNo)); 3355ffd83dbSDimitry Andric } else { 3365ffd83dbSDimitry Andric assert(ResNo == 0 && "Asm only has one result!"); 3375ffd83dbSDimitry Andric OpInfo.ConstraintVT = TLI->getSimpleValueType(DL, Call.getType()); 3385ffd83dbSDimitry Andric } 3395ffd83dbSDimitry Andric ++ResNo; 3405ffd83dbSDimitry Andric } else { 3415ffd83dbSDimitry Andric OpInfo.ConstraintVT = MVT::Other; 3425ffd83dbSDimitry Andric } 3435ffd83dbSDimitry Andric 3445ffd83dbSDimitry Andric // Compute the constraint code and ConstraintType to use. 3455ffd83dbSDimitry Andric computeConstraintToUse(TLI, OpInfo); 3465ffd83dbSDimitry Andric 3475ffd83dbSDimitry Andric // The selected constraint type might expose new sideeffects 3485ffd83dbSDimitry Andric ExtraInfo.update(OpInfo); 3495ffd83dbSDimitry Andric } 3505ffd83dbSDimitry Andric 3515ffd83dbSDimitry Andric // At this point, all operand types are decided. 3525ffd83dbSDimitry Andric // Create the MachineInstr, but don't insert it yet since input 3535ffd83dbSDimitry Andric // operands still need to insert instructions before this one 3545ffd83dbSDimitry Andric auto Inst = MIRBuilder.buildInstrNoInsert(TargetOpcode::INLINEASM) 3555ffd83dbSDimitry Andric .addExternalSymbol(IA->getAsmString().c_str()) 3565ffd83dbSDimitry Andric .addImm(ExtraInfo.get()); 3575ffd83dbSDimitry Andric 3585ffd83dbSDimitry Andric // Starting from this operand: flag followed by register(s) will be added as 3595ffd83dbSDimitry Andric // operands to Inst for each constraint. Used for matching input constraints. 3605ffd83dbSDimitry Andric unsigned StartIdx = Inst->getNumOperands(); 3615ffd83dbSDimitry Andric 3625ffd83dbSDimitry Andric // Collects the output operands for later processing 3635ffd83dbSDimitry Andric GISelAsmOperandInfoVector OutputOperands; 3645ffd83dbSDimitry Andric 3655ffd83dbSDimitry Andric for (auto &OpInfo : ConstraintOperands) { 3665ffd83dbSDimitry Andric GISelAsmOperandInfo &RefOpInfo = 3675ffd83dbSDimitry Andric OpInfo.isMatchingInputConstraint() 3685ffd83dbSDimitry Andric ? ConstraintOperands[OpInfo.getMatchedOperand()] 3695ffd83dbSDimitry Andric : OpInfo; 3705ffd83dbSDimitry Andric 3715ffd83dbSDimitry Andric // Assign registers for register operands 3725ffd83dbSDimitry Andric getRegistersForValue(MF, MIRBuilder, OpInfo, RefOpInfo); 3735ffd83dbSDimitry Andric 3745ffd83dbSDimitry Andric switch (OpInfo.Type) { 3755ffd83dbSDimitry Andric case InlineAsm::isOutput: 3765ffd83dbSDimitry Andric if (OpInfo.ConstraintType == TargetLowering::C_Memory) { 3775ffd83dbSDimitry Andric unsigned ConstraintID = 3785ffd83dbSDimitry Andric TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode); 3795ffd83dbSDimitry Andric assert(ConstraintID != InlineAsm::Constraint_Unknown && 3805ffd83dbSDimitry Andric "Failed to convert memory constraint code to constraint id."); 3815ffd83dbSDimitry Andric 3825ffd83dbSDimitry Andric // Add information to the INLINEASM instruction to know about this 3835ffd83dbSDimitry Andric // output. 3845ffd83dbSDimitry Andric unsigned OpFlags = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1); 3855ffd83dbSDimitry Andric OpFlags = InlineAsm::getFlagWordForMem(OpFlags, ConstraintID); 3865ffd83dbSDimitry Andric Inst.addImm(OpFlags); 3875ffd83dbSDimitry Andric ArrayRef<Register> SourceRegs = 3885ffd83dbSDimitry Andric GetOrCreateVRegs(*OpInfo.CallOperandVal); 3895ffd83dbSDimitry Andric assert( 3905ffd83dbSDimitry Andric SourceRegs.size() == 1 && 3915ffd83dbSDimitry Andric "Expected the memory output to fit into a single virtual register"); 3925ffd83dbSDimitry Andric Inst.addReg(SourceRegs[0]); 3935ffd83dbSDimitry Andric } else { 3945ffd83dbSDimitry Andric // Otherwise, this outputs to a register (directly for C_Register / 3955ffd83dbSDimitry Andric // C_RegisterClass. Find a register that we can use. 3965ffd83dbSDimitry Andric assert(OpInfo.ConstraintType == TargetLowering::C_Register || 3975ffd83dbSDimitry Andric OpInfo.ConstraintType == TargetLowering::C_RegisterClass); 3985ffd83dbSDimitry Andric 3995ffd83dbSDimitry Andric if (OpInfo.Regs.empty()) { 4005ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() 4015ffd83dbSDimitry Andric << "Couldn't allocate output register for constraint\n"); 4025ffd83dbSDimitry Andric return false; 4035ffd83dbSDimitry Andric } 4045ffd83dbSDimitry Andric 4055ffd83dbSDimitry Andric // Add information to the INLINEASM instruction to know that this 4065ffd83dbSDimitry Andric // register is set. 4075ffd83dbSDimitry Andric unsigned Flag = InlineAsm::getFlagWord( 4085ffd83dbSDimitry Andric OpInfo.isEarlyClobber ? InlineAsm::Kind_RegDefEarlyClobber 4095ffd83dbSDimitry Andric : InlineAsm::Kind_RegDef, 4105ffd83dbSDimitry Andric OpInfo.Regs.size()); 4115ffd83dbSDimitry Andric if (OpInfo.Regs.front().isVirtual()) { 4125ffd83dbSDimitry Andric // Put the register class of the virtual registers in the flag word. 4135ffd83dbSDimitry Andric // That way, later passes can recompute register class constraints for 4145ffd83dbSDimitry Andric // inline assembly as well as normal instructions. Don't do this for 4155ffd83dbSDimitry Andric // tied operands that can use the regclass information from the def. 4165ffd83dbSDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front()); 4175ffd83dbSDimitry Andric Flag = InlineAsm::getFlagWordForRegClass(Flag, RC->getID()); 4185ffd83dbSDimitry Andric } 4195ffd83dbSDimitry Andric 4205ffd83dbSDimitry Andric Inst.addImm(Flag); 4215ffd83dbSDimitry Andric 4225ffd83dbSDimitry Andric for (Register Reg : OpInfo.Regs) { 4235ffd83dbSDimitry Andric Inst.addReg(Reg, 4245ffd83dbSDimitry Andric RegState::Define | getImplRegState(Reg.isPhysical()) | 4255ffd83dbSDimitry Andric (OpInfo.isEarlyClobber ? RegState::EarlyClobber : 0)); 4265ffd83dbSDimitry Andric } 4275ffd83dbSDimitry Andric 4285ffd83dbSDimitry Andric // Remember this output operand for later processing 4295ffd83dbSDimitry Andric OutputOperands.push_back(OpInfo); 4305ffd83dbSDimitry Andric } 4315ffd83dbSDimitry Andric 4325ffd83dbSDimitry Andric break; 4335ffd83dbSDimitry Andric case InlineAsm::isInput: { 4345ffd83dbSDimitry Andric if (OpInfo.isMatchingInputConstraint()) { 4355ffd83dbSDimitry Andric unsigned DefIdx = OpInfo.getMatchedOperand(); 4365ffd83dbSDimitry Andric // Find operand with register def that corresponds to DefIdx. 4375ffd83dbSDimitry Andric unsigned InstFlagIdx = StartIdx; 4385ffd83dbSDimitry Andric for (unsigned i = 0; i < DefIdx; ++i) 4395ffd83dbSDimitry Andric InstFlagIdx += getNumOpRegs(*Inst, InstFlagIdx) + 1; 4405ffd83dbSDimitry Andric assert(getNumOpRegs(*Inst, InstFlagIdx) == 1 && "Wrong flag"); 4415ffd83dbSDimitry Andric 4425ffd83dbSDimitry Andric unsigned MatchedOperandFlag = Inst->getOperand(InstFlagIdx).getImm(); 4435ffd83dbSDimitry Andric if (InlineAsm::isMemKind(MatchedOperandFlag)) { 4445ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Matching input constraint to mem operand not " 4455ffd83dbSDimitry Andric "supported. This should be target specific.\n"); 4465ffd83dbSDimitry Andric return false; 4475ffd83dbSDimitry Andric } 4485ffd83dbSDimitry Andric if (!InlineAsm::isRegDefKind(MatchedOperandFlag) && 4495ffd83dbSDimitry Andric !InlineAsm::isRegDefEarlyClobberKind(MatchedOperandFlag)) { 4505ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Unknown matching constraint\n"); 4515ffd83dbSDimitry Andric return false; 4525ffd83dbSDimitry Andric } 4535ffd83dbSDimitry Andric 4545ffd83dbSDimitry Andric // We want to tie input to register in next operand. 4555ffd83dbSDimitry Andric unsigned DefRegIdx = InstFlagIdx + 1; 4565ffd83dbSDimitry Andric Register Def = Inst->getOperand(DefRegIdx).getReg(); 4575ffd83dbSDimitry Andric 4585ffd83dbSDimitry Andric ArrayRef<Register> SrcRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal); 4595ffd83dbSDimitry Andric assert(SrcRegs.size() == 1 && "Single register is expected here"); 4605ffd83dbSDimitry Andric 4611106035dSDimitry Andric // When Def is physreg: use given input. 4621106035dSDimitry Andric Register In = SrcRegs[0]; 4631106035dSDimitry Andric // When Def is vreg: copy input to new vreg with same reg class as Def. 4641106035dSDimitry Andric if (Def.isVirtual()) { 4651106035dSDimitry Andric In = MRI->createVirtualRegister(MRI->getRegClass(Def)); 4661106035dSDimitry Andric if (!buildAnyextOrCopy(In, SrcRegs[0], MIRBuilder)) 4671106035dSDimitry Andric return false; 4681106035dSDimitry Andric } 4691106035dSDimitry Andric 4701106035dSDimitry Andric // Add Flag and input register operand (In) to Inst. Tie In to Def. 4715ffd83dbSDimitry Andric unsigned UseFlag = InlineAsm::getFlagWord(InlineAsm::Kind_RegUse, 1); 4725ffd83dbSDimitry Andric unsigned Flag = InlineAsm::getFlagWordForMatchingOp(UseFlag, DefIdx); 4735ffd83dbSDimitry Andric Inst.addImm(Flag); 4741106035dSDimitry Andric Inst.addReg(In); 4755ffd83dbSDimitry Andric Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1); 4765ffd83dbSDimitry Andric break; 4775ffd83dbSDimitry Andric } 4785ffd83dbSDimitry Andric 4795ffd83dbSDimitry Andric if (OpInfo.ConstraintType == TargetLowering::C_Other && 4805ffd83dbSDimitry Andric OpInfo.isIndirect) { 4815ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Indirect input operands with unknown constraint " 4825ffd83dbSDimitry Andric "not supported yet\n"); 4835ffd83dbSDimitry Andric return false; 4845ffd83dbSDimitry Andric } 4855ffd83dbSDimitry Andric 4865ffd83dbSDimitry Andric if (OpInfo.ConstraintType == TargetLowering::C_Immediate || 4875ffd83dbSDimitry Andric OpInfo.ConstraintType == TargetLowering::C_Other) { 4885ffd83dbSDimitry Andric 4895ffd83dbSDimitry Andric std::vector<MachineOperand> Ops; 4905ffd83dbSDimitry Andric if (!lowerAsmOperandForConstraint(OpInfo.CallOperandVal, 4915ffd83dbSDimitry Andric OpInfo.ConstraintCode, Ops, 4925ffd83dbSDimitry Andric MIRBuilder)) { 4935ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Don't support constraint: " 4945ffd83dbSDimitry Andric << OpInfo.ConstraintCode << " yet\n"); 4955ffd83dbSDimitry Andric return false; 4965ffd83dbSDimitry Andric } 4975ffd83dbSDimitry Andric 4985ffd83dbSDimitry Andric assert(Ops.size() > 0 && 4995ffd83dbSDimitry Andric "Expected constraint to be lowered to at least one operand"); 5005ffd83dbSDimitry Andric 5015ffd83dbSDimitry Andric // Add information to the INLINEASM node to know about this input. 5025ffd83dbSDimitry Andric unsigned OpFlags = 5035ffd83dbSDimitry Andric InlineAsm::getFlagWord(InlineAsm::Kind_Imm, Ops.size()); 5045ffd83dbSDimitry Andric Inst.addImm(OpFlags); 5055ffd83dbSDimitry Andric Inst.add(Ops); 5065ffd83dbSDimitry Andric break; 5075ffd83dbSDimitry Andric } 5085ffd83dbSDimitry Andric 5095ffd83dbSDimitry Andric if (OpInfo.ConstraintType == TargetLowering::C_Memory) { 5105ffd83dbSDimitry Andric 5115ffd83dbSDimitry Andric if (!OpInfo.isIndirect) { 5125ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() 5135ffd83dbSDimitry Andric << "Cannot indirectify memory input operands yet\n"); 5145ffd83dbSDimitry Andric return false; 5155ffd83dbSDimitry Andric } 5165ffd83dbSDimitry Andric 5175ffd83dbSDimitry Andric assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!"); 5185ffd83dbSDimitry Andric 5195ffd83dbSDimitry Andric unsigned ConstraintID = 5205ffd83dbSDimitry Andric TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode); 5215ffd83dbSDimitry Andric unsigned OpFlags = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1); 5225ffd83dbSDimitry Andric OpFlags = InlineAsm::getFlagWordForMem(OpFlags, ConstraintID); 5235ffd83dbSDimitry Andric Inst.addImm(OpFlags); 5245ffd83dbSDimitry Andric ArrayRef<Register> SourceRegs = 5255ffd83dbSDimitry Andric GetOrCreateVRegs(*OpInfo.CallOperandVal); 5265ffd83dbSDimitry Andric assert( 5275ffd83dbSDimitry Andric SourceRegs.size() == 1 && 5285ffd83dbSDimitry Andric "Expected the memory input to fit into a single virtual register"); 5295ffd83dbSDimitry Andric Inst.addReg(SourceRegs[0]); 5305ffd83dbSDimitry Andric break; 5315ffd83dbSDimitry Andric } 5325ffd83dbSDimitry Andric 5335ffd83dbSDimitry Andric assert((OpInfo.ConstraintType == TargetLowering::C_RegisterClass || 5345ffd83dbSDimitry Andric OpInfo.ConstraintType == TargetLowering::C_Register) && 5355ffd83dbSDimitry Andric "Unknown constraint type!"); 5365ffd83dbSDimitry Andric 5375ffd83dbSDimitry Andric if (OpInfo.isIndirect) { 5385ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Can't handle indirect register inputs yet " 5395ffd83dbSDimitry Andric "for constraint '" 5405ffd83dbSDimitry Andric << OpInfo.ConstraintCode << "'\n"); 5415ffd83dbSDimitry Andric return false; 5425ffd83dbSDimitry Andric } 5435ffd83dbSDimitry Andric 5445ffd83dbSDimitry Andric // Copy the input into the appropriate registers. 5455ffd83dbSDimitry Andric if (OpInfo.Regs.empty()) { 5465ffd83dbSDimitry Andric LLVM_DEBUG( 5475ffd83dbSDimitry Andric dbgs() 5485ffd83dbSDimitry Andric << "Couldn't allocate input register for register constraint\n"); 5495ffd83dbSDimitry Andric return false; 5505ffd83dbSDimitry Andric } 5515ffd83dbSDimitry Andric 5525ffd83dbSDimitry Andric unsigned NumRegs = OpInfo.Regs.size(); 5535ffd83dbSDimitry Andric ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal); 5545ffd83dbSDimitry Andric assert(NumRegs == SourceRegs.size() && 5555ffd83dbSDimitry Andric "Expected the number of input registers to match the number of " 5565ffd83dbSDimitry Andric "source registers"); 5575ffd83dbSDimitry Andric 5585ffd83dbSDimitry Andric if (NumRegs > 1) { 5595ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Input operands with multiple input registers are " 5605ffd83dbSDimitry Andric "not supported yet\n"); 5615ffd83dbSDimitry Andric return false; 5625ffd83dbSDimitry Andric } 5635ffd83dbSDimitry Andric 5645ffd83dbSDimitry Andric unsigned Flag = InlineAsm::getFlagWord(InlineAsm::Kind_RegUse, NumRegs); 565*e8d8bef9SDimitry Andric if (OpInfo.Regs.front().isVirtual()) { 566*e8d8bef9SDimitry Andric // Put the register class of the virtual registers in the flag word. 567*e8d8bef9SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front()); 568*e8d8bef9SDimitry Andric Flag = InlineAsm::getFlagWordForRegClass(Flag, RC->getID()); 569*e8d8bef9SDimitry Andric } 5705ffd83dbSDimitry Andric Inst.addImm(Flag); 5715ffd83dbSDimitry Andric if (!buildAnyextOrCopy(OpInfo.Regs[0], SourceRegs[0], MIRBuilder)) 5725ffd83dbSDimitry Andric return false; 5735ffd83dbSDimitry Andric Inst.addReg(OpInfo.Regs[0]); 5745ffd83dbSDimitry Andric break; 5755ffd83dbSDimitry Andric } 5765ffd83dbSDimitry Andric 5775ffd83dbSDimitry Andric case InlineAsm::isClobber: { 5785ffd83dbSDimitry Andric 5795ffd83dbSDimitry Andric unsigned NumRegs = OpInfo.Regs.size(); 5805ffd83dbSDimitry Andric if (NumRegs > 0) { 5815ffd83dbSDimitry Andric unsigned Flag = 5825ffd83dbSDimitry Andric InlineAsm::getFlagWord(InlineAsm::Kind_Clobber, NumRegs); 5835ffd83dbSDimitry Andric Inst.addImm(Flag); 5845ffd83dbSDimitry Andric 5855ffd83dbSDimitry Andric for (Register Reg : OpInfo.Regs) { 5865ffd83dbSDimitry Andric Inst.addReg(Reg, RegState::Define | RegState::EarlyClobber | 5875ffd83dbSDimitry Andric getImplRegState(Reg.isPhysical())); 5885ffd83dbSDimitry Andric } 5895ffd83dbSDimitry Andric } 5905ffd83dbSDimitry Andric break; 5915ffd83dbSDimitry Andric } 5925ffd83dbSDimitry Andric } 5935ffd83dbSDimitry Andric } 5945ffd83dbSDimitry Andric 5955ffd83dbSDimitry Andric if (const MDNode *SrcLoc = Call.getMetadata("srcloc")) 5965ffd83dbSDimitry Andric Inst.addMetadata(SrcLoc); 5975ffd83dbSDimitry Andric 5985ffd83dbSDimitry Andric // All inputs are handled, insert the instruction now 5995ffd83dbSDimitry Andric MIRBuilder.insertInstr(Inst); 6005ffd83dbSDimitry Andric 6015ffd83dbSDimitry Andric // Finally, copy the output operands into the output registers 6025ffd83dbSDimitry Andric ArrayRef<Register> ResRegs = GetOrCreateVRegs(Call); 6035ffd83dbSDimitry Andric if (ResRegs.size() != OutputOperands.size()) { 6045ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Expected the number of output registers to match the " 6055ffd83dbSDimitry Andric "number of destination registers\n"); 6065ffd83dbSDimitry Andric return false; 6075ffd83dbSDimitry Andric } 6085ffd83dbSDimitry Andric for (unsigned int i = 0, e = ResRegs.size(); i < e; i++) { 6095ffd83dbSDimitry Andric GISelAsmOperandInfo &OpInfo = OutputOperands[i]; 6105ffd83dbSDimitry Andric 6115ffd83dbSDimitry Andric if (OpInfo.Regs.empty()) 6125ffd83dbSDimitry Andric continue; 6135ffd83dbSDimitry Andric 6145ffd83dbSDimitry Andric switch (OpInfo.ConstraintType) { 6155ffd83dbSDimitry Andric case TargetLowering::C_Register: 6165ffd83dbSDimitry Andric case TargetLowering::C_RegisterClass: { 6175ffd83dbSDimitry Andric if (OpInfo.Regs.size() > 1) { 6185ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Output operands with multiple defining " 6195ffd83dbSDimitry Andric "registers are not supported yet\n"); 6205ffd83dbSDimitry Andric return false; 6215ffd83dbSDimitry Andric } 6225ffd83dbSDimitry Andric 6235ffd83dbSDimitry Andric Register SrcReg = OpInfo.Regs[0]; 6245ffd83dbSDimitry Andric unsigned SrcSize = TRI->getRegSizeInBits(SrcReg, *MRI); 6255ffd83dbSDimitry Andric if (MRI->getType(ResRegs[i]).getSizeInBits() < SrcSize) { 6265ffd83dbSDimitry Andric // First copy the non-typed virtual register into a generic virtual 6275ffd83dbSDimitry Andric // register 6285ffd83dbSDimitry Andric Register Tmp1Reg = 6295ffd83dbSDimitry Andric MRI->createGenericVirtualRegister(LLT::scalar(SrcSize)); 6305ffd83dbSDimitry Andric MIRBuilder.buildCopy(Tmp1Reg, SrcReg); 6315ffd83dbSDimitry Andric // Need to truncate the result of the register 6325ffd83dbSDimitry Andric MIRBuilder.buildTrunc(ResRegs[i], Tmp1Reg); 6335ffd83dbSDimitry Andric } else { 6345ffd83dbSDimitry Andric MIRBuilder.buildCopy(ResRegs[i], SrcReg); 6355ffd83dbSDimitry Andric } 6365ffd83dbSDimitry Andric break; 6375ffd83dbSDimitry Andric } 6385ffd83dbSDimitry Andric case TargetLowering::C_Immediate: 6395ffd83dbSDimitry Andric case TargetLowering::C_Other: 6405ffd83dbSDimitry Andric LLVM_DEBUG( 6415ffd83dbSDimitry Andric dbgs() << "Cannot lower target specific output constraints yet\n"); 6425ffd83dbSDimitry Andric return false; 6435ffd83dbSDimitry Andric case TargetLowering::C_Memory: 6445ffd83dbSDimitry Andric break; // Already handled. 6455ffd83dbSDimitry Andric case TargetLowering::C_Unknown: 6465ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Unexpected unknown constraint\n"); 6475ffd83dbSDimitry Andric return false; 6485ffd83dbSDimitry Andric } 6495ffd83dbSDimitry Andric } 6505ffd83dbSDimitry Andric 6515ffd83dbSDimitry Andric return true; 6525ffd83dbSDimitry Andric } 6535ffd83dbSDimitry Andric 6545ffd83dbSDimitry Andric bool InlineAsmLowering::lowerAsmOperandForConstraint( 6555ffd83dbSDimitry Andric Value *Val, StringRef Constraint, std::vector<MachineOperand> &Ops, 6565ffd83dbSDimitry Andric MachineIRBuilder &MIRBuilder) const { 6575ffd83dbSDimitry Andric if (Constraint.size() > 1) 6585ffd83dbSDimitry Andric return false; 6595ffd83dbSDimitry Andric 6605ffd83dbSDimitry Andric char ConstraintLetter = Constraint[0]; 6615ffd83dbSDimitry Andric switch (ConstraintLetter) { 6625ffd83dbSDimitry Andric default: 6635ffd83dbSDimitry Andric return false; 6645ffd83dbSDimitry Andric case 'i': // Simple Integer or Relocatable Constant 665*e8d8bef9SDimitry Andric case 'n': // immediate integer with a known value. 6665ffd83dbSDimitry Andric if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) { 6675ffd83dbSDimitry Andric assert(CI->getBitWidth() <= 64 && 6685ffd83dbSDimitry Andric "expected immediate to fit into 64-bits"); 6695ffd83dbSDimitry Andric // Boolean constants should be zero-extended, others are sign-extended 6705ffd83dbSDimitry Andric bool IsBool = CI->getBitWidth() == 1; 6715ffd83dbSDimitry Andric int64_t ExtVal = IsBool ? CI->getZExtValue() : CI->getSExtValue(); 6725ffd83dbSDimitry Andric Ops.push_back(MachineOperand::CreateImm(ExtVal)); 6735ffd83dbSDimitry Andric return true; 6745ffd83dbSDimitry Andric } 6755ffd83dbSDimitry Andric return false; 6765ffd83dbSDimitry Andric } 6775ffd83dbSDimitry Andric } 678