23#define DEBUG_TYPE "inline-asm-lowering"
27void InlineAsmLowering::anchor() {}
47 SmallVector<Register, 1> Regs;
52 explicit GISelAsmOperandInfo(
const TargetLowering::AsmOperandInfo &Info)
53 : TargetLowering::AsmOperandInfo(
Info) {}
62 explicit ExtraFlags(
const CallBase &CB) {
64 if (
IA->hasSideEffects())
66 if (
IA->isAlignStack())
75 void update(
const TargetLowering::AsmOperandInfo &OpInfo) {
91 unsigned get()
const {
return Flags; }
99 GISelAsmOperandInfo &OpInfo,
100 GISelAsmOperandInfo &RefOpInfo) {
114 &
TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
118 OpInfo.RegClass = RC;
122 if (OpInfo.isMatchingInputConstraint())
126 unsigned NumRegs = 1;
127 if (OpInfo.ConstraintVT != MVT::Other)
141 for (; *
I != AssignedReg; ++
I)
142 assert(
I != RC->
end() &&
"AssignedReg should be a member of provided RC");
147 for (; NumRegs; --NumRegs, ++
I) {
148 assert(
I != RC->
end() &&
"Ran out of registers to allocate!");
150 OpInfo.Regs.push_back(R);
156 assert(!OpInfo.Codes.empty() &&
"Must have at least one constraint");
159 if (OpInfo.Codes.size() == 1) {
160 OpInfo.ConstraintCode = OpInfo.Codes[0];
167 unsigned BestIdx = 0;
168 for (
const unsigned E =
G.size();
173 OpInfo.ConstraintCode =
G[BestIdx].first;
174 OpInfo.ConstraintType =
G[BestIdx].second;
178 if (OpInfo.ConstraintCode ==
"X" && OpInfo.CallOperandVal) {
182 Value *Val = OpInfo.CallOperandVal;
189 OpInfo.ConstraintCode = Repl;
197 return F.getNumOperandRegisters();
206 auto SrcTy = MRI->
getType(Src);
207 if (!SrcTy.isValid()) {
211 unsigned SrcSize =
TRI->getRegSizeInBits(Src, *MRI);
212 unsigned DstSize =
TRI->getRegSizeInBits(Dst, *MRI);
214 if (DstSize < SrcSize) {
215 LLVM_DEBUG(
dbgs() <<
"Input can't fit in destination reg class\n");
220 if (DstSize > SrcSize) {
221 if (!SrcTy.isScalar()) {
223 "destination register class\n");
240 GISelAsmOperandInfoVector ConstraintOperands;
252 ExtraFlags ExtraInfo(
Call);
255 for (
auto &
T : TargetConstraints) {
256 ConstraintOperands.push_back(GISelAsmOperandInfo(
T));
257 GISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
260 if (OpInfo.hasArg()) {
261 OpInfo.CallOperandVal =
Call.getArgOperand(ArgNo);
264 LLVM_DEBUG(
dbgs() <<
"Basic block input operands not supported yet\n");
268 Type *
OpTy = OpInfo.CallOperandVal->getType();
272 if (OpInfo.isIndirect) {
273 OpTy =
Call.getParamElementType(ArgNo);
274 assert(
OpTy &&
"Indirect operand must have elementtype attribute");
278 if (!
OpTy->isSingleValueType()) {
280 dbgs() <<
"Aggregate input operands are not supported yet\n");
284 OpInfo.ConstraintVT =
285 TLI->getAsmOperandValueType(
DL,
OpTy,
true).getSimpleVT();
288 assert(!
Call.getType()->isVoidTy() &&
"Bad inline asm!");
290 OpInfo.ConstraintVT =
291 TLI->getSimpleValueType(
DL, STy->getElementType(ResNo));
293 assert(ResNo == 0 &&
"Asm only has one result!");
294 OpInfo.ConstraintVT =
295 TLI->getAsmOperandValueType(
DL,
Call.getType()).getSimpleVT();
300 "GlobalISel currently doesn't support callbr");
301 OpInfo.ConstraintVT = MVT::Other;
304 if (OpInfo.ConstraintVT == MVT::i64x8)
311 ExtraInfo.update(OpInfo);
326 GISelAsmOperandInfoVector OutputOperands;
328 for (
auto &OpInfo : ConstraintOperands) {
329 GISelAsmOperandInfo &RefOpInfo =
330 OpInfo.isMatchingInputConstraint()
331 ? ConstraintOperands[OpInfo.getMatchedOperand()]
337 switch (OpInfo.Type) {
341 TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode);
343 "Failed to convert memory constraint code to constraint id.");
348 Flag.setMemConstraint(ConstraintID);
351 GetOrCreateVRegs(*OpInfo.CallOperandVal);
353 SourceRegs.
size() == 1 &&
354 "Expected the memory output to fit into a single virtual register");
355 Inst.addReg(SourceRegs[0]);
364 if (OpInfo.Regs.empty()) {
366 "could not allocate output register for "
368 Twine(OpInfo.ConstraintCode) +
"'",
369 GetOrCreateVRegs(
Call));
379 if (OpInfo.Regs.front().isVirtual()) {
385 Flag.setRegClass(RC->
getID());
397 OutputOperands.push_back(OpInfo);
403 if (OpInfo.isMatchingInputConstraint()) {
404 unsigned DefIdx = OpInfo.getMatchedOperand();
406 unsigned InstFlagIdx = StartIdx;
407 for (
unsigned i = 0; i < DefIdx; ++i)
411 const InlineAsm::Flag MatchedOperandFlag(Inst->getOperand(InstFlagIdx).getImm());
413 LLVM_DEBUG(
dbgs() <<
"Matching input constraint to mem operand not "
414 "supported. This should be target specific.\n");
423 unsigned DefRegIdx = InstFlagIdx + 1;
424 Register Def = Inst->getOperand(DefRegIdx).getReg();
427 assert(SrcRegs.
size() == 1 &&
"Single register is expected here");
438 Def.isVirtual() ? MRI->
getRegClass(Def) : OpInfo.RegClass;
439 assert(RC &&
"Expected a register class for matching constraint");
450 Inst.addImm(UseFlag);
452 Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1);
458 LLVM_DEBUG(
dbgs() <<
"Indirect input operands with unknown constraint "
459 "not supported yet\n");
466 std::vector<MachineOperand>
Ops;
468 OpInfo.ConstraintCode,
Ops,
471 << OpInfo.ConstraintCode <<
" yet\n");
476 "Expected constraint to be lowered to at least one operand");
479 const unsigned OpFlags =
481 Inst.addImm(OpFlags);
488 TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode);
491 Inst.addImm(OpFlags);
493 if (OpInfo.isIndirect) {
496 GetOrCreateVRegs(*OpInfo.CallOperandVal);
497 if (SourceRegs.
size() != 1) {
499 "single virtual register "
501 << OpInfo.ConstraintCode <<
"'\n");
504 Inst.addReg(SourceRegs[0]);
510 Value *OpVal = OpInfo.CallOperandVal;
516 unsigned AddrSpace =
DL.getAllocaAddrSpace();
521 GetOrCreateVRegs(*OpInfo.CallOperandVal);
522 if (SourceRegs.
size() != 1) {
523 LLVM_DEBUG(
dbgs() <<
"Expected the memory input to fit into a single "
526 << OpInfo.ConstraintCode <<
"'\n");
538 "Unknown constraint type!");
540 if (OpInfo.isIndirect) {
543 << OpInfo.ConstraintCode <<
"'\n");
548 if (OpInfo.Regs.empty()) {
550 "could not allocate input reg for constraint '" +
551 Twine(OpInfo.ConstraintCode) +
"'",
552 GetOrCreateVRegs(
Call));
556 unsigned NumRegs = OpInfo.Regs.size();
558 if (NumRegs != 1 || SourceRegs.
size() != 1) {
559 LLVM_DEBUG(
dbgs() <<
"Input operands with multiple input registers are "
560 "not supported yet\n");
565 if (OpInfo.Regs.front().isVirtual()) {
568 Flag.setRegClass(RC->
getID());
573 Inst.addReg(OpInfo.Regs[0]);
579 const unsigned NumRegs = OpInfo.Regs.size();
595 auto *Token = Bundle->Inputs[0].get();
598 "Expected the control token to fit into a single virtual register");
602 if (
const MDNode *SrcLoc =
Call.getMetadata(
"srcloc"))
603 Inst.addMetadata(SrcLoc);
617 if (ResRegs.
size() != OutputOperands.size()) {
618 LLVM_DEBUG(
dbgs() <<
"Expected the number of output registers to match the "
619 "number of destination registers\n");
622 for (
unsigned int i = 0, e = ResRegs.
size(); i < e; i++) {
623 GISelAsmOperandInfo &OpInfo = OutputOperands[i];
625 if (OpInfo.Regs.empty())
628 switch (OpInfo.ConstraintType) {
631 if (OpInfo.Regs.size() > 1) {
633 "registers are not supported yet\n");
638 unsigned SrcSize =
TRI->getRegSizeInBits(SrcReg, *MRI);
647 MIRBuilder.
buildCopy(ResRegs[i], SrcReg);
650 "mismatched register size\n");
659 dbgs() <<
"Cannot lower target specific output constraints yet\n");
677 if (Constraint.
size() > 1)
680 char ConstraintLetter = Constraint[0];
681 switch (ConstraintLetter) {
698 assert(CI->getBitWidth() <= 64 &&
699 "expected immediate to fit into 64-bits");
701 bool IsBool = CI->getBitWidth() == 1;
702 int64_t ExtVal = IsBool ? CI->getZExtValue() : CI->getSExtValue();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Module.h This file contains the declarations for the Module class.
static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx)
static void getRegistersForValue(MachineFunction &MF, MachineIRBuilder &MIRBuilder, GISelAsmOperandInfo &OpInfo, GISelAsmOperandInfo &RefOpInfo)
Assign virtual/physical registers for the specified register operand.
static void emitInlineAsmError(MachineIRBuilder &MIRBuilder, const CallBase &Call, const Twine &Message, ArrayRef< Register > ResRegs)
Emit an inline asm error diagnostic and materialize undef values for the call results so that the res...
static void computeConstraintToUse(const TargetLowering *TLI, TargetLowering::AsmOperandInfo &OpInfo)
static bool buildAnyextOrCopy(Register Dst, Register Src, MachineIRBuilder &MIRBuilder)
This file describes how to lower LLVM inline asm to machine code INLINEASM.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
This file describes how to lower LLVM code to machine code.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Value * getCalledOperand() const
bool isConvergent() const
Determine if the invoke is convergent.
This is the shared class of boolean and integer constants.
A parsed version of the target data layout string in and methods for querying it.
Diagnostic information for inline asm reporting.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool lowerInlineAsm(MachineIRBuilder &MIRBuilder, const CallBase &CB, std::function< ArrayRef< Register >(const Value &Val)> GetOrCreateVRegs) const
Lower the given inline asm call instruction GetOrCreateVRegs is a callback to materialize a register ...
virtual bool lowerAsmOperandForConstraint(Value *Val, StringRef Constraint, std::vector< MachineOperand > &Ops, MachineIRBuilder &MIRBuilder) const
Lower the specified operand into the Ops vector.
void setMatchingOp(unsigned OperandNo)
setMatchingOp - Augment an existing flag with information indicating that this input operand is tied ...
void setMemConstraint(ConstraintCode C)
setMemConstraint - Augment an existing flag with the constraint code for a memory constraint.
bool isRegDefEarlyClobberKind() const
bool isRegDefKind() const
constexpr bool isScalar() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
unsigned getID() const
getID() - Return the register class ID number.
const MCPhysReg * iterator
iterator begin() const
begin/end - Return all of the registers in this class.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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.
MachineInstrBuilder buildUndef(const DstOp &Res)
Build and insert Res = IMPLICIT_DEF.
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx)
Build and insert Res = G_FRAME_INDEX Idx.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
static MachineOperand CreateImm(int64_t Val)
static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
constexpr size_t size() const
Get the string size.
Class to represent struct types.
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SmallVector< ConstraintPair > ConstraintGroup
std::vector< AsmOperandInfo > AsmOperandInfoVector
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual const char * LowerXConstraint(EVT ConstraintVT) const
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
ConstraintGroup getConstraintPreferences(AsmOperandInfo &OpInfo) const
Given an OpInfo with list of constraints codes as strings, return a sorted Vector of pairs of constra...
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
This is an optimization pass for GlobalISel generic memory operations.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ EarlyClobber
Register definition happens before uses.
@ Define
Register definition.
constexpr RegState getImplRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr RegState getEarlyClobberRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.
ConstraintPrefix Type
Type - The basic type of the constraint: input/output/clobber/label.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This contains information for each constraint that we are lowering.
TargetLowering::ConstraintType ConstraintType
Information about the constraint code, e.g.