Index: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp +++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp @@ -1381,6 +1381,18 @@ if (PushedRegs) emitCalleeSavedFrameMoves(MBB, MBBI, DL); } + + // X86 Interrupt handling function cannot assume anything about the direction + // flag (DF in EFLAGS register). Clear this flag by creating "cld" instruction + // in each prologue of interrupt handler function. + // + // FIXME: Create "cld" instruction only in these cases: + // 1. The interrupt handling function uses any of the "rep" instructions. + // 2. Interrupt handling function calls another function. + // + if (Fn->getCallingConv() == CallingConv::X86_INTR) + BuildMI(MBB, MBBI, DL, TII.get(X86::CLD)) + .setMIFlag(MachineInstr::FrameSetup); } bool X86FrameLowering::canUseLEAForSPInEpilogue( Index: llvm/trunk/test/CodeGen/X86/x86-interrupt_cld.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/x86-interrupt_cld.ll +++ llvm/trunk/test/CodeGen/X86/x86-interrupt_cld.ll @@ -0,0 +1,17 @@ +; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Checks that interrupt handler code calls cld before calling an external +;; function. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; CHECK: cld +; CHECK: call + +define x86_intrcc void @foo(i8* %frame) { + call void @bar() + ret void +} + +declare void @bar() +