diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1035,9 +1035,11 @@ /// bytes. Return the size of nop emitted. static unsigned EmitNop(MCStreamer &OS, unsigned NumBytes, bool Is64Bit, const MCSubtargetInfo &STI) { - // This works only for 64bit. For 32bit we have to do additional checking if - // the CPU supports multi-byte nops. - assert(Is64Bit && "EmitNops only supports X86-64"); + if (!Is64Bit) { + // TODO Do additional checking if the CPU supports multi-byte nops. + OS.EmitInstruction(MCInstBuilder(X86::NOOP), STI); + return 1; + } unsigned NopSize; unsigned Opc, BaseReg, ScaleVal, IndexReg, Displacement, SegmentReg; @@ -1597,6 +1599,16 @@ NoAutoPaddingScope NoPadScope(*OutStreamer); + const Function &F = MF->getFunction(); + if (F.hasFnAttribute("patchable-function-entry")) { + unsigned Num; + if (F.getFnAttribute("patchable-function-entry") + .getValueAsString() + .getAsInteger(10, Num)) + return; + EmitNops(*OutStreamer, Num, Subtarget->is64Bit(), getSubtargetInfo()); + return; + } // We want to emit the following pattern: // // .p2align 1, ... diff --git a/llvm/test/CodeGen/X86/patchable-function-entry.ll b/llvm/test/CodeGen/X86/patchable-function-entry.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/patchable-function-entry.ll @@ -0,0 +1,58 @@ +; RUN: llc -mtriple=i386 %s -o - | FileCheck --check-prefixes=CHECK,NOFSECT,32 %s +; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,NOFSECT,64 %s + +define void @f0() "patchable-function-entry"="0" { +; CHECK-LABEL: f0: +; CHECK-NEXT: .Lfunc_begin0: +; CHECK-NOT: nop +; CHECK: ret +; CHECK: .section __patchable_function_entries,"awo",@progbits,f0,unique,0 +; 32: .p2align 2 +; 32-NEXT: .long .Lfunc_begin0 +; 64: .p2align 3 +; 64-NEXT: .quad .Lfunc_begin0 + ret void +} + +define void @f1() "patchable-function-entry"="1" { +; CHECK-LABEL: f1: +; CHECK: nop +; CHECK-NEXT: ret +; NOFSECT: .section __patchable_function_entries,"awo",@progbits,f0,unique,0 +; FSECT: .section __patchable_function_entries,"awo",@progbits,f1,unique,1 +; 32: .p2align 2 +; 32-NEXT: .long .Lfunc_begin1 +; 64: .p2align 3 +; 64-NEXT: .quad .Lfunc_begin1 + ret void +} + +$f3 = comdat any +define void @f3() "patchable-function-entry"="3" comdat { +; CHECK-LABEL: f3: +; 32-COUNT-3: nop +; 64: nopl (%rax) +; CHECK: ret +; NOFSECT: .section __patchable_function_entries,"aGwo",@progbits,f3,comdat,f3,unique,1 +; FSECT: .section __patchable_function_entries,"aGwo",@progbits,f3,comdat,f3,unique,2 +; 32: .p2align 2 +; 32-NEXT: .long .Lfunc_begin2 +; 64: .p2align 3 +; 64-NEXT: .quad .Lfunc_begin2 + ret void +} + +$f5 = comdat any +define void @f5() "patchable-function-entry"="5" comdat { +; CHECK-LABEL: f5: +; 32-COUNT-5: nop +; 64: nopl 8(%rax,%rax) +; CHECK-NEXT: ret +; NOFSECT .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5,unique,2 +; FSECT: .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5,unique,3 +; 32: .p2align 2 +; 32-NEXT: .long .Lfunc_begin3 +; 64: .p2align 3 +; 64-NEXT: .quad .Lfunc_begin3 + ret void +}