forked from OSchip/llvm-project
[WinEH] Update exception pointer registers
Summary: The CLR's personality routine passes these in rdx/edx, not rax/eax. Make getExceptionPointerRegister a virtual method parameterized by personality function to allow making this distinction. Similarly make getExceptionSelectorRegister a virtual method parameterized by personality function, for symmetry. Reviewers: pgavlin, majnemer, rnk Subscribers: jyknight, dsanders, llvm-commits Differential Revision: http://reviews.llvm.org/D14344 llvm-svn: 252383
This commit is contained in:
parent
c22811bbcc
commit
f748c8937e
|
@ -939,15 +939,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If a physical register, this returns the register that receives the
|
/// If a physical register, this returns the register that receives the
|
||||||
/// exception address on entry to a landing pad.
|
/// exception address on entry to an EH pad.
|
||||||
unsigned getExceptionPointerRegister() const {
|
virtual unsigned
|
||||||
return ExceptionPointerRegister;
|
getExceptionPointerRegister(const Constant *PersonalityFn) const {
|
||||||
|
// 0 is guaranteed to be the NoRegister value on all targets
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If a physical register, this returns the register that receives the
|
/// If a physical register, this returns the register that receives the
|
||||||
/// exception typeid on entry to a landing pad.
|
/// exception typeid on entry to a landing pad.
|
||||||
unsigned getExceptionSelectorRegister() const {
|
virtual unsigned
|
||||||
return ExceptionSelectorRegister;
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const {
|
||||||
|
// 0 is guaranteed to be the NoRegister value on all targets
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the target's jmp_buf size in bytes (if never set, the default is
|
/// Returns the target's jmp_buf size in bytes (if never set, the default is
|
||||||
|
@ -1228,18 +1232,6 @@ protected:
|
||||||
StackPointerRegisterToSaveRestore = R;
|
StackPointerRegisterToSaveRestore = R;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If set to a physical register, this sets the register that receives the
|
|
||||||
/// exception address on entry to a landing pad.
|
|
||||||
void setExceptionPointerRegister(unsigned R) {
|
|
||||||
ExceptionPointerRegister = R;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If set to a physical register, this sets the register that receives the
|
|
||||||
/// exception typeid on entry to a landing pad.
|
|
||||||
void setExceptionSelectorRegister(unsigned R) {
|
|
||||||
ExceptionSelectorRegister = R;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tells the code generator not to expand operations into sequences that use
|
/// Tells the code generator not to expand operations into sequences that use
|
||||||
/// the select operations if possible.
|
/// the select operations if possible.
|
||||||
void setSelectIsExpensive(bool isExpensive = true) {
|
void setSelectIsExpensive(bool isExpensive = true) {
|
||||||
|
@ -1856,14 +1848,6 @@ private:
|
||||||
/// llvm.savestack/llvm.restorestack should save and restore.
|
/// llvm.savestack/llvm.restorestack should save and restore.
|
||||||
unsigned StackPointerRegisterToSaveRestore;
|
unsigned StackPointerRegisterToSaveRestore;
|
||||||
|
|
||||||
/// If set to a physical register, this specifies the register that receives
|
|
||||||
/// the exception address on entry to a landing pad.
|
|
||||||
unsigned ExceptionPointerRegister;
|
|
||||||
|
|
||||||
/// If set to a physical register, this specifies the register that receives
|
|
||||||
/// the exception typeid on entry to a landing pad.
|
|
||||||
unsigned ExceptionSelectorRegister;
|
|
||||||
|
|
||||||
/// This indicates the default register class to use for each ValueType the
|
/// This indicates the default register class to use for each ValueType the
|
||||||
/// target supports natively.
|
/// target supports natively.
|
||||||
const TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE];
|
const TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE];
|
||||||
|
|
|
@ -2184,8 +2184,9 @@ void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) {
|
||||||
// If there aren't registers to copy the values into (e.g., during SjLj
|
// If there aren't registers to copy the values into (e.g., during SjLj
|
||||||
// exceptions), then don't bother to create these DAG nodes.
|
// exceptions), then don't bother to create these DAG nodes.
|
||||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
||||||
if (TLI.getExceptionPointerRegister() == 0 &&
|
const Constant *PersonalityFn = FuncInfo.Fn->getPersonalityFn();
|
||||||
TLI.getExceptionSelectorRegister() == 0)
|
if (TLI.getExceptionPointerRegister(PersonalityFn) == 0 &&
|
||||||
|
TLI.getExceptionSelectorRegister(PersonalityFn) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SmallVector<EVT, 2> ValueVTs;
|
SmallVector<EVT, 2> ValueVTs;
|
||||||
|
|
|
@ -938,6 +938,7 @@ static bool hasExceptionPointerOrCodeUser(const CatchPadInst *CPI) {
|
||||||
/// do other setup for EH landing-pad blocks.
|
/// do other setup for EH landing-pad blocks.
|
||||||
bool SelectionDAGISel::PrepareEHLandingPad() {
|
bool SelectionDAGISel::PrepareEHLandingPad() {
|
||||||
MachineBasicBlock *MBB = FuncInfo->MBB;
|
MachineBasicBlock *MBB = FuncInfo->MBB;
|
||||||
|
const Constant *PersonalityFn = FuncInfo->Fn->getPersonalityFn();
|
||||||
const BasicBlock *LLVMBB = MBB->getBasicBlock();
|
const BasicBlock *LLVMBB = MBB->getBasicBlock();
|
||||||
const TargetRegisterClass *PtrRC =
|
const TargetRegisterClass *PtrRC =
|
||||||
TLI->getRegClassFor(TLI->getPointerTy(CurDAG->getDataLayout()));
|
TLI->getRegClassFor(TLI->getPointerTy(CurDAG->getDataLayout()));
|
||||||
|
@ -948,7 +949,7 @@ bool SelectionDAGISel::PrepareEHLandingPad() {
|
||||||
if (hasExceptionPointerOrCodeUser(CPI)) {
|
if (hasExceptionPointerOrCodeUser(CPI)) {
|
||||||
// Get or create the virtual register to hold the pointer or code. Mark
|
// Get or create the virtual register to hold the pointer or code. Mark
|
||||||
// the live in physreg and copy into the vreg.
|
// the live in physreg and copy into the vreg.
|
||||||
MCPhysReg EHPhysReg = TLI->getExceptionPointerRegister();
|
MCPhysReg EHPhysReg = TLI->getExceptionPointerRegister(PersonalityFn);
|
||||||
assert(EHPhysReg && "target lacks exception pointer register");
|
assert(EHPhysReg && "target lacks exception pointer register");
|
||||||
MBB->addLiveIn(EHPhysReg);
|
MBB->addLiveIn(EHPhysReg);
|
||||||
unsigned VReg = FuncInfo->getCatchPadExceptionPointerVReg(CPI, PtrRC);
|
unsigned VReg = FuncInfo->getCatchPadExceptionPointerVReg(CPI, PtrRC);
|
||||||
|
@ -974,11 +975,11 @@ bool SelectionDAGISel::PrepareEHLandingPad() {
|
||||||
.addSym(Label);
|
.addSym(Label);
|
||||||
|
|
||||||
// Mark exception register as live in.
|
// Mark exception register as live in.
|
||||||
if (unsigned Reg = TLI->getExceptionPointerRegister())
|
if (unsigned Reg = TLI->getExceptionPointerRegister(PersonalityFn))
|
||||||
FuncInfo->ExceptionPointerVirtReg = MBB->addLiveIn(Reg, PtrRC);
|
FuncInfo->ExceptionPointerVirtReg = MBB->addLiveIn(Reg, PtrRC);
|
||||||
|
|
||||||
// Mark exception selector register as live in.
|
// Mark exception selector register as live in.
|
||||||
if (unsigned Reg = TLI->getExceptionSelectorRegister())
|
if (unsigned Reg = TLI->getExceptionSelectorRegister(PersonalityFn))
|
||||||
FuncInfo->ExceptionSelectorVirtReg = MBB->addLiveIn(Reg, PtrRC);
|
FuncInfo->ExceptionSelectorVirtReg = MBB->addLiveIn(Reg, PtrRC);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -765,8 +765,6 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) : TM(tm) {
|
||||||
EnableExtLdPromotion = false;
|
EnableExtLdPromotion = false;
|
||||||
HasFloatingPointExceptions = true;
|
HasFloatingPointExceptions = true;
|
||||||
StackPointerRegisterToSaveRestore = 0;
|
StackPointerRegisterToSaveRestore = 0;
|
||||||
ExceptionPointerRegister = 0;
|
|
||||||
ExceptionSelectorRegister = 0;
|
|
||||||
BooleanContents = UndefinedBooleanContent;
|
BooleanContents = UndefinedBooleanContent;
|
||||||
BooleanFloatContents = UndefinedBooleanContent;
|
BooleanFloatContents = UndefinedBooleanContent;
|
||||||
BooleanVectorContents = UndefinedBooleanContent;
|
BooleanVectorContents = UndefinedBooleanContent;
|
||||||
|
|
|
@ -196,11 +196,6 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
|
||||||
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
|
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
|
||||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
|
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
|
||||||
|
|
||||||
// Exception handling.
|
|
||||||
// FIXME: These are guesses. Has this been defined yet?
|
|
||||||
setExceptionPointerRegister(AArch64::X0);
|
|
||||||
setExceptionSelectorRegister(AArch64::X1);
|
|
||||||
|
|
||||||
// Constant pool entries
|
// Constant pool entries
|
||||||
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
|
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H
|
#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H
|
||||||
#define LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H
|
#define LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H
|
||||||
|
|
||||||
|
#include "AArch64.h"
|
||||||
#include "llvm/CodeGen/CallingConvLower.h"
|
#include "llvm/CodeGen/CallingConvLower.h"
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
#include "llvm/IR/CallingConv.h"
|
#include "llvm/IR/CallingConv.h"
|
||||||
|
@ -366,6 +367,22 @@ public:
|
||||||
/// returns the address of that location. Otherwise, returns nullptr.
|
/// returns the address of that location. Otherwise, returns nullptr.
|
||||||
Value *getSafeStackPointerLocation(IRBuilder<> &IRB) const override;
|
Value *getSafeStackPointerLocation(IRBuilder<> &IRB) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override {
|
||||||
|
// FIXME: This is a guess. Has this been defined yet?
|
||||||
|
return AArch64::X0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
|
||||||
|
// FIXME: This is a guess. Has this been defined yet?
|
||||||
|
return AArch64::X1;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isExtFreeImpl(const Instruction *Ext) const override;
|
bool isExtFreeImpl(const Instruction *Ext) const override;
|
||||||
|
|
||||||
|
|
|
@ -813,13 +813,6 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
||||||
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
|
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
|
||||||
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
|
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
|
||||||
|
|
||||||
if (!Subtarget->useSjLjEH()) {
|
|
||||||
// Platforms which do not use SjLj EH may return values in these registers
|
|
||||||
// via the personality function.
|
|
||||||
setExceptionPointerRegister(ARM::R0);
|
|
||||||
setExceptionSelectorRegister(ARM::R1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Subtarget->getTargetTriple().isWindowsItaniumEnvironment())
|
if (Subtarget->getTargetTriple().isWindowsItaniumEnvironment())
|
||||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
|
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
|
||||||
else
|
else
|
||||||
|
@ -12147,3 +12140,17 @@ bool ARMTargetLowering::functionArgumentNeedsConsecutiveRegisters(
|
||||||
bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
|
bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
|
||||||
return IsHA || IsIntArray;
|
return IsHA || IsIntArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned ARMTargetLowering::getExceptionPointerRegister(
|
||||||
|
const Constant *PersonalityFn) const {
|
||||||
|
// Platforms which do not use SjLj EH may return values in these registers
|
||||||
|
// via the personality function.
|
||||||
|
return Subtarget->useSjLjEH() ? ARM::NoRegister : ARM::R0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ARMTargetLowering::getExceptionSelectorRegister(
|
||||||
|
const Constant *PersonalityFn) const {
|
||||||
|
// Platforms which do not use SjLj EH may return values in these registers
|
||||||
|
// via the personality function.
|
||||||
|
return Subtarget->useSjLjEH() ? ARM::NoRegister : ARM::R1;
|
||||||
|
}
|
||||||
|
|
|
@ -423,6 +423,16 @@ namespace llvm {
|
||||||
bool functionArgumentNeedsConsecutiveRegisters(
|
bool functionArgumentNeedsConsecutiveRegisters(
|
||||||
Type *Ty, CallingConv::ID CallConv, bool isVarArg) const override;
|
Type *Ty, CallingConv::ID CallConv, bool isVarArg) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
|
||||||
|
|
||||||
Instruction *makeDMB(IRBuilder<> &Builder, ARM_MB::MemBOpt Domain) const;
|
Instruction *makeDMB(IRBuilder<> &Builder, ARM_MB::MemBOpt Domain) const;
|
||||||
Value *emitLoadLinked(IRBuilder<> &Builder, Value *Addr,
|
Value *emitLoadLinked(IRBuilder<> &Builder, Value *Addr,
|
||||||
AtomicOrdering Ord) const override;
|
AtomicOrdering Ord) const override;
|
||||||
|
|
|
@ -1286,8 +1286,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
||||||
setPrefFunctionAlignment(4);
|
setPrefFunctionAlignment(4);
|
||||||
setMinFunctionAlignment(2);
|
setMinFunctionAlignment(2);
|
||||||
setInsertFencesForAtomic(false);
|
setInsertFencesForAtomic(false);
|
||||||
setExceptionPointerRegister(Hexagon::R0);
|
|
||||||
setExceptionSelectorRegister(Hexagon::R1);
|
|
||||||
setStackPointerRegisterToSaveRestore(HRI.getStackRegister());
|
setStackPointerRegisterToSaveRestore(HRI.getStackRegister());
|
||||||
|
|
||||||
if (EnableHexSDNodeSched)
|
if (EnableHexSDNodeSched)
|
||||||
|
|
|
@ -163,6 +163,20 @@ bool isPositiveHalfWord(SDNode *N);
|
||||||
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI,
|
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||||
MachineBasicBlock *BB) const override;
|
MachineBasicBlock *BB) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return Hexagon::R0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return Hexagon::R1;
|
||||||
|
}
|
||||||
|
|
||||||
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
||||||
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
||||||
EVT getSetCCResultType(const DataLayout &, LLVMContext &C,
|
EVT getSetCCResultType(const DataLayout &, LLVMContext &C,
|
||||||
|
|
|
@ -438,9 +438,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
|
||||||
|
|
||||||
setStackPointerRegisterToSaveRestore(ABI.IsN64() ? Mips::SP_64 : Mips::SP);
|
setStackPointerRegisterToSaveRestore(ABI.IsN64() ? Mips::SP_64 : Mips::SP);
|
||||||
|
|
||||||
setExceptionPointerRegister(ABI.IsN64() ? Mips::A0_64 : Mips::A0);
|
|
||||||
setExceptionSelectorRegister(ABI.IsN64() ? Mips::A1_64 : Mips::A1);
|
|
||||||
|
|
||||||
MaxStoresPerMemcpy = 16;
|
MaxStoresPerMemcpy = 16;
|
||||||
|
|
||||||
isMicroMips = Subtarget.inMicroMipsMode();
|
isMicroMips = Subtarget.inMicroMipsMode();
|
||||||
|
|
|
@ -267,6 +267,20 @@ namespace llvm {
|
||||||
unsigned getRegisterByName(const char* RegName, EVT VT,
|
unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||||
SelectionDAG &DAG) const override;
|
SelectionDAG &DAG) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return ABI.IsN64() ? Mips::A0_64 : Mips::A0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return ABI.IsN64() ? Mips::A1_64 : Mips::A1;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if a cast between SrcAS and DestAS is a noop.
|
/// Returns true if a cast between SrcAS and DestAS is a noop.
|
||||||
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override {
|
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override {
|
||||||
// Mips doesn't have any special address spaces so we just reserve
|
// Mips doesn't have any special address spaces so we just reserve
|
||||||
|
|
|
@ -827,15 +827,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
|
||||||
setLibcallName(RTLIB::SRA_I128, nullptr);
|
setLibcallName(RTLIB::SRA_I128, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPPC64) {
|
setStackPointerRegisterToSaveRestore(isPPC64 ? PPC::X1 : PPC::R1);
|
||||||
setStackPointerRegisterToSaveRestore(PPC::X1);
|
|
||||||
setExceptionPointerRegister(PPC::X3);
|
|
||||||
setExceptionSelectorRegister(PPC::X4);
|
|
||||||
} else {
|
|
||||||
setStackPointerRegisterToSaveRestore(PPC::R1);
|
|
||||||
setExceptionPointerRegister(PPC::R3);
|
|
||||||
setExceptionSelectorRegister(PPC::R4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have target-specific dag combine patterns for the following nodes:
|
// We have target-specific dag combine patterns for the following nodes:
|
||||||
setTargetDAGCombine(ISD::SINT_TO_FP);
|
setTargetDAGCombine(ISD::SINT_TO_FP);
|
||||||
|
@ -11532,6 +11524,16 @@ PPCTargetLowering::getScratchRegisters(CallingConv::ID) const {
|
||||||
return ScratchRegs;
|
return ScratchRegs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned PPCTargetLowering::getExceptionPointerRegister(
|
||||||
|
const Constant *PersonalityFn) const {
|
||||||
|
return Subtarget.isPPC64() ? PPC::X3 : PPC::R3;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned PPCTargetLowering::getExceptionSelectorRegister(
|
||||||
|
const Constant *PersonalityFn) const {
|
||||||
|
return Subtarget.isPPC64() ? PPC::X4 : PPC::R4;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PPCTargetLowering::shouldExpandBuildVectorWithShuffles(
|
PPCTargetLowering::shouldExpandBuildVectorWithShuffles(
|
||||||
EVT VT , unsigned DefinedValues) const {
|
EVT VT , unsigned DefinedValues) const {
|
||||||
|
|
|
@ -655,8 +655,17 @@ namespace llvm {
|
||||||
return Ty->isArrayTy();
|
return Ty->isArrayTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
struct ReuseLoadInfo {
|
struct ReuseLoadInfo {
|
||||||
SDValue Ptr;
|
SDValue Ptr;
|
||||||
SDValue Chain;
|
SDValue Chain;
|
||||||
|
|
|
@ -1674,9 +1674,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM,
|
||||||
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
|
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
|
||||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
|
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
|
||||||
|
|
||||||
setExceptionPointerRegister(SP::I0);
|
|
||||||
setExceptionSelectorRegister(SP::I1);
|
|
||||||
|
|
||||||
setStackPointerRegisterToSaveRestore(SP::O6);
|
setStackPointerRegisterToSaveRestore(SP::O6);
|
||||||
|
|
||||||
setOperationAction(ISD::CTPOP, MVT::i32,
|
setOperationAction(ISD::CTPOP, MVT::i32,
|
||||||
|
|
|
@ -89,6 +89,20 @@ namespace llvm {
|
||||||
return MVT::i32;
|
return MVT::i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return SP::I0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return SP::I1;
|
||||||
|
}
|
||||||
|
|
||||||
/// getSetCCResultType - Return the ISD::SETCC ValueType
|
/// getSetCCResultType - Return the ISD::SETCC ValueType
|
||||||
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
|
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
|
||||||
EVT VT) const override;
|
EVT VT) const override;
|
||||||
|
|
|
@ -114,8 +114,6 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
|
||||||
computeRegisterProperties(Subtarget.getRegisterInfo());
|
computeRegisterProperties(Subtarget.getRegisterInfo());
|
||||||
|
|
||||||
// Set up special registers.
|
// Set up special registers.
|
||||||
setExceptionPointerRegister(SystemZ::R6D);
|
|
||||||
setExceptionSelectorRegister(SystemZ::R7D);
|
|
||||||
setStackPointerRegisterToSaveRestore(SystemZ::R15D);
|
setStackPointerRegisterToSaveRestore(SystemZ::R15D);
|
||||||
|
|
||||||
// TODO: It may be better to default to latency-oriented scheduling, however
|
// TODO: It may be better to default to latency-oriented scheduling, however
|
||||||
|
|
|
@ -409,6 +409,20 @@ public:
|
||||||
return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
|
return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return SystemZ::R6D;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return SystemZ::R7D;
|
||||||
|
}
|
||||||
|
|
||||||
MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
|
MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||||
MachineBasicBlock *BB) const
|
MachineBasicBlock *BB) const
|
||||||
override;
|
override;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
|
#include "llvm/Analysis/LibCallSemantics.h"
|
||||||
#include "llvm/CodeGen/IntrinsicLowering.h"
|
#include "llvm/CodeGen/IntrinsicLowering.h"
|
||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
@ -476,13 +477,6 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
|
||||||
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
|
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Subtarget->isTarget64BitLP64()) {
|
|
||||||
setExceptionPointerRegister(X86::RAX);
|
|
||||||
setExceptionSelectorRegister(X86::RDX);
|
|
||||||
} else {
|
|
||||||
setExceptionPointerRegister(X86::EAX);
|
|
||||||
setExceptionSelectorRegister(X86::EDX);
|
|
||||||
}
|
|
||||||
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
|
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i64, Custom);
|
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i64, Custom);
|
||||||
|
|
||||||
|
@ -17246,6 +17240,21 @@ SDValue X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDValue Op,
|
||||||
return DAG.getIntPtrConstant(2 * RegInfo->getSlotSize(), SDLoc(Op));
|
return DAG.getIntPtrConstant(2 * RegInfo->getSlotSize(), SDLoc(Op));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned X86TargetLowering::getExceptionPointerRegister(
|
||||||
|
const Constant *PersonalityFn) const {
|
||||||
|
if (classifyEHPersonality(PersonalityFn) == EHPersonality::CoreCLR)
|
||||||
|
return Subtarget->isTarget64BitLP64() ? X86::RDX : X86::EDX;
|
||||||
|
|
||||||
|
return Subtarget->isTarget64BitLP64() ? X86::RAX : X86::EAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned X86TargetLowering::getExceptionSelectorRegister(
|
||||||
|
const Constant *PersonalityFn) const {
|
||||||
|
// Funclet personalities don't use selectors (the runtime does the selection).
|
||||||
|
assert(!isFuncletEHPersonality(classifyEHPersonality(PersonalityFn)));
|
||||||
|
return Subtarget->isTarget64BitLP64() ? X86::RDX : X86::EDX;
|
||||||
|
}
|
||||||
|
|
||||||
SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
|
SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
|
||||||
SDValue Chain = Op.getOperand(0);
|
SDValue Chain = Op.getOperand(0);
|
||||||
SDValue Offset = Op.getOperand(1);
|
SDValue Offset = Op.getOperand(1);
|
||||||
|
|
|
@ -889,6 +889,16 @@ namespace llvm {
|
||||||
unsigned getRegisterByName(const char* RegName, EVT VT,
|
unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||||
SelectionDAG &DAG) const override;
|
SelectionDAG &DAG) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
|
||||||
|
|
||||||
/// This method returns a target specific FastISel object,
|
/// This method returns a target specific FastISel object,
|
||||||
/// or null if the target does not support "fast" ISel.
|
/// or null if the target does not support "fast" ISel.
|
||||||
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
|
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
|
|
@ -160,19 +160,19 @@ static void GetSpillList(SmallVectorImpl<StackSlotInfo> &SpillList,
|
||||||
/// As offsets are negative, the largest offsets will be first.
|
/// As offsets are negative, the largest offsets will be first.
|
||||||
static void GetEHSpillList(SmallVectorImpl<StackSlotInfo> &SpillList,
|
static void GetEHSpillList(SmallVectorImpl<StackSlotInfo> &SpillList,
|
||||||
MachineFrameInfo *MFI, XCoreFunctionInfo *XFI,
|
MachineFrameInfo *MFI, XCoreFunctionInfo *XFI,
|
||||||
|
const Constant *PersonalityFn,
|
||||||
const TargetLowering *TL) {
|
const TargetLowering *TL) {
|
||||||
assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots");
|
assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots");
|
||||||
const int* EHSlot = XFI->getEHSpillSlot();
|
const int *EHSlot = XFI->getEHSpillSlot();
|
||||||
SpillList.push_back(StackSlotInfo(EHSlot[0],
|
SpillList.push_back(
|
||||||
MFI->getObjectOffset(EHSlot[0]),
|
StackSlotInfo(EHSlot[0], MFI->getObjectOffset(EHSlot[0]),
|
||||||
TL->getExceptionPointerRegister()));
|
TL->getExceptionPointerRegister(PersonalityFn)));
|
||||||
SpillList.push_back(StackSlotInfo(EHSlot[0],
|
SpillList.push_back(
|
||||||
MFI->getObjectOffset(EHSlot[1]),
|
StackSlotInfo(EHSlot[0], MFI->getObjectOffset(EHSlot[1]),
|
||||||
TL->getExceptionSelectorRegister()));
|
TL->getExceptionSelectorRegister(PersonalityFn)));
|
||||||
std::sort(SpillList.begin(), SpillList.end(), CompareSSIOffset);
|
std::sort(SpillList.begin(), SpillList.end(), CompareSSIOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static MachineMemOperand *
|
static MachineMemOperand *
|
||||||
getFrameIndexMMO(MachineBasicBlock &MBB, int FrameIndex, unsigned flags) {
|
getFrameIndexMMO(MachineBasicBlock &MBB, int FrameIndex, unsigned flags) {
|
||||||
MachineFunction *MF = MBB.getParent();
|
MachineFunction *MF = MBB.getParent();
|
||||||
|
@ -322,8 +322,11 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF,
|
||||||
if (XFI->hasEHSpillSlot()) {
|
if (XFI->hasEHSpillSlot()) {
|
||||||
// The unwinder requires stack slot & CFI offsets for the exception info.
|
// The unwinder requires stack slot & CFI offsets for the exception info.
|
||||||
// We do not save/spill these registers.
|
// We do not save/spill these registers.
|
||||||
SmallVector<StackSlotInfo,2> SpillList;
|
const Function *Fn = MF.getFunction();
|
||||||
GetEHSpillList(SpillList, MFI, XFI,
|
const Constant *PersonalityFn =
|
||||||
|
Fn->hasPersonalityFn() ? Fn->getPersonalityFn() : nullptr;
|
||||||
|
SmallVector<StackSlotInfo, 2> SpillList;
|
||||||
|
GetEHSpillList(SpillList, MFI, XFI, PersonalityFn,
|
||||||
MF.getSubtarget().getTargetLowering());
|
MF.getSubtarget().getTargetLowering());
|
||||||
assert(SpillList.size()==2 && "Unexpected SpillList size");
|
assert(SpillList.size()==2 && "Unexpected SpillList size");
|
||||||
EmitCfiOffset(MBB, MBBI, dl, TII, MMI,
|
EmitCfiOffset(MBB, MBBI, dl, TII, MMI,
|
||||||
|
@ -354,8 +357,12 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
if (RetOpcode == XCore::EH_RETURN) {
|
if (RetOpcode == XCore::EH_RETURN) {
|
||||||
// 'Restore' the exception info the unwinder has placed into the stack
|
// 'Restore' the exception info the unwinder has placed into the stack
|
||||||
// slots.
|
// slots.
|
||||||
SmallVector<StackSlotInfo,2> SpillList;
|
const Function *Fn = MF.getFunction();
|
||||||
GetEHSpillList(SpillList, MFI, XFI, MF.getSubtarget().getTargetLowering());
|
const Constant *PersonalityFn =
|
||||||
|
Fn->hasPersonalityFn() ? Fn->getPersonalityFn() : nullptr;
|
||||||
|
SmallVector<StackSlotInfo, 2> SpillList;
|
||||||
|
GetEHSpillList(SpillList, MFI, XFI, PersonalityFn,
|
||||||
|
MF.getSubtarget().getTargetLowering());
|
||||||
RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList);
|
RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList);
|
||||||
|
|
||||||
// Return to the landing pad.
|
// Return to the landing pad.
|
||||||
|
|
|
@ -151,8 +151,6 @@ XCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM,
|
||||||
|
|
||||||
// Exception handling
|
// Exception handling
|
||||||
setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
|
setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
|
||||||
setExceptionPointerRegister(XCore::R0);
|
|
||||||
setExceptionSelectorRegister(XCore::R1);
|
|
||||||
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
|
setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
|
||||||
|
|
||||||
// Atomic operations
|
// Atomic operations
|
||||||
|
|
|
@ -125,6 +125,20 @@ namespace llvm {
|
||||||
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM,
|
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM,
|
||||||
Type *Ty, unsigned AS) const override;
|
Type *Ty, unsigned AS) const override;
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception address on entry to an EH pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionPointerRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return XCore::R0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a physical register, this returns the register that receives the
|
||||||
|
/// exception typeid on entry to a landing pad.
|
||||||
|
unsigned
|
||||||
|
getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
|
||||||
|
return XCore::R1;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const TargetMachine &TM;
|
const TargetMachine &TM;
|
||||||
const XCoreSubtarget &Subtarget;
|
const XCoreSubtarget &Subtarget;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
declare void @ProcessCLRException()
|
declare void @ProcessCLRException()
|
||||||
declare void @f(i32)
|
declare void @f(i32)
|
||||||
|
declare void @g(i8 addrspace(1)*)
|
||||||
|
declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
|
||||||
|
|
||||||
; Simplified IR for pseudo-C# like the following:
|
; Simplified IR for pseudo-C# like the following:
|
||||||
; void test1() {
|
; void test1() {
|
||||||
|
@ -51,8 +53,13 @@ catch1.pad:
|
||||||
to label %catch1.body unwind label %catch2.pad
|
to label %catch1.body unwind label %catch2.pad
|
||||||
catch1.body:
|
catch1.body:
|
||||||
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
||||||
; ^ establisher frame pointer passed in rcx
|
; ^ establisher frame pointer passed in rcx
|
||||||
; CHECK: .seh_endprologue
|
; CHECK: .seh_endprologue
|
||||||
|
; CHECK: movq %rdx, %rcx
|
||||||
|
; ^ exception pointer passed in rdx
|
||||||
|
; CHECK-NEXT: callq g
|
||||||
|
%exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1)
|
||||||
|
call void @g(i8 addrspace(1)* %exn1)
|
||||||
; CHECK: [[L_before_f3:.+]]:
|
; CHECK: [[L_before_f3:.+]]:
|
||||||
; CHECK-NEXT: movl $3, %ecx
|
; CHECK-NEXT: movl $3, %ecx
|
||||||
; CHECK-NEXT: callq f
|
; CHECK-NEXT: callq f
|
||||||
|
@ -67,8 +74,13 @@ catch2.pad:
|
||||||
to label %catch2.body unwind label %catch.end
|
to label %catch2.body unwind label %catch.end
|
||||||
catch2.body:
|
catch2.body:
|
||||||
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
||||||
; ^ establisher frame pointer passed in rcx
|
; ^ establisher frame pointer passed in rcx
|
||||||
; CHECK: .seh_endprologue
|
; CHECK: .seh_endprologue
|
||||||
|
; CHECK: movq %rdx, %rcx
|
||||||
|
; ^ exception pointer passed in rdx
|
||||||
|
; CHECK-NEXT: callq g
|
||||||
|
%exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2)
|
||||||
|
call void @g(i8 addrspace(1)* %exn2)
|
||||||
; CHECK: [[L_before_f4:.+]]:
|
; CHECK: [[L_before_f4:.+]]:
|
||||||
; CHECK-NEXT: movl $4, %ecx
|
; CHECK-NEXT: movl $4, %ecx
|
||||||
; CHECK-NEXT: callq f
|
; CHECK-NEXT: callq f
|
||||||
|
@ -87,7 +99,7 @@ fault.pad:
|
||||||
; CHECK: .seh_proc [[L_fault:[^ ]+]]
|
; CHECK: .seh_proc [[L_fault:[^ ]+]]
|
||||||
%fault = cleanuppad [i32 undef]
|
%fault = cleanuppad [i32 undef]
|
||||||
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
||||||
; ^ establisher frame pointer passed in rcx
|
; ^ establisher frame pointer passed in rcx
|
||||||
; CHECK: .seh_endprologue
|
; CHECK: .seh_endprologue
|
||||||
; CHECK: [[L_before_f6:.+]]:
|
; CHECK: [[L_before_f6:.+]]:
|
||||||
; CHECK-NEXT: movl $6, %ecx
|
; CHECK-NEXT: movl $6, %ecx
|
||||||
|
@ -110,7 +122,7 @@ finally.pad:
|
||||||
; CHECK: .seh_proc [[L_finally:[^ ]+]]
|
; CHECK: .seh_proc [[L_finally:[^ ]+]]
|
||||||
%finally = cleanuppad []
|
%finally = cleanuppad []
|
||||||
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
; CHECK: leaq {{[0-9]+}}(%rcx), %rbp
|
||||||
; ^ establisher frame pointer passed in rcx
|
; ^ establisher frame pointer passed in rcx
|
||||||
; CHECK: .seh_endprologue
|
; CHECK: .seh_endprologue
|
||||||
; CHECK: [[L_before_f7:.+]]:
|
; CHECK: [[L_before_f7:.+]]:
|
||||||
; CHECK-NEXT: movl $7, %ecx
|
; CHECK-NEXT: movl $7, %ecx
|
||||||
|
|
|
@ -17,7 +17,7 @@ catch.pad:
|
||||||
catch.body:
|
catch.body:
|
||||||
%exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
|
%exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
|
||||||
%cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
|
%cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
|
||||||
; CHECK: movq %rax, %rcx
|
; CHECK: movq %rdx, %rcx
|
||||||
; CHECK-NEXT: callq g
|
; CHECK-NEXT: callq g
|
||||||
call void @g(i32 addrspace(1)* %cast_exn)
|
call void @g(i32 addrspace(1)* %cast_exn)
|
||||||
catchret %catch to label %exit
|
catchret %catch to label %exit
|
||||||
|
|
Loading…
Reference in New Issue