23#define DEBUG_TYPE "inline-asm-lowering"
27void InlineAsmLowering::anchor() {}
47 SmallVector<Register, 1> Regs;
49 explicit GISelAsmOperandInfo(
const TargetLowering::AsmOperandInfo &Info)
50 : TargetLowering::AsmOperandInfo(
Info) {}
59 explicit ExtraFlags(
const CallBase &CB) {
61 if (
IA->hasSideEffects())
63 if (
IA->isAlignStack())
72 void update(
const TargetLowering::AsmOperandInfo &OpInfo) {
88 unsigned get()
const {
return Flags; }
96 GISelAsmOperandInfo &OpInfo,
97 GISelAsmOperandInfo &RefOpInfo) {
111 &
TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
118 if (OpInfo.isMatchingInputConstraint())
122 unsigned NumRegs = 1;
123 if (OpInfo.ConstraintVT != MVT::Other)
137 for (; *
I != AssignedReg; ++
I)
138 assert(
I != RC->
end() &&
"AssignedReg should be a member of provided RC");
143 for (; NumRegs; --NumRegs, ++
I) {
144 assert(
I != RC->
end() &&
"Ran out of registers to allocate!");
146 OpInfo.Regs.push_back(R);
152 assert(!OpInfo.Codes.empty() &&
"Must have at least one constraint");
155 if (OpInfo.Codes.size() == 1) {
156 OpInfo.ConstraintCode = OpInfo.Codes[0];
163 unsigned BestIdx = 0;
164 for (
const unsigned E =
G.size();
169 OpInfo.ConstraintCode =
G[BestIdx].first;
170 OpInfo.ConstraintType =
G[BestIdx].second;
174 if (OpInfo.ConstraintCode ==
"X" && OpInfo.CallOperandVal) {
178 Value *Val = OpInfo.CallOperandVal;
185 OpInfo.ConstraintCode = Repl;
193 return F.getNumOperandRegisters();
202 auto SrcTy = MRI->
getType(Src);
203 if (!SrcTy.isValid()) {
207 unsigned SrcSize =
TRI->getRegSizeInBits(Src, *MRI);
208 unsigned DstSize =
TRI->getRegSizeInBits(Dst, *MRI);
210 if (DstSize < SrcSize) {
211 LLVM_DEBUG(
dbgs() <<
"Input can't fit in destination reg class\n");
216 if (DstSize > SrcSize) {
217 if (!SrcTy.isScalar()) {
219 "destination register class\n");
236 GISelAsmOperandInfoVector ConstraintOperands;
248 ExtraFlags ExtraInfo(
Call);
251 for (
auto &
T : TargetConstraints) {
252 ConstraintOperands.push_back(GISelAsmOperandInfo(
T));
253 GISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
256 if (OpInfo.hasArg()) {
257 OpInfo.CallOperandVal =
Call.getArgOperand(ArgNo);
260 LLVM_DEBUG(
dbgs() <<
"Basic block input operands not supported yet\n");
264 Type *OpTy = OpInfo.CallOperandVal->getType();
268 if (OpInfo.isIndirect) {
269 OpTy =
Call.getParamElementType(ArgNo);
270 assert(OpTy &&
"Indirect operand must have elementtype attribute");
276 dbgs() <<
"Aggregate input operands are not supported yet\n");
280 OpInfo.ConstraintVT =
281 TLI->getAsmOperandValueType(
DL, OpTy,
true).getSimpleVT();
284 assert(!
Call.getType()->isVoidTy() &&
"Bad inline asm!");
286 OpInfo.ConstraintVT =
287 TLI->getSimpleValueType(
DL, STy->getElementType(ResNo));
289 assert(ResNo == 0 &&
"Asm only has one result!");
290 OpInfo.ConstraintVT =
291 TLI->getAsmOperandValueType(
DL,
Call.getType()).getSimpleVT();
296 "GlobalISel currently doesn't support callbr");
297 OpInfo.ConstraintVT = MVT::Other;
300 if (OpInfo.ConstraintVT == MVT::i64x8)
307 ExtraInfo.update(OpInfo);
322 GISelAsmOperandInfoVector OutputOperands;
324 for (
auto &OpInfo : ConstraintOperands) {
325 GISelAsmOperandInfo &RefOpInfo =
326 OpInfo.isMatchingInputConstraint()
327 ? ConstraintOperands[OpInfo.getMatchedOperand()]
333 switch (OpInfo.Type) {
337 TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode);
339 "Failed to convert memory constraint code to constraint id.");
344 Flag.setMemConstraint(ConstraintID);
347 GetOrCreateVRegs(*OpInfo.CallOperandVal);
349 SourceRegs.
size() == 1 &&
350 "Expected the memory output to fit into a single virtual register");
351 Inst.addReg(SourceRegs[0]);
360 if (OpInfo.Regs.empty()) {
362 "could not allocate output register for "
364 Twine(OpInfo.ConstraintCode) +
"'",
365 GetOrCreateVRegs(
Call));
375 if (OpInfo.Regs.front().isVirtual()) {
381 Flag.setRegClass(RC->
getID());
393 OutputOperands.push_back(OpInfo);
399 if (OpInfo.isMatchingInputConstraint()) {
400 unsigned DefIdx = OpInfo.getMatchedOperand();
402 unsigned InstFlagIdx = StartIdx;
403 for (
unsigned i = 0; i < DefIdx; ++i)
407 const InlineAsm::Flag MatchedOperandFlag(Inst->getOperand(InstFlagIdx).getImm());
409 LLVM_DEBUG(
dbgs() <<
"Matching input constraint to mem operand not "
410 "supported. This should be target specific.\n");
419 unsigned DefRegIdx = InstFlagIdx + 1;
420 Register Def = Inst->getOperand(DefRegIdx).getReg();
423 assert(SrcRegs.
size() == 1 &&
"Single register is expected here");
435 :
TRI->getMinimalPhysRegClass(Def);
446 Inst.addImm(UseFlag);
448 Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1);
454 LLVM_DEBUG(
dbgs() <<
"Indirect input operands with unknown constraint "
455 "not supported yet\n");
462 std::vector<MachineOperand>
Ops;
464 OpInfo.ConstraintCode,
Ops,
467 << OpInfo.ConstraintCode <<
" yet\n");
472 "Expected constraint to be lowered to at least one operand");
475 const unsigned OpFlags =
477 Inst.addImm(OpFlags);
484 TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode);
487 Inst.addImm(OpFlags);
489 if (OpInfo.isIndirect) {
492 GetOrCreateVRegs(*OpInfo.CallOperandVal);
493 if (SourceRegs.
size() != 1) {
495 "single virtual register "
497 << OpInfo.ConstraintCode <<
"'\n");
500 Inst.addReg(SourceRegs[0]);
506 Value *OpVal = OpInfo.CallOperandVal;
512 unsigned AddrSpace =
DL.getAllocaAddrSpace();
517 GetOrCreateVRegs(*OpInfo.CallOperandVal);
518 if (SourceRegs.
size() != 1) {
519 LLVM_DEBUG(
dbgs() <<
"Expected the memory input to fit into a single "
522 << OpInfo.ConstraintCode <<
"'\n");
534 "Unknown constraint type!");
536 if (OpInfo.isIndirect) {
539 << OpInfo.ConstraintCode <<
"'\n");
544 if (OpInfo.Regs.empty()) {
546 "could not allocate input reg for constraint '" +
547 Twine(OpInfo.ConstraintCode) +
"'",
548 GetOrCreateVRegs(
Call));
552 unsigned NumRegs = OpInfo.Regs.size();
555 "Expected the number of input registers to match the number of "
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);
649 MIRBuilder.
buildCopy(ResRegs[i], SrcReg);
652 "mismatched register size\n");
661 dbgs() <<
"Cannot lower target specific output constraints yet\n");
679 if (Constraint.
size() > 1)
682 char ConstraintLetter = Constraint[0];
683 switch (ConstraintLetter) {
700 assert(CI->getBitWidth() <= 64 &&
701 "expected immediate to fit into 64-bits");
703 bool IsBool = CI->getBitWidth() == 1;
704 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 scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
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.
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.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
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.
unsigned getID() const
Return the register class ID number.
const MCPhysReg * iterator
iterator begin() const
begin/end - Return all of the registers in this class.
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.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
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.
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.