[llvm] a880c10 - [CodeGen][NFC] Refactor inline asm constraint determination (#195104)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 30 11:52:48 PDT 2026
Author: Bill Wendling
Date: 2026-04-30T11:52:42-07:00
New Revision: a880c10074b7d9d57cd5f2b1616025d7de0a736d
URL: https://github.com/llvm/llvm-project/commit/a880c10074b7d9d57cd5f2b1616025d7de0a736d
DIFF: https://github.com/llvm/llvm-project/commit/a880c10074b7d9d57cd5f2b1616025d7de0a736d.diff
LOG: [CodeGen][NFC] Refactor inline asm constraint determination (#195104)
The original function was very large and unwieldy. This also sets the
function up for future improvements.
Added:
Modified:
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index fb454afd141e2..3deb8b4f2cf22 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10193,32 +10193,38 @@ static bool isFunction(SDValue Op) {
return false;
}
-/// visitInlineAsm - Handle a call to an InlineAsm object.
-void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
- const BasicBlock *EHPadBB) {
- const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
+namespace {
- /// ConstraintOperands - Information about all of the constraints.
+struct ConstraintDecisionInfo {
SmallVector<SDISelAsmOperandInfo, 16> ConstraintOperands;
+ std::vector<SDValue> AsmNodeOperands;
+ SDValue Glue, Chain;
+ bool HasSideEffect = false;
+ MCSymbol *BeginLabel = nullptr;
- const TargetLowering &TLI = DAG.getTargetLoweringInfo();
- TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(
- DAG.getDataLayout(), DAG.getSubtarget().getRegisterInfo(), Call);
+ SmallVector<char> Buffer;
+ raw_svector_ostream ErrorMsg;
- // First Pass: Calculate HasSideEffects and ExtraFlags (AlignStack,
- // AsmDialect, MayLoad, MayStore).
- bool HasSideEffect = IA->hasSideEffects();
- ExtraFlags ExtraInfo(Call);
+ ConstraintDecisionInfo() : ErrorMsg(Buffer) {}
+};
+} // end anonymous namespace
+
+/// Construct operand info objects.
+static bool
+constructOperandInfo(ConstraintDecisionInfo &Info,
+ TargetLowering::AsmOperandInfoVector &TargetConstraints,
+ SelectionDAGBuilder &Builder, const TargetLowering &TLI,
+ ExtraFlags &ExtraInfo) {
for (auto &T : TargetConstraints) {
- ConstraintOperands.push_back(SDISelAsmOperandInfo(T));
- SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
+ Info.ConstraintOperands.push_back(SDISelAsmOperandInfo(T));
+ SDISelAsmOperandInfo &OpInfo = Info.ConstraintOperands.back();
if (OpInfo.CallOperandVal)
- OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
+ OpInfo.CallOperand = Builder.getValue(OpInfo.CallOperandVal);
- if (!HasSideEffect)
- HasSideEffect = OpInfo.hasMemory(TLI);
+ if (!Info.HasSideEffect)
+ Info.HasSideEffect = OpInfo.hasMemory(TLI);
// Determine if this InlineAsm MayLoad or MayStore based on the constraints.
// FIXME: Could we compute this on OpInfo rather than T?
@@ -10226,45 +10232,33 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// Compute the constraint code and ConstraintType to use.
TLI.ComputeConstraintToUse(T, SDValue());
- if (T.ConstraintType == TargetLowering::C_Immediate &&
- OpInfo.CallOperand && !isa<ConstantSDNode>(OpInfo.CallOperand))
+ if (T.ConstraintType == TargetLowering::C_Immediate && OpInfo.CallOperand &&
+ !isa<ConstantSDNode>(OpInfo.CallOperand)) {
// We've delayed emitting a diagnostic like the "n" constraint because
// inlining could cause an integer showing up.
- return emitInlineAsmError(Call, "constraint '" + Twine(T.ConstraintCode) +
- "' expects an integer constant "
- "expression");
+ Info.ErrorMsg << "constraint '" << T.ConstraintCode
+ << "' expects an integer constant expression";
+ return true;
+ }
ExtraInfo.update(T);
}
- // We won't need to flush pending loads if this asm doesn't touch
- // memory and is nonvolatile.
- SDValue Glue, Chain = (HasSideEffect) ? getRoot() : DAG.getRoot();
-
- bool EmitEHLabels = isa<InvokeInst>(Call);
- if (EmitEHLabels) {
- assert(EHPadBB && "InvokeInst must have an EHPadBB");
- }
- bool IsCallBr = isa<CallBrInst>(Call);
-
- if (IsCallBr || EmitEHLabels) {
- // If this is a callbr or invoke we need to flush pending exports since
- // inlineasm_br and invoke are terminators.
- // We need to do this before nodes are glued to the inlineasm_br node.
- Chain = getControlRoot();
- }
-
- MCSymbol *BeginLabel = nullptr;
- if (EmitEHLabels) {
- Chain = lowerStartEH(Chain, EHPadBB, BeginLabel);
- }
+ return false;
+}
- int OpNo = -1;
- SmallVector<StringRef> AsmStrs;
+/// Compute which constraint option to use for each operand.
+static void
+computeConstraintToUse(ConstraintDecisionInfo &Info, const CallBase &Call,
+ TargetLowering::AsmOperandInfoVector &TargetConstraints,
+ SelectionDAGBuilder &Builder, const TargetLowering &TLI,
+ const TargetMachine &TM, SelectionDAG &DAG) {
+ const auto *IA = cast<InlineAsm>(Call.getCalledOperand());
+ SmallVector<StringRef, 4> AsmStrs;
IA->collectAsmStrs(AsmStrs);
- // Second pass over the constraints: compute which constraint option to use.
- for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
+ int OpNo = -1;
+ for (SDISelAsmOperandInfo &OpInfo : Info.ConstraintOperands) {
if (OpInfo.hasArg() || OpInfo.Type == InlineAsm::isOutput)
OpNo++;
@@ -10273,7 +10267,8 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// other is floating point, or their sizes are
diff erent, flag it as an
// error.
if (OpInfo.hasMatchingInput()) {
- SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
+ SDISelAsmOperandInfo &Input =
+ Info.ConstraintOperands[OpInfo.MatchingInput];
patchMatchingInput(OpInfo, Input, DAG);
}
@@ -10320,7 +10315,8 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
"Can only indirectify direct input operands!");
// Memory operands really want the address of the value.
- Chain = getAddressForMemoryInput(Chain, getCurSDLoc(), OpInfo, DAG);
+ Info.Chain = getAddressForMemoryInput(Info.Chain, Builder.getCurSDLoc(),
+ OpInfo, DAG);
// There is no longer a Value* corresponding to this operand.
OpInfo.CallOperandVal = nullptr;
@@ -10328,58 +10324,46 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// It is now an indirect operand.
OpInfo.isIndirect = true;
}
-
}
+}
- // AsmNodeOperands - The operands for the ISD::INLINEASM node.
- std::vector<SDValue> AsmNodeOperands;
- AsmNodeOperands.push_back(SDValue()); // reserve space for input chain
- AsmNodeOperands.push_back(DAG.getTargetExternalSymbol(
- IA->getAsmString().data(), TLI.getProgramPointerTy(DAG.getDataLayout())));
-
- // If we have a !srcloc metadata node associated with it, we want to attach
- // this to the ultimately generated inline asm machineinstr. To do this, we
- // pass in the third operand as this (potentially null) inline asm MDNode.
- const MDNode *SrcLoc = Call.getMetadata("srcloc");
- AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc));
-
- // Remember the HasSideEffect, AlignStack, AsmDialect, MayLoad and MayStore
- // bits as operand 3.
- AsmNodeOperands.push_back(DAG.getTargetConstant(
- ExtraInfo.get(), getCurSDLoc(), TLI.getPointerTy(DAG.getDataLayout())));
-
- // Third pass: Loop over operands to prepare DAG-level operands.. As part of
- // this, assign virtual and physical registers for inputs and otput.
- for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
+/// Prepare DAG-level operands. As part of this, assign virtual and physical
+/// registers for inputs and output.
+static bool prepareDAGLevelOperands(ConstraintDecisionInfo &Info,
+ const CallBase &Call,
+ SelectionDAGBuilder &Builder,
+ const TargetLowering &TLI,
+ SelectionDAG &DAG) {
+ SDLoc DL = Builder.getCurSDLoc();
+ for (SDISelAsmOperandInfo &OpInfo : Info.ConstraintOperands) {
// Assign Registers.
SDISelAsmOperandInfo &RefOpInfo =
OpInfo.isMatchingInputConstraint()
- ? ConstraintOperands[OpInfo.getMatchedOperand()]
+ ? Info.ConstraintOperands[OpInfo.getMatchedOperand()]
: OpInfo;
- const auto RegError =
- getRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
+ const auto RegError = getRegistersForValue(DAG, DL, OpInfo, RefOpInfo);
if (RegError) {
const MachineFunction &MF = DAG.getMachineFunction();
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
const char *RegName = TRI.getName(*RegError);
- emitInlineAsmError(Call, "register '" + Twine(RegName) +
- "' allocated for constraint '" +
- Twine(OpInfo.ConstraintCode) +
- "' does not match required type");
- return;
+ Info.ErrorMsg << "register '" << RegName << "' allocated for constraint '"
+ << OpInfo.ConstraintCode
+ << "' does not match required type";
+ return true;
}
auto DetectWriteToReservedRegister = [&]() {
const MachineFunction &MF = DAG.getMachineFunction();
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
+
for (Register Reg : OpInfo.AssignedRegs.Regs) {
if (Reg.isPhysical() && TRI.isInlineAsmReadOnlyReg(MF, Reg)) {
- const char *RegName = TRI.getName(Reg);
- emitInlineAsmError(Call, "write to reserved register '" +
- Twine(RegName) + "'");
+ Info.ErrorMsg << "write to reserved register '"
+ << TRI.getRegAsmName(Reg) << "'";
return true;
}
}
+
return false;
};
assert((OpInfo.ConstraintType != TargetLowering::C_Address ||
@@ -10398,29 +10382,28 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// Add information to the INLINEASM node to know about this output.
InlineAsm::Flag OpFlags(InlineAsm::Kind::Mem, 1);
OpFlags.setMemConstraint(ConstraintID);
- AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlags, getCurSDLoc(),
- MVT::i32));
- AsmNodeOperands.push_back(OpInfo.CallOperand);
+ Info.AsmNodeOperands.push_back(
+ DAG.getTargetConstant(OpFlags, DL, MVT::i32));
+ Info.AsmNodeOperands.push_back(OpInfo.CallOperand);
} else {
// Otherwise, this outputs to a register (directly for C_Register /
// C_RegisterClass, and a target-defined fashion for
// C_Immediate/C_Other). Find a register that we can use.
if (OpInfo.AssignedRegs.Regs.empty()) {
- emitInlineAsmError(
- Call, "couldn't allocate output register for constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
- return;
+ Info.ErrorMsg << "couldn't allocate output register for "
+ << "constraint '" << OpInfo.ConstraintCode << "'";
+ return true;
}
if (DetectWriteToReservedRegister())
- return;
+ return true;
// Add information to the INLINEASM node to know that this register is
// set.
OpInfo.AssignedRegs.AddInlineAsmOperands(
OpInfo.isEarlyClobber ? InlineAsm::Kind::RegDefEarlyClobber
: InlineAsm::Kind::RegDef,
- false, 0, getCurSDLoc(), DAG, AsmNodeOperands);
+ false, 0, DL, DAG, Info.AsmNodeOperands);
}
break;
@@ -10432,52 +10415,52 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// If this is required to match an output register we have already set,
// just use its register.
auto CurOp = findMatchingInlineAsmOperand(OpInfo.getMatchedOperand(),
- AsmNodeOperands);
- InlineAsm::Flag Flag(AsmNodeOperands[CurOp]->getAsZExtVal());
+ Info.AsmNodeOperands);
+ InlineAsm::Flag Flag(Info.AsmNodeOperands[CurOp]->getAsZExtVal());
if (Flag.isRegDefKind() || Flag.isRegDefEarlyClobberKind()) {
if (OpInfo.isIndirect) {
// This happens on gcc/testsuite/gcc.dg/pr8788-1.c
- emitInlineAsmError(Call, "inline asm not supported yet: "
- "don't know how to handle tied "
- "indirect register inputs");
- return;
+ Info.ErrorMsg << "inline asm not supported yet: don't know how "
+ << "to handle tied indirect register inputs";
+ return true;
}
SmallVector<Register, 4> Regs;
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &MRI = MF.getRegInfo();
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
- auto *R = cast<RegisterSDNode>(AsmNodeOperands[CurOp+1]);
+ auto *R = cast<RegisterSDNode>(Info.AsmNodeOperands[CurOp + 1]);
Register TiedReg = R->getReg();
MVT RegVT = R->getSimpleValueType(0);
const TargetRegisterClass *RC =
TiedReg.isVirtual() ? MRI.getRegClass(TiedReg)
: RegVT != MVT::Untyped ? TLI.getRegClassFor(RegVT)
: TRI.getMinimalPhysRegClass(TiedReg);
- for (unsigned i = 0, e = Flag.getNumOperandRegisters(); i != e; ++i)
+ for (unsigned I = 0, E = Flag.getNumOperandRegisters(); I != E; ++I)
Regs.push_back(MRI.createVirtualRegister(RC));
RegsForValue MatchedRegs(Regs, RegVT, InOperandVal.getValueType());
- SDLoc dl = getCurSDLoc();
// Use the produced MatchedRegs object to
- MatchedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Glue, &Call);
+ MatchedRegs.getCopyToRegs(InOperandVal, DAG, DL, Info.Chain,
+ &Info.Glue, &Call);
MatchedRegs.AddInlineAsmOperands(InlineAsm::Kind::RegUse, true,
- OpInfo.getMatchedOperand(), dl, DAG,
- AsmNodeOperands);
+ OpInfo.getMatchedOperand(), DL, DAG,
+ Info.AsmNodeOperands);
break;
}
assert(Flag.isMemKind() && "Unknown matching constraint!");
assert(Flag.getNumOperandRegisters() == 1 &&
"Unexpected number of operands");
+
// Add information to the INLINEASM node to know about this input.
// See InlineAsm.h isUseOperandTiedToDef.
Flag.clearMemConstraint();
Flag.setMatchingOp(OpInfo.getMatchedOperand());
- AsmNodeOperands.push_back(DAG.getTargetConstant(
- Flag, getCurSDLoc(), TLI.getPointerTy(DAG.getDataLayout())));
- AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
+ Info.AsmNodeOperands.push_back(DAG.getTargetConstant(
+ Flag, DL, TLI.getPointerTy(DAG.getDataLayout())));
+ Info.AsmNodeOperands.push_back(Info.AsmNodeOperands[CurOp + 1]);
break;
}
@@ -10494,22 +10477,21 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
if (Ops.empty()) {
if (OpInfo.ConstraintType == TargetLowering::C_Immediate)
if (isa<ConstantSDNode>(InOperandVal)) {
- emitInlineAsmError(Call, "value out of range for constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
- return;
+ Info.ErrorMsg << "value out of range for constraint '"
+ << OpInfo.ConstraintCode << "'";
+ return true;
}
- emitInlineAsmError(Call,
- "invalid operand for inline asm constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
- return;
+ Info.ErrorMsg << "invalid operand for inline asm constraint '"
+ << OpInfo.ConstraintCode << "'";
+ return true;
}
// Add information to the INLINEASM node to know about this input.
InlineAsm::Flag ResOpType(InlineAsm::Kind::Imm, Ops.size());
- AsmNodeOperands.push_back(DAG.getTargetConstant(
- ResOpType, getCurSDLoc(), TLI.getPointerTy(DAG.getDataLayout())));
- llvm::append_range(AsmNodeOperands, Ops);
+ Info.AsmNodeOperands.push_back(DAG.getTargetConstant(
+ ResOpType, DL, TLI.getPointerTy(DAG.getDataLayout())));
+ llvm::append_range(Info.AsmNodeOperands, Ops);
break;
}
@@ -10529,10 +10511,9 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// Add information to the INLINEASM node to know about this input.
InlineAsm::Flag ResOpType(InlineAsm::Kind::Mem, 1);
ResOpType.setMemConstraint(ConstraintID);
- AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
- getCurSDLoc(),
- MVT::i32));
- AsmNodeOperands.push_back(InOperandVal);
+ Info.AsmNodeOperands.push_back(
+ DAG.getTargetConstant(ResOpType, DL, MVT::i32));
+ Info.AsmNodeOperands.push_back(InOperandVal);
break;
}
@@ -10548,7 +10529,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
if (isFunction(InOperandVal)) {
auto *GA = cast<GlobalAddressSDNode>(InOperandVal);
ResOpType = InlineAsm::Flag(InlineAsm::Kind::Func, 1);
- AsmOp = DAG.getTargetGlobalAddress(GA->getGlobal(), getCurSDLoc(),
+ AsmOp = DAG.getTargetGlobalAddress(GA->getGlobal(), DL,
InOperandVal.getValueType(),
GA->getOffset());
}
@@ -10556,67 +10537,138 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// Add information to the INLINEASM node to know about this input.
ResOpType.setMemConstraint(ConstraintID);
- AsmNodeOperands.push_back(
- DAG.getTargetConstant(ResOpType, getCurSDLoc(), MVT::i32));
-
- AsmNodeOperands.push_back(AsmOp);
+ Info.AsmNodeOperands.push_back(
+ DAG.getTargetConstant(ResOpType, DL, MVT::i32));
+ Info.AsmNodeOperands.push_back(AsmOp);
break;
}
if (OpInfo.ConstraintType != TargetLowering::C_RegisterClass &&
OpInfo.ConstraintType != TargetLowering::C_Register) {
- emitInlineAsmError(Call, "unknown asm constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
- return;
+ Info.ErrorMsg << "unknown asm constraint '" << OpInfo.ConstraintCode
+ << "'";
+ return true;
}
// TODO: Support this.
if (OpInfo.isIndirect) {
- emitInlineAsmError(
- Call, "Don't know how to handle indirect register inputs yet "
- "for constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
- return;
+ Info.ErrorMsg << "Don't know how to handle indirect register inputs "
+ << "yet for constraint '" << OpInfo.ConstraintCode << "'";
+ return true;
}
// Copy the input into the appropriate registers.
if (OpInfo.AssignedRegs.Regs.empty()) {
- emitInlineAsmError(Call,
- "couldn't allocate input reg for constraint '" +
- Twine(OpInfo.ConstraintCode) + "'");
- return;
+ Info.ErrorMsg << "couldn't allocate input reg for constraint '"
+ << OpInfo.ConstraintCode << "'";
+ return true;
}
if (DetectWriteToReservedRegister())
- return;
-
- SDLoc dl = getCurSDLoc();
-
- OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Glue,
- &Call);
+ return true;
- OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind::RegUse, false,
- 0, dl, DAG, AsmNodeOperands);
+ OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, DL, Info.Chain,
+ &Info.Glue, &Call);
+ OpInfo.AssignedRegs.AddInlineAsmOperands(
+ InlineAsm::Kind::RegUse, false, 0, DL, DAG, Info.AsmNodeOperands);
break;
}
+
case InlineAsm::isClobber:
// Add the clobbered value to the operand list, so that the register
// allocator is aware that the physreg got clobbered.
if (!OpInfo.AssignedRegs.Regs.empty())
- OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind::Clobber,
- false, 0, getCurSDLoc(), DAG,
- AsmNodeOperands);
+ OpInfo.AssignedRegs.AddInlineAsmOperands(
+ InlineAsm::Kind::Clobber, false, 0, DL, DAG, Info.AsmNodeOperands);
break;
}
}
+ return false;
+}
+
+/// DetermineConstraints - Find the constraints to use for inline asm operands.
+static bool
+determineConstraints(ConstraintDecisionInfo &Info,
+ TargetLowering::AsmOperandInfoVector &TargetConstraints,
+ const CallBase &Call, SelectionDAGBuilder &Builder,
+ const TargetLowering &TLI, const TargetMachine &TM,
+ SelectionDAG &DAG, const BasicBlock *EHPadBB) {
+ const auto *IA = cast<InlineAsm>(Call.getCalledOperand());
+ ExtraFlags ExtraInfo(Call);
+
+ // First pass: Construct operand info objects.
+ Info.HasSideEffect = IA->hasSideEffects();
+ if (constructOperandInfo(Info, TargetConstraints, Builder, TLI, ExtraInfo))
+ return true;
+
+ // We won't need to flush pending loads if this asm doesn't touch
+ // memory and is nonvolatile.
+ Info.Chain = Info.HasSideEffect ? Builder.getRoot() : DAG.getRoot();
+
+ bool IsCallBr = isa<CallBrInst>(Call);
+ bool EmitEHLabels = isa<InvokeInst>(Call);
+ if (IsCallBr || EmitEHLabels)
+ // If this is a callbr or invoke we need to flush pending exports since
+ // inlineasm_br and invoke are terminators.
+ // We need to do this before nodes are glued to the inlineasm_br node.
+ Info.Chain = Builder.getControlRoot();
+
+ if (EmitEHLabels)
+ Info.Chain = Builder.lowerStartEH(Info.Chain, EHPadBB, Info.BeginLabel);
+
+ // Second pass: Compute which constraint option to use.
+ computeConstraintToUse(Info, Call, TargetConstraints, Builder, TLI, TM, DAG);
+
+ // AsmNodeOperands - The operands for the ISD::INLINEASM node.
+ Info.AsmNodeOperands.push_back(SDValue()); // reserve space for input chain
+ Info.AsmNodeOperands.push_back(DAG.getTargetExternalSymbol(
+ IA->getAsmString().data(), TLI.getProgramPointerTy(DAG.getDataLayout())));
+
+ // If we have a !srcloc metadata node associated with it, we want to attach
+ // this to the ultimately generated inline asm machineinstr. To do this, we
+ // pass in the third operand as this (potentially null) inline asm MDNode.
+ const MDNode *SrcLoc = Call.getMetadata("srcloc");
+ Info.AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc));
+
+ // Remember the HasSideEffect, AlignStack, AsmDialect, MayLoad and MayStore
+ // bits as operand 3.
+ Info.AsmNodeOperands.push_back(
+ DAG.getTargetConstant(ExtraInfo.get(), Builder.getCurSDLoc(),
+ TLI.getPointerTy(DAG.getDataLayout())));
+
+ // Third pass: Prepare DAG-level operands
+ return prepareDAGLevelOperands(Info, Call, Builder, TLI, DAG);
+}
+
+/// visitInlineAsm - Handle a call to an InlineAsm object.
+void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
+ const BasicBlock *EHPadBB) {
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(
+ DAG.getDataLayout(), DAG.getSubtarget().getRegisterInfo(), Call);
+
+ assert((!isa<InvokeInst>(Call) || EHPadBB) &&
+ "InvokeInst must have an EHPadBB");
+
+ ConstraintDecisionInfo Info;
+ if (determineConstraints(Info, TargetConstraints, Call, *this, TLI, TM, DAG,
+ EHPadBB))
+ return emitInlineAsmError(Call, Info.ErrorMsg.str());
+
+ SDValue Glue = Info.Glue;
+ SDValue Chain = Info.Chain;
+
// Finish up input operands. Set the input chain and add the flag last.
- AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
- if (Glue.getNode()) AsmNodeOperands.push_back(Glue);
+ Info.AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
+ if (Glue.getNode())
+ Info.AsmNodeOperands.push_back(Glue);
+ bool IsCallBr = isa<CallBrInst>(Call);
unsigned ISDOpc = IsCallBr ? ISD::INLINEASM_BR : ISD::INLINEASM;
- Chain = DAG.getNode(ISDOpc, getCurSDLoc(),
- DAG.getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
+ Chain =
+ DAG.getNode(ISDOpc, getCurSDLoc(), DAG.getVTList(MVT::Other, MVT::Glue),
+ Info.AsmNodeOperands);
Glue = Chain.getValue(1);
// Do additional work to generate outputs.
@@ -10664,7 +10716,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
};
// Deal with output operands.
- for (SDISelAsmOperandInfo &OpInfo : ConstraintOperands) {
+ for (SDISelAsmOperandInfo &OpInfo : Info.ConstraintOperands) {
if (OpInfo.Type == InlineAsm::isOutput) {
SDValue Val;
// Skip trivial output operands.
@@ -10725,13 +10777,12 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
if (!OutChains.empty())
Chain = DAG.getNode(ISD::TokenFactor, getCurSDLoc(), MVT::Other, OutChains);
- if (EmitEHLabels) {
- Chain = lowerEndEH(Chain, cast<InvokeInst>(&Call), EHPadBB, BeginLabel);
- }
+ if (const auto *II = dyn_cast<InvokeInst>(&Call))
+ Chain = lowerEndEH(Chain, II, EHPadBB, Info.BeginLabel);
// Only Update Root if inline assembly has a memory effect.
- if (ResultValues.empty() || HasSideEffect || !OutChains.empty() || IsCallBr ||
- EmitEHLabels)
+ if (ResultValues.empty() || Info.HasSideEffect || !OutChains.empty() ||
+ IsCallBr || isa<InvokeInst>(Call))
DAG.setRoot(Chain);
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index bab0509dd138f..21aac333a73cd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -733,8 +733,11 @@ class SelectionDAGBuilder {
DIExpression *Expr, const DebugLoc &dl,
unsigned DbgSDNodeOrder);
+public:
SDValue lowerStartEH(SDValue Chain, const BasicBlock *EHPadBB,
MCSymbol *&BeginLabel);
+
+private:
SDValue lowerEndEH(SDValue Chain, const InvokeInst *II,
const BasicBlock *EHPadBB, MCSymbol *BeginLabel);
More information about the llvm-commits
mailing list