forked from OSchip/llvm-project
[X86] Support ``-mindirect-branch-cs-prefix`` for call and jmp to indirect thunk
This is to address feature request from https://github.com/ClangBuiltLinux/linux/issues/1665 Reviewed By: nickdesaulniers, MaskRay Differential Revision: https://reviews.llvm.org/D130754
This commit is contained in:
parent
45bae1be90
commit
6f867f9102
|
@ -138,6 +138,8 @@ CUDA Support in Clang
|
|||
X86 Support in Clang
|
||||
--------------------
|
||||
|
||||
- Support ``-mindirect-branch-cs-prefix`` for call and jmp to indirect thunk.
|
||||
|
||||
DWARF Support in Clang
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -108,6 +108,8 @@ CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is
|
|||
///< set to full or branch.
|
||||
CODEGENOPT(IBTSeal, 1, 0) ///< set to optimize CFProtectionBranch.
|
||||
CODEGENOPT(FunctionReturnThunks, 1, 0) ///< -mfunction-return={keep|thunk-extern}
|
||||
CODEGENOPT(IndirectBranchCSPrefix, 1, 0) ///< if -mindirect-branch-cs-prefix
|
||||
///< is set.
|
||||
|
||||
CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is
|
||||
///< enabled.
|
||||
|
|
|
@ -2025,6 +2025,10 @@ def mfunction_return_EQ : Joined<["-"], "mfunction-return=">,
|
|||
NormalizedValues<["Keep", "Extern"]>,
|
||||
NormalizedValuesScope<"llvm::FunctionReturnThunksKind">,
|
||||
MarshallingInfoEnum<CodeGenOpts<"FunctionReturnThunks">, "Keep">;
|
||||
def mindirect_branch_cs_prefix : Flag<["-"], "mindirect-branch-cs-prefix">,
|
||||
Group<m_Group>, Flags<[CoreOption, CC1Option]>,
|
||||
HelpText<"Add cs prefix to call and jmp to indirect thunk">,
|
||||
MarshallingInfoFlag<CodeGenOpts<"IndirectBranchCSPrefix">>;
|
||||
|
||||
defm xray_instrument : BoolFOption<"xray-instrument",
|
||||
LangOpts<"XRayInstrument">, DefaultFalse,
|
||||
|
|
|
@ -775,6 +775,9 @@ void CodeGenModule::Release() {
|
|||
if (CodeGenOpts.FunctionReturnThunks)
|
||||
getModule().addModuleFlag(llvm::Module::Override, "function_return_thunk_extern", 1);
|
||||
|
||||
if (CodeGenOpts.IndirectBranchCSPrefix)
|
||||
getModule().addModuleFlag(llvm::Module::Override, "indirect_branch_cs_prefix", 1);
|
||||
|
||||
// Add module metadata for return address signing (ignoring
|
||||
// non-leaf/all) and stack tagging. These are actually turned on by function
|
||||
// attributes, but we use module metadata to emit build attributes. This is
|
||||
|
|
|
@ -6359,6 +6359,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
CmdArgs.push_back(
|
||||
Args.MakeArgString(Twine("-mfunction-return=") + A->getValue()));
|
||||
|
||||
Args.AddLastArg(CmdArgs, options::OPT_mindirect_branch_cs_prefix);
|
||||
|
||||
// Forward -f options with positive and negative forms; we translate these by
|
||||
// hand. Do not propagate PGO options to the GPU-side compilations as the
|
||||
// profile info is for the host-side compilation only.
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// RUN: %clang -target i386-unknown-unknown -o - -emit-llvm -S -mindirect-branch-cs-prefix %s | FileCheck %s
|
||||
|
||||
// CHECK: !{i32 4, !"indirect_branch_cs_prefix", i32 1}
|
||||
void foo() {}
|
|
@ -6,8 +6,11 @@
|
|||
// RUN: %clang -### %s -mieee-fp -S 2>&1 | FileCheck --check-prefix=IEEE %s
|
||||
// IEEE-NOT: error: unknown argument
|
||||
|
||||
// RUN: %clang -target i386-unknown-unknown -### %s -mskip-rax-setup -S 2>&1 | FileCheck --check-prefix=SRS %s
|
||||
// RUN: %clang --target=i386 -### %s -mskip-rax-setup -S 2>&1 | FileCheck --check-prefix=SRS %s
|
||||
// SRS: "-mskip-rax-setup"
|
||||
|
||||
// RUN: %clang -target i386-unknown-unknown -### %s -mno-skip-rax-setup -S 2>&1 | FileCheck --check-prefix=NO-SRS %s
|
||||
// RUN: %clang --target=i386 -### %s -mno-skip-rax-setup -S 2>&1 | FileCheck --check-prefix=NO-SRS %s
|
||||
// NO-SRS-NOT: "-mskip-rax-setup"
|
||||
|
||||
// RUN: %clang --target=i386 -### %s -mindirect-branch-cs-prefix -S 2>&1 | FileCheck --check-prefix=IND-CS %s
|
||||
// IND-CS: "-mindirect-branch-cs-prefix"
|
||||
|
|
|
@ -2440,6 +2440,9 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
|
|||
if (OutStreamer->isVerboseAsm())
|
||||
addConstantComments(MI, *OutStreamer);
|
||||
|
||||
bool IndCS =
|
||||
MF->getMMI().getModule()->getModuleFlag("indirect_branch_cs_prefix");
|
||||
|
||||
switch (MI->getOpcode()) {
|
||||
case TargetOpcode::DBG_VALUE:
|
||||
llvm_unreachable("Should be handled target independently");
|
||||
|
@ -2488,13 +2491,16 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
|
|||
break;
|
||||
}
|
||||
|
||||
case X86::TAILJMPd64:
|
||||
if (IndCS && MI->hasRegisterImplicitUseOperand(X86::R11))
|
||||
EmitAndCountInstruction(MCInstBuilder(X86::CS_PREFIX));
|
||||
LLVM_FALLTHROUGH;
|
||||
case X86::TAILJMPr:
|
||||
case X86::TAILJMPm:
|
||||
case X86::TAILJMPd:
|
||||
case X86::TAILJMPd_CC:
|
||||
case X86::TAILJMPr64:
|
||||
case X86::TAILJMPm64:
|
||||
case X86::TAILJMPd64:
|
||||
case X86::TAILJMPd64_CC:
|
||||
case X86::TAILJMPr64_REX:
|
||||
case X86::TAILJMPm64_REX:
|
||||
|
@ -2668,6 +2674,10 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
|
|||
.addImm(MI->getOperand(0).getImm())
|
||||
.addReg(X86::NoRegister));
|
||||
return;
|
||||
case X86::CALL64pcrel32:
|
||||
if (IndCS && MI->hasRegisterImplicitUseOperand(X86::R11))
|
||||
EmitAndCountInstruction(MCInstBuilder(X86::CS_PREFIX));
|
||||
break;
|
||||
}
|
||||
|
||||
MCInst TmpInst;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
|
@ -73,9 +74,14 @@ bool X86ReturnThunks::runOnMachineFunction(MachineFunction &MF) {
|
|||
if (Term.getOpcode() == RetOpc)
|
||||
Rets.push_back(&Term);
|
||||
|
||||
bool IndCS =
|
||||
MF.getMMI().getModule()->getModuleFlag("indirect_branch_cs_prefix");
|
||||
const MCInstrDesc &CS = ST.getInstrInfo()->get(X86::CS_PREFIX);
|
||||
const MCInstrDesc &JMP = ST.getInstrInfo()->get(X86::TAILJMPd);
|
||||
|
||||
for (MachineInstr *Ret : Rets) {
|
||||
if (IndCS)
|
||||
BuildMI(Ret->getParent(), Ret->getDebugLoc(), CS);
|
||||
BuildMI(Ret->getParent(), Ret->getDebugLoc(), JMP)
|
||||
.addExternalSymbol(ThunkName.data());
|
||||
Ret->eraseFromParent();
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
define void @x() fn_ret_thunk_extern {
|
||||
; CHECK-LABEL: x:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: cs
|
||||
; CHECK-NEXT: jmp __x86_return_thunk
|
||||
ret void
|
||||
}
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
|
||||
!0 = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
|
||||
|
|
|
@ -22,18 +22,22 @@ entry:
|
|||
; X64: callq bar
|
||||
; X64-DAG: movl %[[x]], %edi
|
||||
; X64-DAG: movq %[[fp]], %r11
|
||||
; X64: callq __llvm_lvi_thunk_r11
|
||||
; X64: cs
|
||||
; X64-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64: movl %[[x]], %edi
|
||||
; X64: callq bar
|
||||
; X64-DAG: movl %[[x]], %edi
|
||||
; X64-DAG: movq %[[fp]], %r11
|
||||
; X64: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64: cs
|
||||
; X64-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
|
||||
; X64FAST-LABEL: icall_reg:
|
||||
; X64FAST: callq bar
|
||||
; X64FAST: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: callq bar
|
||||
; X64FAST: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
|
||||
|
||||
@global_fp = external dso_local global ptr
|
||||
|
@ -50,16 +54,20 @@ define void @icall_global_fp(i32 %x, ptr %fpp) #0 {
|
|||
; X64-LABEL: icall_global_fp:
|
||||
; X64-DAG: movl %edi, %[[x:[^ ]*]]
|
||||
; X64-DAG: movq global_fp(%rip), %r11
|
||||
; X64: callq __llvm_lvi_thunk_r11
|
||||
; X64: cs
|
||||
; X64-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64-DAG: movl %[[x]], %edi
|
||||
; X64-DAG: movq global_fp(%rip), %r11
|
||||
; X64: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64: cs
|
||||
; X64-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
|
||||
; X64FAST-LABEL: icall_global_fp:
|
||||
; X64FAST: movq global_fp(%rip), %r11
|
||||
; X64FAST: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: movq global_fp(%rip), %r11
|
||||
; X64FAST: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
|
||||
|
||||
%struct.Foo = type { ptr }
|
||||
|
@ -79,14 +87,18 @@ define void @vcall(ptr %obj) #0 {
|
|||
; X64: movq (%rdi), %[[vptr:[^ ]*]]
|
||||
; X64: movq 8(%[[vptr]]), %[[fp:[^ ]*]]
|
||||
; X64: movq %[[fp]], %r11
|
||||
; X64: callq __llvm_lvi_thunk_r11
|
||||
; X64: cs
|
||||
; X64-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64-DAG: movq %[[obj]], %rdi
|
||||
; X64-DAG: movq %[[fp]], %r11
|
||||
; X64: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64: cs
|
||||
; X64-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
|
||||
; X64FAST-LABEL: vcall:
|
||||
; X64FAST: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
|
||||
|
||||
declare dso_local void @direct_callee()
|
||||
|
@ -113,14 +125,18 @@ define void @nonlazybind_caller() #0 {
|
|||
; X64-LABEL: nonlazybind_caller:
|
||||
; X64: movq nonlazybind_callee@GOTPCREL(%rip), %[[REG:.*]]
|
||||
; X64: movq %[[REG]], %r11
|
||||
; X64: callq __llvm_lvi_thunk_r11
|
||||
; X64: cs
|
||||
; X64-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64: movq %[[REG]], %r11
|
||||
; X64: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64: cs
|
||||
; X64-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64FAST-LABEL: nonlazybind_caller:
|
||||
; X64FAST: movq nonlazybind_callee@GOTPCREL(%rip), %r11
|
||||
; X64FAST: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: callq __llvm_lvi_thunk_r11
|
||||
; X64FAST: movq nonlazybind_callee@GOTPCREL(%rip), %r11
|
||||
; X64FAST: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
; X64FAST: cs
|
||||
; X64FAST-NEXT: jmp __llvm_lvi_thunk_r11 # TAILCALL
|
||||
|
||||
|
||||
; Check that a switch gets lowered using a jump table
|
||||
|
@ -278,3 +294,7 @@ latch:
|
|||
; X64-NEXT: jmpq *%r11
|
||||
|
||||
attributes #1 = { nonlazybind }
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
|
||||
!0 = !{i32 4, !"indirect_branch_cs_prefix", i32 1}
|
||||
|
|
Loading…
Reference in New Issue