mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 17:24:48 +00:00
[WinEH] Adjust the 32-bit SEH prologue to better match reality
It turns out that _except_handler3 and _except_handler4 really use the same stack allocation layout, at least today. They just make different choices about encoding the LSDA. This is in preparation for lowering the llvm.eh.exceptioninfo(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238627 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -74,17 +74,15 @@ private:
|
|||||||
int escapeRegNode(Function &F);
|
int escapeRegNode(Function &F);
|
||||||
|
|
||||||
// Module-level type getters.
|
// Module-level type getters.
|
||||||
Type *getEHRegistrationType();
|
Type *getEHLinkRegistrationType();
|
||||||
Type *getSEH3RegistrationType();
|
Type *getSEHRegistrationType();
|
||||||
Type *getSEH4RegistrationType();
|
Type *getCXXEHRegistrationType();
|
||||||
Type *getCXXEH3RegistrationType();
|
|
||||||
|
|
||||||
// Per-module data.
|
// Per-module data.
|
||||||
Module *TheModule = nullptr;
|
Module *TheModule = nullptr;
|
||||||
StructType *EHRegistrationTy = nullptr;
|
StructType *EHLinkRegistrationTy = nullptr;
|
||||||
StructType *CXXEH3RegistrationTy = nullptr;
|
StructType *CXXEHRegistrationTy = nullptr;
|
||||||
StructType *SEH3RegistrationTy = nullptr;
|
StructType *SEHRegistrationTy = nullptr;
|
||||||
StructType *SEH4RegistrationTy = nullptr;
|
|
||||||
|
|
||||||
// Per-function state
|
// Per-function state
|
||||||
EHPersonality Personality = EHPersonality::Unknown;
|
EHPersonality Personality = EHPersonality::Unknown;
|
||||||
@ -117,10 +115,9 @@ bool WinEHStatePass::doInitialization(Module &M) {
|
|||||||
bool WinEHStatePass::doFinalization(Module &M) {
|
bool WinEHStatePass::doFinalization(Module &M) {
|
||||||
assert(TheModule == &M);
|
assert(TheModule == &M);
|
||||||
TheModule = nullptr;
|
TheModule = nullptr;
|
||||||
EHRegistrationTy = nullptr;
|
EHLinkRegistrationTy = nullptr;
|
||||||
CXXEH3RegistrationTy = nullptr;
|
CXXEHRegistrationTy = nullptr;
|
||||||
SEH3RegistrationTy = nullptr;
|
SEHRegistrationTy = nullptr;
|
||||||
SEH4RegistrationTy = nullptr;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,17 +179,17 @@ bool WinEHStatePass::runOnFunction(Function &F) {
|
|||||||
/// EHRegistrationNode *Next;
|
/// EHRegistrationNode *Next;
|
||||||
/// PEXCEPTION_ROUTINE Handler;
|
/// PEXCEPTION_ROUTINE Handler;
|
||||||
/// };
|
/// };
|
||||||
Type *WinEHStatePass::getEHRegistrationType() {
|
Type *WinEHStatePass::getEHLinkRegistrationType() {
|
||||||
if (EHRegistrationTy)
|
if (EHLinkRegistrationTy)
|
||||||
return EHRegistrationTy;
|
return EHLinkRegistrationTy;
|
||||||
LLVMContext &Context = TheModule->getContext();
|
LLVMContext &Context = TheModule->getContext();
|
||||||
EHRegistrationTy = StructType::create(Context, "EHRegistrationNode");
|
EHLinkRegistrationTy = StructType::create(Context, "EHRegistrationNode");
|
||||||
Type *FieldTys[] = {
|
Type *FieldTys[] = {
|
||||||
EHRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
|
EHLinkRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
|
||||||
Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
|
Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
|
||||||
};
|
};
|
||||||
EHRegistrationTy->setBody(FieldTys, false);
|
EHLinkRegistrationTy->setBody(FieldTys, false);
|
||||||
return EHRegistrationTy;
|
return EHLinkRegistrationTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The __CxxFrameHandler3 registration node:
|
/// The __CxxFrameHandler3 registration node:
|
||||||
@ -201,40 +198,21 @@ Type *WinEHStatePass::getEHRegistrationType() {
|
|||||||
/// EHRegistrationNode SubRecord;
|
/// EHRegistrationNode SubRecord;
|
||||||
/// int32_t TryLevel;
|
/// int32_t TryLevel;
|
||||||
/// };
|
/// };
|
||||||
Type *WinEHStatePass::getCXXEH3RegistrationType() {
|
Type *WinEHStatePass::getCXXEHRegistrationType() {
|
||||||
if (CXXEH3RegistrationTy)
|
if (CXXEHRegistrationTy)
|
||||||
return CXXEH3RegistrationTy;
|
return CXXEHRegistrationTy;
|
||||||
LLVMContext &Context = TheModule->getContext();
|
LLVMContext &Context = TheModule->getContext();
|
||||||
Type *FieldTys[] = {
|
Type *FieldTys[] = {
|
||||||
Type::getInt8PtrTy(Context), // void *SavedESP
|
Type::getInt8PtrTy(Context), // void *SavedESP
|
||||||
getEHRegistrationType(), // EHRegistrationNode SubRecord
|
getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
|
||||||
Type::getInt32Ty(Context) // int32_t TryLevel
|
Type::getInt32Ty(Context) // int32_t TryLevel
|
||||||
};
|
};
|
||||||
CXXEH3RegistrationTy =
|
CXXEHRegistrationTy =
|
||||||
StructType::create(FieldTys, "CXXExceptionRegistration");
|
StructType::create(FieldTys, "CXXExceptionRegistration");
|
||||||
return CXXEH3RegistrationTy;
|
return CXXEHRegistrationTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The _except_handler3 registration node:
|
/// The _except_handler3/4 registration node:
|
||||||
/// struct EH3ExceptionRegistration {
|
|
||||||
/// EHRegistrationNode SubRecord;
|
|
||||||
/// void *ScopeTable;
|
|
||||||
/// int32_t TryLevel;
|
|
||||||
/// };
|
|
||||||
Type *WinEHStatePass::getSEH3RegistrationType() {
|
|
||||||
if (SEH3RegistrationTy)
|
|
||||||
return SEH3RegistrationTy;
|
|
||||||
LLVMContext &Context = TheModule->getContext();
|
|
||||||
Type *FieldTys[] = {
|
|
||||||
getEHRegistrationType(), // EHRegistrationNode SubRecord
|
|
||||||
Type::getInt8PtrTy(Context), // void *ScopeTable
|
|
||||||
Type::getInt32Ty(Context) // int32_t TryLevel
|
|
||||||
};
|
|
||||||
SEH3RegistrationTy = StructType::create(FieldTys, "EH3ExceptionRegistration");
|
|
||||||
return SEH3RegistrationTy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The _except_handler4 registration node:
|
|
||||||
/// struct EH4ExceptionRegistration {
|
/// struct EH4ExceptionRegistration {
|
||||||
/// void *SavedESP;
|
/// void *SavedESP;
|
||||||
/// _EXCEPTION_POINTERS *ExceptionPointers;
|
/// _EXCEPTION_POINTERS *ExceptionPointers;
|
||||||
@ -242,19 +220,19 @@ Type *WinEHStatePass::getSEH3RegistrationType() {
|
|||||||
/// int32_t EncodedScopeTable;
|
/// int32_t EncodedScopeTable;
|
||||||
/// int32_t TryLevel;
|
/// int32_t TryLevel;
|
||||||
/// };
|
/// };
|
||||||
Type *WinEHStatePass::getSEH4RegistrationType() {
|
Type *WinEHStatePass::getSEHRegistrationType() {
|
||||||
if (SEH4RegistrationTy)
|
if (SEHRegistrationTy)
|
||||||
return SEH4RegistrationTy;
|
return SEHRegistrationTy;
|
||||||
LLVMContext &Context = TheModule->getContext();
|
LLVMContext &Context = TheModule->getContext();
|
||||||
Type *FieldTys[] = {
|
Type *FieldTys[] = {
|
||||||
Type::getInt8PtrTy(Context), // void *SavedESP
|
Type::getInt8PtrTy(Context), // void *SavedESP
|
||||||
Type::getInt8PtrTy(Context), // void *ExceptionPointers
|
Type::getInt8PtrTy(Context), // void *ExceptionPointers
|
||||||
getEHRegistrationType(), // EHRegistrationNode SubRecord
|
getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
|
||||||
Type::getInt32Ty(Context), // int32_t EncodedScopeTable
|
Type::getInt32Ty(Context), // int32_t EncodedScopeTable
|
||||||
Type::getInt32Ty(Context) // int32_t TryLevel
|
Type::getInt32Ty(Context) // int32_t TryLevel
|
||||||
};
|
};
|
||||||
SEH4RegistrationTy = StructType::create(FieldTys, "EH4ExceptionRegistration");
|
SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration");
|
||||||
return SEH4RegistrationTy;
|
return SEHRegistrationTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit an exception registration record. These are stack allocations with the
|
// Emit an exception registration record. These are stack allocations with the
|
||||||
@ -268,8 +246,8 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
|
|||||||
StringRef PersonalityName = PersonalityFn->getName();
|
StringRef PersonalityName = PersonalityFn->getName();
|
||||||
IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
|
IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
|
||||||
Type *Int8PtrType = Builder.getInt8PtrTy();
|
Type *Int8PtrType = Builder.getInt8PtrTy();
|
||||||
if (PersonalityName == "__CxxFrameHandler3") {
|
if (Personality == EHPersonality::MSVC_CXX) {
|
||||||
RegNodeTy = getCXXEH3RegistrationType();
|
RegNodeTy = getCXXEHRegistrationType();
|
||||||
RegNode = Builder.CreateAlloca(RegNodeTy);
|
RegNode = Builder.CreateAlloca(RegNodeTy);
|
||||||
// FIXME: We can skip this in -GS- mode, when we figure that out.
|
// FIXME: We can skip this in -GS- mode, when we figure that out.
|
||||||
// SavedESP = llvm.stacksave()
|
// SavedESP = llvm.stacksave()
|
||||||
@ -283,33 +261,35 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
|
|||||||
Function *Trampoline = generateLSDAInEAXThunk(F);
|
Function *Trampoline = generateLSDAInEAXThunk(F);
|
||||||
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
|
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
|
||||||
linkExceptionRegistration(Builder, Trampoline);
|
linkExceptionRegistration(Builder, Trampoline);
|
||||||
} else if (PersonalityName == "_except_handler3") {
|
} else if (Personality == EHPersonality::MSVC_X86SEH) {
|
||||||
RegNodeTy = getSEH3RegistrationType();
|
// If _except_handler4 is in use, some additional guard checks and prologue
|
||||||
RegNode = Builder.CreateAlloca(RegNodeTy);
|
// stuff is required.
|
||||||
// TryLevel = -1
|
bool UseStackGuard = (PersonalityName == "_except_handler4");
|
||||||
StateFieldIndex = 2;
|
RegNodeTy = getSEHRegistrationType();
|
||||||
insertStateNumberStore(RegNode, Builder.GetInsertPoint(), -1);
|
|
||||||
// ScopeTable = llvm.x86.seh.lsda(F)
|
|
||||||
Value *LSDA = emitEHLSDA(Builder, F);
|
|
||||||
Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
|
|
||||||
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 0);
|
|
||||||
linkExceptionRegistration(Builder, PersonalityFn);
|
|
||||||
} else if (PersonalityName == "_except_handler4") {
|
|
||||||
RegNodeTy = getSEH4RegistrationType();
|
|
||||||
RegNode = Builder.CreateAlloca(RegNodeTy);
|
RegNode = Builder.CreateAlloca(RegNodeTy);
|
||||||
// SavedESP = llvm.stacksave()
|
// SavedESP = llvm.stacksave()
|
||||||
Value *SP = Builder.CreateCall(
|
Value *SP = Builder.CreateCall(
|
||||||
Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
|
Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
|
||||||
Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
|
Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
|
||||||
// TryLevel = -1
|
// TryLevel = -2 / -1
|
||||||
StateFieldIndex = 4;
|
StateFieldIndex = 4;
|
||||||
insertStateNumberStore(RegNode, Builder.GetInsertPoint(), -1);
|
insertStateNumberStore(RegNode, Builder.GetInsertPoint(),
|
||||||
// FIXME: XOR the LSDA with __security_cookie.
|
UseStackGuard ? -2 : -1);
|
||||||
// ScopeTable = llvm.x86.seh.lsda(F)
|
// ScopeTable = llvm.x86.seh.lsda(F)
|
||||||
Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
|
Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
|
||||||
Value *LSDA = Builder.CreateCall(
|
Value *LSDA = Builder.CreateCall(
|
||||||
Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
|
Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
|
||||||
Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
|
Type *Int32Ty = Type::getInt32Ty(TheModule->getContext());
|
||||||
|
LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
|
||||||
|
// If using _except_handler4, xor the address of the table with
|
||||||
|
// __security_cookie.
|
||||||
|
if (UseStackGuard) {
|
||||||
|
Value *Cookie =
|
||||||
|
TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
|
||||||
|
Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
|
||||||
|
LSDA = Builder.CreateXor(LSDA, Val);
|
||||||
|
}
|
||||||
|
Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
|
||||||
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
|
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
|
||||||
linkExceptionRegistration(Builder, PersonalityFn);
|
linkExceptionRegistration(Builder, PersonalityFn);
|
||||||
} else {
|
} else {
|
||||||
@ -372,7 +352,7 @@ Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
|
|||||||
|
|
||||||
void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
|
void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
|
||||||
Value *Handler) {
|
Value *Handler) {
|
||||||
Type *LinkTy = getEHRegistrationType();
|
Type *LinkTy = getEHLinkRegistrationType();
|
||||||
// Handler = Handler
|
// Handler = Handler
|
||||||
Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
|
Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
|
||||||
Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1));
|
Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1));
|
||||||
@ -392,7 +372,7 @@ void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
|
|||||||
Builder.Insert(GEP);
|
Builder.Insert(GEP);
|
||||||
Link = GEP;
|
Link = GEP;
|
||||||
}
|
}
|
||||||
Type *LinkTy = getEHRegistrationType();
|
Type *LinkTy = getEHLinkRegistrationType();
|
||||||
// [fs:00] = Link->Next
|
// [fs:00] = Link->Next
|
||||||
Value *Next =
|
Value *Next =
|
||||||
Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0));
|
Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0));
|
||||||
|
@ -24,10 +24,10 @@ catchall:
|
|||||||
; CHECK: subl ${{[0-9]+}}, %esp
|
; CHECK: subl ${{[0-9]+}}, %esp
|
||||||
; CHECK: movl $-1, -4(%ebp)
|
; CHECK: movl $-1, -4(%ebp)
|
||||||
; CHECK: movl $L__ehtable$use_except_handler3, -8(%ebp)
|
; CHECK: movl $L__ehtable$use_except_handler3, -8(%ebp)
|
||||||
|
; CHECK: leal -16(%ebp), %[[node:[^ ,]*]]
|
||||||
; CHECK: movl $__except_handler3, -12(%ebp)
|
; CHECK: movl $__except_handler3, -12(%ebp)
|
||||||
; CHECK: movl %fs:0, %[[next:[^ ,]*]]
|
; CHECK: movl %fs:0, %[[next:[^ ,]*]]
|
||||||
; CHECK: movl %[[next]], -16(%ebp)
|
; CHECK: movl %[[next]], -16(%ebp)
|
||||||
; CHECK: leal -16(%ebp), %[[node:[^ ,]*]]
|
|
||||||
; CHECK: movl %[[node]], %fs:0
|
; CHECK: movl %[[node]], %fs:0
|
||||||
; CHECK: calll _may_throw_or_crash
|
; CHECK: calll _may_throw_or_crash
|
||||||
; CHECK: movl -16(%ebp), %[[next:[^ ,]*]]
|
; CHECK: movl -16(%ebp), %[[next:[^ ,]*]]
|
||||||
@ -50,8 +50,10 @@ catchall:
|
|||||||
; CHECK: movl %esp, %ebp
|
; CHECK: movl %esp, %ebp
|
||||||
; CHECK: subl ${{[0-9]+}}, %esp
|
; CHECK: subl ${{[0-9]+}}, %esp
|
||||||
; CHECK: movl %esp, -24(%ebp)
|
; CHECK: movl %esp, -24(%ebp)
|
||||||
; CHECK: movl $-1, -4(%ebp)
|
; CHECK: movl $-2, -4(%ebp)
|
||||||
; CHECK: movl $L__ehtable$use_except_handler4, -20(%ebp)
|
; CHECK: movl $L__ehtable$use_except_handler4, %[[lsda:[^ ,]*]]
|
||||||
|
; CHECK: xorl ___security_cookie, %[[lsda]]
|
||||||
|
; CHECK: movl %[[lsda]], -8(%ebp)
|
||||||
; CHECK: leal -16(%ebp), %[[node:[^ ,]*]]
|
; CHECK: leal -16(%ebp), %[[node:[^ ,]*]]
|
||||||
; CHECK: movl $__except_handler4, -12(%ebp)
|
; CHECK: movl $__except_handler4, -12(%ebp)
|
||||||
; CHECK: movl %fs:0, %[[next:[^ ,]*]]
|
; CHECK: movl %fs:0, %[[next:[^ ,]*]]
|
||||||
|
Reference in New Issue
Block a user