summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM
diff options
context:
space:
mode:
authorAndrew Paverd <andrew.paverd@microsoft.com>2019-10-28 13:22:19 +0000
committerDavid Chisnall <David.Chisnall@microsoft.com>2019-10-28 15:19:39 +0000
commitd157a9bc8ba1085cc4808c6941412322a7fd884e (patch)
treec675a8e26a4bf08d0cd8abcde693780dd5bd3859 /llvm/lib/Target/ARM
parenta233e7d7cb642ada49985426c23aa3c6a4c98690 (diff)
downloadbcm5719-llvm-d157a9bc8ba1085cc4808c6941412322a7fd884e.tar.gz
bcm5719-llvm-d157a9bc8ba1085cc4808c6941412322a7fd884e.zip
Add Windows Control Flow Guard checks (/guard:cf).
Summary: A new function pass (Transforms/CFGuard/CFGuard.cpp) inserts CFGuard checks on indirect function calls, using either the check mechanism (X86, ARM, AArch64) or or the dispatch mechanism (X86-64). The check mechanism requires a new calling convention for the supported targets. The dispatch mechanism adds the target as an operand bundle, which is processed by SelectionDAG. Another pass (CodeGen/CFGuardLongjmp.cpp) identifies and emits valid longjmp targets, as required by /guard:cf. This feature is enabled using the `cfguard` CC1 option. Reviewers: thakis, rnk, theraven, pcc Subscribers: ychen, hans, metalcanine, dmajor, tomrittervg, alex, mehdi_amini, mgorny, javed.absar, kristof.beyls, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D65761
Diffstat (limited to 'llvm/lib/Target/ARM')
-rw-r--r--llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp5
-rw-r--r--llvm/lib/Target/ARM/ARMCallingConv.h3
-rw-r--r--llvm/lib/Target/ARM/ARMCallingConv.td15
-rw-r--r--llvm/lib/Target/ARM/ARMFastISel.cpp2
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp3
-rw-r--r--llvm/lib/Target/ARM/ARMTargetMachine.cpp9
-rw-r--r--llvm/lib/Target/ARM/LLVMBuild.txt2
7 files changed, 37 insertions, 2 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 1eaf871867e..0276ff140ac 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -75,6 +75,8 @@ ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
// GHC set of callee saved regs is empty as all those regs are
// used for passing STG regs around
return CSR_NoRegs_SaveList;
+ } else if (F.getCallingConv() == CallingConv::CFGuard_Check) {
+ return CSR_Win_AAPCS_CFGuard_Check_SaveList;
} else if (F.hasFnAttribute("interrupt")) {
if (STI.isMClass()) {
// M-class CPUs have hardware which saves the registers needed to allow a
@@ -123,7 +125,8 @@ ARMBaseRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
if (CC == CallingConv::GHC)
// This is academic because all GHC calls are (supposed to be) tail calls
return CSR_NoRegs_RegMask;
-
+ if (CC == CallingConv::CFGuard_Check)
+ return CSR_Win_AAPCS_CFGuard_Check_RegMask;
if (STI.getTargetLowering()->supportSwiftError() &&
MF.getFunction().getAttributes().hasAttrSomewhere(Attribute::SwiftError))
return STI.isTargetDarwin() ? CSR_iOS_SwiftError_RegMask
diff --git a/llvm/lib/Target/ARM/ARMCallingConv.h b/llvm/lib/Target/ARM/ARMCallingConv.h
index 615634551d9..7c692f03b44 100644
--- a/llvm/lib/Target/ARM/ARMCallingConv.h
+++ b/llvm/lib/Target/ARM/ARMCallingConv.h
@@ -32,6 +32,9 @@ bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
CCState &State);
+bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT,
+ CCValAssign::LocInfo LocInfo,
+ ISD::ArgFlagsTy ArgFlags, CCState &State);
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
CCState &State);
diff --git a/llvm/lib/Target/ARM/ARMCallingConv.td b/llvm/lib/Target/ARM/ARMCallingConv.td
index 61d2d83ddc4..55111f544ff 100644
--- a/llvm/lib/Target/ARM/ARMCallingConv.td
+++ b/llvm/lib/Target/ARM/ARMCallingConv.td
@@ -246,6 +246,16 @@ def RetCC_ARM_AAPCS_VFP : CallingConv<[
CCDelegateTo<RetCC_ARM_AAPCS_Common>
]>;
+
+// Windows Control Flow Guard checks take a single argument (the target function
+// address) and have no return value.
+let Entry = 1 in
+def CC_ARM_Win32_CFGuard_Check : CallingConv<[
+ CCIfType<[i32], CCAssignToReg<[R0]>>
+]>;
+
+
+
//===----------------------------------------------------------------------===//
// Callee-saved register lists.
//===----------------------------------------------------------------------===//
@@ -256,6 +266,11 @@ def CSR_FPRegs : CalleeSavedRegs<(add (sequence "D%u", 0, 31))>;
def CSR_AAPCS : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7, R6, R5, R4,
(sequence "D%u", 15, 8))>;
+// The Windows Control Flow Guard Check function preserves the same registers as
+// AAPCS, and also preserves all floating point registers.
+def CSR_Win_AAPCS_CFGuard_Check : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7,
+ R6, R5, R4, (sequence "D%u", 15, 0))>;
+
// R8 is used to pass swifterror, remove it from CSR.
def CSR_AAPCS_SwiftError : CalleeSavedRegs<(sub CSR_AAPCS, R8)>;
diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp
index 1fc5ff6921c..6c204bc0ed5 100644
--- a/llvm/lib/Target/ARM/ARMFastISel.cpp
+++ b/llvm/lib/Target/ARM/ARMFastISel.cpp
@@ -1879,6 +1879,8 @@ CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC,
report_fatal_error("Can't return in GHC call convention");
else
return CC_ARM_APCS_GHC;
+ case CallingConv::CFGuard_Check:
+ return (Return ? RetCC_ARM_AAPCS : CC_ARM_Win32_CFGuard_Check);
}
}
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index bb6bca51efd..6e511e68d7a 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1855,6 +1855,7 @@ ARMTargetLowering::getEffectiveCallingConv(CallingConv::ID CC,
case CallingConv::ARM_AAPCS:
case CallingConv::ARM_APCS:
case CallingConv::GHC:
+ case CallingConv::CFGuard_Check:
return CC;
case CallingConv::PreserveMost:
return CallingConv::PreserveMost;
@@ -1914,6 +1915,8 @@ CCAssignFn *ARMTargetLowering::CCAssignFnForNode(CallingConv::ID CC,
return (Return ? RetCC_ARM_APCS : CC_ARM_APCS_GHC);
case CallingConv::PreserveMost:
return (Return ? RetCC_ARM_AAPCS : CC_ARM_AAPCS);
+ case CallingConv::CFGuard_Check:
+ return (Return ? RetCC_ARM_AAPCS : CC_ARM_Win32_CFGuard_Check);
}
}
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index 5c8007f101d..7f85b93beac 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -46,6 +46,7 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/CFGuard.h"
#include "llvm/Transforms/Scalar.h"
#include <cassert>
#include <memory>
@@ -420,6 +421,10 @@ void ARMPassConfig::addIRPasses() {
// Match interleaved memory accesses to ldN/stN intrinsics.
if (TM->getOptLevel() != CodeGenOpt::None)
addPass(createInterleavedAccessPass());
+
+ // Add Control Flow Guard checks.
+ if (TM->getTargetTriple().isOSWindows())
+ addPass(createCFGuardCheckPass());
}
void ARMPassConfig::addCodeGenPrepare() {
@@ -534,4 +539,8 @@ void ARMPassConfig::addPreEmitPass() {
addPass(createARMConstantIslandPass());
addPass(createARMLowOverheadLoopsPass());
+
+ // Identify valid longjmp targets for Windows Control Flow Guard.
+ if (TM->getTargetTriple().isOSWindows())
+ addPass(createCFGuardLongjmpPass());
}
diff --git a/llvm/lib/Target/ARM/LLVMBuild.txt b/llvm/lib/Target/ARM/LLVMBuild.txt
index 7a6b3a8401e..40f8c2c93b0 100644
--- a/llvm/lib/Target/ARM/LLVMBuild.txt
+++ b/llvm/lib/Target/ARM/LLVMBuild.txt
@@ -30,5 +30,5 @@ has_jit = 1
type = Library
name = ARMCodeGen
parent = ARM
-required_libraries = ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target GlobalISel ARMUtils TransformUtils
+required_libraries = ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target GlobalISel ARMUtils TransformUtils CFGuard
add_to_library_groups = ARM
OpenPOWER on IntegriCloud