[llvm-branch-commits] [llvm] release/22.x: [X86][WinEH] Insert nop after unwinding inline assembly (#176393) (PR #176887)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jan 20 02:13:24 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: None (llvmbot)
<details>
<summary>Changes</summary>
Backport 792670a4003cba8636713916bed89a0b991fb32d
Requested by: @<!-- -->nikic
---
Full diff: https://github.com/llvm/llvm-project/pull/176887.diff
16 Files Affected:
- (modified) llvm/include/llvm/CodeGen/AsmPrinter.h (+8-7)
- (modified) llvm/include/llvm/IR/InlineAsm.h (+3)
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp (+8-6)
- (modified) llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp (+2)
- (modified) llvm/lib/CodeGen/MachineInstr.cpp (+2)
- (modified) llvm/lib/CodeGen/MachineVerifier.cpp (+2-2)
- (modified) llvm/lib/CodeGen/SelectionDAG/FastISel.cpp (+2)
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+2)
- (modified) llvm/lib/Target/ARM/ARMAsmPrinter.cpp (+2-1)
- (modified) llvm/lib/Target/ARM/ARMAsmPrinter.h (+2-1)
- (modified) llvm/lib/Target/Mips/MipsAsmPrinter.cpp (+2-1)
- (modified) llvm/lib/Target/Mips/MipsAsmPrinter.h (+2-1)
- (modified) llvm/lib/Target/X86/X86AsmPrinter.h (+4)
- (modified) llvm/lib/Target/X86/X86MCInstLower.cpp (+12)
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll (+1-1)
- (modified) llvm/test/CodeGen/X86/seh-unwind-inline-asm-codegen.ll (+2)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 7f99e81e7d1a0..707dd5ddcf515 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -908,7 +908,8 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
/// \p EndInfo - the final subtarget info after parsing the inline asm,
/// or NULL if the value is unknown.
virtual void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
- const MCSubtargetInfo *EndInfo) const;
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI);
/// This emits visibility information about symbol, if this is supported by
/// the target.
@@ -942,15 +943,15 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
void emitFunctionPrefix(ArrayRef<const Constant *> Prefix);
/// Emit a blob of inline asm to the output streamer.
- void
- emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
- const MCTargetOptions &MCOptions,
- const MDNode *LocMDNode = nullptr,
- InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const;
+ void emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
+ const MCTargetOptions &MCOptions,
+ const MDNode *LocMDNode = nullptr,
+ InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT,
+ const MachineInstr *MI = nullptr);
/// This method formats and emits the specified machine instruction that is an
/// inline asm.
- void emitInlineAsm(const MachineInstr *MI) const;
+ void emitInlineAsm(const MachineInstr *MI);
/// Add inline assembly info to the diagnostics machinery, so we can
/// emit file and position info. Returns SrcMgr memory buffer position.
diff --git a/llvm/include/llvm/IR/InlineAsm.h b/llvm/include/llvm/IR/InlineAsm.h
index 96887d129a69f..fed0ccc5818f8 100644
--- a/llvm/include/llvm/IR/InlineAsm.h
+++ b/llvm/include/llvm/IR/InlineAsm.h
@@ -220,6 +220,7 @@ class InlineAsm final : public Value {
Extra_MayLoad = 8,
Extra_MayStore = 16,
Extra_IsConvergent = 32,
+ Extra_MayUnwind = 64,
};
// Inline asm operands map to multiple SDNode / MachineInstr operands.
@@ -455,6 +456,8 @@ class InlineAsm final : public Value {
Result.push_back("isconvergent");
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
Result.push_back("alignstack");
+ if (ExtraInfo & InlineAsm::Extra_MayUnwind)
+ Result.push_back("unwind");
AsmDialect Dialect =
InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect));
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 69c2950711c7c..ae9fff80133d0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -73,7 +73,8 @@ unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr,
void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
const MCTargetOptions &MCOptions,
const MDNode *LocMDNode,
- InlineAsm::AsmDialect Dialect) const {
+ InlineAsm::AsmDialect Dialect,
+ const MachineInstr *MI) {
assert(!Str.empty() && "Can't emit empty inline asm block");
// Remember if the buffer is nul terminated or not so we can avoid a copy.
@@ -93,7 +94,7 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
!OutStreamer->isIntegratedAssemblerRequired()) {
emitInlineAsmStart();
OutStreamer->emitRawText(Str);
- emitInlineAsmEnd(STI, nullptr);
+ emitInlineAsmEnd(STI, nullptr, MI);
return;
}
@@ -135,7 +136,7 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
// Don't implicitly switch to the text section before the asm.
(void)Parser->Run(/*NoInitialTextSection*/ true,
/*NoFinalize*/ true);
- emitInlineAsmEnd(STI, &TAP->getSTI());
+ emitInlineAsmEnd(STI, &TAP->getSTI(), MI);
}
static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
@@ -336,7 +337,7 @@ static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
/// This method formats and emits the specified machine instruction that is an
/// inline asm.
-void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const {
+void AsmPrinter::emitInlineAsm(const MachineInstr *MI) {
assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
// Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
@@ -417,7 +418,7 @@ void AsmPrinter::emitInlineAsm(const MachineInstr *MI) const {
}
emitInlineAsm(StringData, getSubtargetInfo(), TM.Options.MCOptions, LocMD,
- MI->getInlineAsmDialect());
+ MI->getInlineAsmDialect(), MI);
// Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
// enabled, so we use emitRawComment.
@@ -518,4 +519,5 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
void AsmPrinter::emitInlineAsmStart() const {}
void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
- const MCSubtargetInfo *EndInfo) const {}
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI) {}
diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
index 2927b075fc360..41b6489064efd 100644
--- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
@@ -51,6 +51,8 @@ class ExtraFlags {
Flags |= InlineAsm::Extra_HasSideEffects;
if (IA->isAlignStack())
Flags |= InlineAsm::Extra_IsAlignStack;
+ if (IA->canThrow())
+ Flags |= InlineAsm::Extra_MayUnwind;
if (CB.isConvergent())
Flags |= InlineAsm::Extra_IsConvergent;
Flags |= IA->getDialect() * InlineAsm::Extra_AsmDialect;
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index c801d3deafa0f..003f78ecfddd0 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -1924,6 +1924,8 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
OS << " [isconvergent]";
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
OS << " [alignstack]";
+ if (ExtraInfo & InlineAsm::Extra_MayUnwind)
+ OS << " [unwind]";
if (getInlineAsmDialect() == InlineAsm::AD_ATT)
OS << " [attdialect]";
if (getInlineAsmDialect() == InlineAsm::AD_Intel)
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 5ce7606b051a5..9e64a19f1d017 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -955,8 +955,8 @@ void MachineVerifier::verifyInlineAsm(const MachineInstr *MI) {
report("Asm flags must be an immediate", MI);
// Allowed flags are Extra_HasSideEffects = 1, Extra_IsAlignStack = 2,
// Extra_AsmDialect = 4, Extra_MayLoad = 8, and Extra_MayStore = 16,
- // and Extra_IsConvergent = 32.
- if (!isUInt<6>(MI->getOperand(1).getImm()))
+ // and Extra_IsConvergent = 32, Extra_MayUnwind = 64.
+ if (!isUInt<7>(MI->getOperand(1).getImm()))
report("Unknown asm flags", &MI->getOperand(1), 1);
static_assert(InlineAsm::MIOp_FirstOperand == 2, "Asm format changed");
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 03727b77b3e1a..dd5587625e2aa 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1162,6 +1162,8 @@ bool FastISel::selectCall(const User *I) {
ExtraInfo |= InlineAsm::Extra_HasSideEffects;
if (IA->isAlignStack())
ExtraInfo |= InlineAsm::Extra_IsAlignStack;
+ if (IA->canThrow())
+ ExtraInfo |= InlineAsm::Extra_MayUnwind;
if (Call->isConvergent())
ExtraInfo |= InlineAsm::Extra_IsConvergent;
ExtraInfo |= IA->getDialect() * InlineAsm::Extra_AsmDialect;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index bc8a97cbcc024..e68339bd9b428 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10057,6 +10057,8 @@ class ExtraFlags {
Flags |= InlineAsm::Extra_HasSideEffects;
if (IA->isAlignStack())
Flags |= InlineAsm::Extra_IsAlignStack;
+ if (IA->canThrow())
+ Flags |= InlineAsm::Extra_MayUnwind;
if (Call.isConvergent())
Flags |= InlineAsm::Extra_IsConvergent;
Flags |= IA->getDialect() * InlineAsm::Extra_AsmDialect;
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index 458a3f0ced070..e7d30aec14860 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -519,7 +519,8 @@ static bool isThumb(const MCSubtargetInfo& STI) {
}
void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
- const MCSubtargetInfo *EndInfo) const {
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI) {
// If either end mode is unknown (EndInfo == NULL) or different than
// the start mode, then restore the start mode.
const bool WasThumb = isThumb(StartInfo);
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h
index 12e20d758e415..1d35b3c445958 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.h
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h
@@ -83,7 +83,8 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {
const char *ExtraCode, raw_ostream &O) override;
void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
- const MCSubtargetInfo *EndInfo) const override;
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI) override;
void emitJumpTableAddrs(const MachineInstr *MI);
void emitJumpTableInsts(const MachineInstr *MI);
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
index 9d8b9f86daf7a..a0e5872da5e6e 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -810,7 +810,8 @@ void MipsAsmPrinter::emitInlineAsmStart() const {
}
void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
- const MCSubtargetInfo *EndInfo) const {
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI) {
OutStreamer->addBlankLine();
getTargetStreamer().emitDirectiveSetPop();
}
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.h b/llvm/lib/Target/Mips/MipsAsmPrinter.h
index 8b2fb32dc552d..6d45ad551db72 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.h
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.h
@@ -83,7 +83,8 @@ class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter {
void emitInlineAsmStart() const override;
void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
- const MCSubtargetInfo *EndInfo) const override;
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI) override;
void emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
const MachineBasicBlock *MBB,
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h
index e02b5562d3b5e..705bb9a4aacfb 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.h
+++ b/llvm/lib/Target/X86/X86AsmPrinter.h
@@ -172,6 +172,10 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
void emitInstruction(const MachineInstr *MI) override;
+ void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI) override;
+
void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 2287a921a19c0..1dd702069843b 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -2627,6 +2627,18 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitAndCountInstruction(TmpInst);
}
+void X86AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
+ const MCSubtargetInfo *EndInfo,
+ const MachineInstr *MI) {
+ if (MI) {
+ // If unwinding inline asm ends on a call, wineh may require insertion of
+ // a nop.
+ unsigned ExtraInfo = MI->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ if (ExtraInfo & InlineAsm::Extra_MayUnwind)
+ maybeEmitNopAfterCallForWindowsEH(MI);
+ }
+}
+
void X86AsmPrinter::emitCallInstruction(const llvm::MCInst &MCI) {
// Stackmap shadows cannot include branch targets, so we can count the bytes
// in a call towards the shadow, but must ensure that the no thread returns
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll
index fbffb50bcbc8a..1d22682a804ea 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll
@@ -21,7 +21,7 @@ define dso_local void @test() personality ptr @__gxx_personality_v0 {
; CHECK-NEXT: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @.str.2
; CHECK-NEXT: G_INVOKE_REGION_START
; CHECK-NEXT: EH_LABEL <mcsymbol >
- ; CHECK-NEXT: INLINEASM &"bl trap", 1 /* sideeffect attdialect */
+ ; CHECK-NEXT: INLINEASM &"bl trap", 65 /* sideeffect unwind attdialect */
; CHECK-NEXT: EH_LABEL <mcsymbol >
; CHECK-NEXT: G_BR %bb.2
; CHECK-NEXT: {{ $}}
diff --git a/llvm/test/CodeGen/X86/seh-unwind-inline-asm-codegen.ll b/llvm/test/CodeGen/X86/seh-unwind-inline-asm-codegen.ll
index 5a6aeb6020344..e2959718b6068 100644
--- a/llvm/test/CodeGen/X86/seh-unwind-inline-asm-codegen.ll
+++ b/llvm/test/CodeGen/X86/seh-unwind-inline-asm-codegen.ll
@@ -15,6 +15,7 @@ entry:
; CHECK-LABEL: .Ltmp0:
; CHECK: callq trap
+; CHECK: nop
; CHECK-LABEL: .Ltmp1:
invoke void asm sideeffect unwind "call trap", "~{dirflag},~{fpsr},~{flags}"()
@@ -27,6 +28,7 @@ except:
; CHECK-LABEL: "?dtor$2@?0?test at 4HA":
; CHECK: callq printf
+; CHECK: nop
%0 = cleanuppad within none []
call void (ptr, ...) @printf(ptr @str) [ "funclet"(token %0) ]
``````````
</details>
https://github.com/llvm/llvm-project/pull/176887
More information about the llvm-branch-commits
mailing list