mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	Revert "[WinEH] Add an EH registration and state insertion pass for 32-bit x86"
This reverts commit r236359. Things are still broken despite testing. :( git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236360 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		@@ -37,7 +37,6 @@ enum class EncodingType {
 | 
				
			|||||||
  ARM,     /// Windows NT (Windows on ARM)
 | 
					  ARM,     /// Windows NT (Windows on ARM)
 | 
				
			||||||
  CE,      /// Windows CE ARM, PowerPC, SH3, SH4
 | 
					  CE,      /// Windows CE ARM, PowerPC, SH3, SH4
 | 
				
			||||||
  Itanium, /// Windows x64, Windows Itanium (IA-64)
 | 
					  Itanium, /// Windows x64, Windows Itanium (IA-64)
 | 
				
			||||||
  X86,     /// Windows x86, uses no CFI, just EH tables
 | 
					 | 
				
			||||||
  MIPS = Alpha,
 | 
					  MIPS = Alpha,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -507,13 +506,12 @@ public:
 | 
				
			|||||||
  /// frame information to unwind.
 | 
					  /// frame information to unwind.
 | 
				
			||||||
  bool usesCFIForEH() const {
 | 
					  bool usesCFIForEH() const {
 | 
				
			||||||
    return (ExceptionsType == ExceptionHandling::DwarfCFI ||
 | 
					    return (ExceptionsType == ExceptionHandling::DwarfCFI ||
 | 
				
			||||||
            ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI());
 | 
					            ExceptionsType == ExceptionHandling::ARM ||
 | 
				
			||||||
 | 
					            ExceptionsType == ExceptionHandling::WinEH);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool usesWindowsCFI() const {
 | 
					  bool usesWindowsCFI() const {
 | 
				
			||||||
    return ExceptionsType == ExceptionHandling::WinEH &&
 | 
					    return ExceptionsType == ExceptionHandling::WinEH;
 | 
				
			||||||
           (WinEHEncodingType != WinEH::EncodingType::Invalid &&
 | 
					 | 
				
			||||||
            WinEHEncodingType != WinEH::EncodingType::X86);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool doesDwarfUseRelocationsAcrossSections() const {
 | 
					  bool doesDwarfUseRelocationsAcrossSections() const {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -266,8 +266,6 @@ bool AsmPrinter::doInitialization(Module &M) {
 | 
				
			|||||||
  case ExceptionHandling::WinEH:
 | 
					  case ExceptionHandling::WinEH:
 | 
				
			||||||
    switch (MAI->getWinEHEncodingType()) {
 | 
					    switch (MAI->getWinEHEncodingType()) {
 | 
				
			||||||
    default: llvm_unreachable("unsupported unwinding information encoding");
 | 
					    default: llvm_unreachable("unsupported unwinding information encoding");
 | 
				
			||||||
    case WinEH::EncodingType::Invalid:
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    case WinEH::EncodingType::Itanium:
 | 
					    case WinEH::EncodingType::Itanium:
 | 
				
			||||||
      ES = new Win64Exception(this);
 | 
					      ES = new Win64Exception(this);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,11 +8,9 @@
 | 
				
			|||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// This pass lowers LLVM IR exception handling into something closer to what the
 | 
					// This pass lowers LLVM IR exception handling into something closer to what the
 | 
				
			||||||
// backend wants for functions using a personality function from a runtime
 | 
					// backend wants. It snifs the personality function to see which kind of
 | 
				
			||||||
// provided by MSVC. Functions with other personality functions are left alone
 | 
					// preparation is necessary. If the personality function uses the Itanium LSDA,
 | 
				
			||||||
// and may be prepared by other passes. In particular, all supported MSVC
 | 
					// this pass delegates to the DWARF EH preparation pass.
 | 
				
			||||||
// personality functions require cleanup code to be outlined, and the C++
 | 
					 | 
				
			||||||
// personality requires catch handler code to be outlined.
 | 
					 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,6 +31,7 @@
 | 
				
			|||||||
#include "llvm/IR/Module.h"
 | 
					#include "llvm/IR/Module.h"
 | 
				
			||||||
#include "llvm/IR/PatternMatch.h"
 | 
					#include "llvm/IR/PatternMatch.h"
 | 
				
			||||||
#include "llvm/Pass.h"
 | 
					#include "llvm/Pass.h"
 | 
				
			||||||
 | 
					#include "llvm/Support/CommandLine.h"
 | 
				
			||||||
#include "llvm/Support/Debug.h"
 | 
					#include "llvm/Support/Debug.h"
 | 
				
			||||||
#include "llvm/Support/raw_ostream.h"
 | 
					#include "llvm/Support/raw_ostream.h"
 | 
				
			||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 | 
					#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 | 
				
			||||||
@@ -923,7 +922,7 @@ bool WinEHPrepare::prepareExceptionHandlers(
 | 
				
			|||||||
  if (SEHExceptionCodeSlot) {
 | 
					  if (SEHExceptionCodeSlot) {
 | 
				
			||||||
    if (SEHExceptionCodeSlot->hasNUses(0))
 | 
					    if (SEHExceptionCodeSlot->hasNUses(0))
 | 
				
			||||||
      SEHExceptionCodeSlot->eraseFromParent();
 | 
					      SEHExceptionCodeSlot->eraseFromParent();
 | 
				
			||||||
    else if (isAllocaPromotable(SEHExceptionCodeSlot))
 | 
					    else
 | 
				
			||||||
      PromoteMemToReg(SEHExceptionCodeSlot, *DT);
 | 
					      PromoteMemToReg(SEHExceptionCodeSlot, *DT);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,6 @@ set(sources
 | 
				
			|||||||
  X86TargetTransformInfo.cpp
 | 
					  X86TargetTransformInfo.cpp
 | 
				
			||||||
  X86VZeroUpper.cpp
 | 
					  X86VZeroUpper.cpp
 | 
				
			||||||
  X86FixupLEAs.cpp
 | 
					  X86FixupLEAs.cpp
 | 
				
			||||||
  X86WinEHState.cpp
 | 
					 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if( CMAKE_CL_64 )
 | 
					if( CMAKE_CL_64 )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -132,9 +132,8 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) {
 | 
				
			|||||||
    PrivateLabelPrefix = ".L";
 | 
					    PrivateLabelPrefix = ".L";
 | 
				
			||||||
    PointerSize = 8;
 | 
					    PointerSize = 8;
 | 
				
			||||||
    WinEHEncodingType = WinEH::EncodingType::Itanium;
 | 
					    WinEHEncodingType = WinEH::EncodingType::Itanium;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ExceptionsType = ExceptionHandling::WinEH;
 | 
					    ExceptionsType = ExceptionHandling::WinEH;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  AssemblerDialect = AsmWriterFlavor;
 | 
					  AssemblerDialect = AsmWriterFlavor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,12 +69,6 @@ FunctionPass *createX86FixupLEAs();
 | 
				
			|||||||
/// esp-relative movs with pushes.
 | 
					/// esp-relative movs with pushes.
 | 
				
			||||||
FunctionPass *createX86CallFrameOptimization();
 | 
					FunctionPass *createX86CallFrameOptimization();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// createX86WinEHStatePass - Return an IR pass that inserts EH registration
 | 
					 | 
				
			||||||
/// stack objects and explicit EH state updates. This pass must run after EH
 | 
					 | 
				
			||||||
/// preparation, which does Windows-specific but architecture-neutral
 | 
					 | 
				
			||||||
/// preparation.
 | 
					 | 
				
			||||||
FunctionPass *createX86WinEHStatePass();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // End llvm namespace
 | 
					} // End llvm namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -185,7 +185,6 @@ public:
 | 
				
			|||||||
  void addIRPasses() override;
 | 
					  void addIRPasses() override;
 | 
				
			||||||
  bool addInstSelector() override;
 | 
					  bool addInstSelector() override;
 | 
				
			||||||
  bool addILPOpts() override;
 | 
					  bool addILPOpts() override;
 | 
				
			||||||
  bool addPreISel() override;
 | 
					 | 
				
			||||||
  void addPreRegAlloc() override;
 | 
					  void addPreRegAlloc() override;
 | 
				
			||||||
  void addPostRegAlloc() override;
 | 
					  void addPostRegAlloc() override;
 | 
				
			||||||
  void addPreEmitPass() override;
 | 
					  void addPreEmitPass() override;
 | 
				
			||||||
@@ -221,14 +220,6 @@ bool X86PassConfig::addILPOpts() {
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool X86PassConfig::addPreISel() {
 | 
					 | 
				
			||||||
  // Only add this pass for 32-bit x86.
 | 
					 | 
				
			||||||
  Triple TT(TM->getTargetTriple());
 | 
					 | 
				
			||||||
  if (TT.getArch() == Triple::x86)
 | 
					 | 
				
			||||||
    addPass(createX86WinEHStatePass());
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void X86PassConfig::addPreRegAlloc() {
 | 
					void X86PassConfig::addPreRegAlloc() {
 | 
				
			||||||
  addPass(createX86CallFrameOptimization());
 | 
					  addPass(createX86CallFrameOptimization());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,317 +0,0 @@
 | 
				
			|||||||
//===-- X86WinEHState - Insert EH state updates for win32 exceptions ------===//
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//                     The LLVM Compiler Infrastructure
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This file is distributed under the University of Illinois Open Source
 | 
					 | 
				
			||||||
// License. See LICENSE.TXT for details.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// All functions using an MSVC EH personality use an explicitly updated state
 | 
					 | 
				
			||||||
// number stored in an exception registration stack object. The registration
 | 
					 | 
				
			||||||
// object is linked into a thread-local chain of registrations stored at fs:00.
 | 
					 | 
				
			||||||
// This pass adds the registration object and EH state updates.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "X86.h"
 | 
					 | 
				
			||||||
#include "llvm/Analysis/LibCallSemantics.h"
 | 
					 | 
				
			||||||
#include "llvm/CodeGen/Passes.h"
 | 
					 | 
				
			||||||
#include "llvm/CodeGen/WinEHFuncInfo.h"
 | 
					 | 
				
			||||||
#include "llvm/IR/Dominators.h"
 | 
					 | 
				
			||||||
#include "llvm/IR/Function.h"
 | 
					 | 
				
			||||||
#include "llvm/IR/IRBuilder.h"
 | 
					 | 
				
			||||||
#include "llvm/IR/Instructions.h"
 | 
					 | 
				
			||||||
#include "llvm/IR/IntrinsicInst.h"
 | 
					 | 
				
			||||||
#include "llvm/IR/Module.h"
 | 
					 | 
				
			||||||
#include "llvm/IR/PatternMatch.h"
 | 
					 | 
				
			||||||
#include "llvm/Pass.h"
 | 
					 | 
				
			||||||
#include "llvm/Support/Debug.h"
 | 
					 | 
				
			||||||
#include "llvm/Support/raw_ostream.h"
 | 
					 | 
				
			||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 | 
					 | 
				
			||||||
#include "llvm/Transforms/Utils/Cloning.h"
 | 
					 | 
				
			||||||
#include "llvm/Transforms/Utils/Local.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using namespace llvm;
 | 
					 | 
				
			||||||
using namespace llvm::PatternMatch;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define DEBUG_TYPE "winehstate"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace {
 | 
					 | 
				
			||||||
class WinEHStatePass : public FunctionPass {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  static char ID; // Pass identification, replacement for typeid.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  WinEHStatePass() : FunctionPass(ID) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool runOnFunction(Function &Fn) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool doInitialization(Module &M) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool doFinalization(Module &M) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void getAnalysisUsage(AnalysisUsage &AU) const override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const char *getPassName() const override {
 | 
					 | 
				
			||||||
    return "Windows 32-bit x86 EH state insertion";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
  void emitExceptionRegistrationRecord(Function *F);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void linkExceptionRegistration(IRBuilder<> &Builder, Value *RegNode,
 | 
					 | 
				
			||||||
                                 Value *Handler);
 | 
					 | 
				
			||||||
  void unlinkExceptionRegistration(IRBuilder<> &Builder, Value *RegNode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Module-level type getters.
 | 
					 | 
				
			||||||
  Type *getEHRegistrationType();
 | 
					 | 
				
			||||||
  Type *getSEH3RegistrationType();
 | 
					 | 
				
			||||||
  Type *getSEH4RegistrationType();
 | 
					 | 
				
			||||||
  Type *getCXXEH3RegistrationType();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Per-module data.
 | 
					 | 
				
			||||||
  Module *TheModule = nullptr;
 | 
					 | 
				
			||||||
  StructType *EHRegistrationTy = nullptr;
 | 
					 | 
				
			||||||
  StructType *CXXEH3RegistrationTy = nullptr;
 | 
					 | 
				
			||||||
  StructType *SEH3RegistrationTy = nullptr;
 | 
					 | 
				
			||||||
  StructType *SEH4RegistrationTy = nullptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Per-function state
 | 
					 | 
				
			||||||
  EHPersonality Personality = EHPersonality::Unknown;
 | 
					 | 
				
			||||||
  Function *PersonalityFn = nullptr;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
char WinEHStatePass::ID = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool WinEHStatePass::doInitialization(Module &M) {
 | 
					 | 
				
			||||||
  TheModule = &M;
 | 
					 | 
				
			||||||
  return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool WinEHStatePass::doFinalization(Module &M) {
 | 
					 | 
				
			||||||
  assert(TheModule == &M);
 | 
					 | 
				
			||||||
  TheModule = nullptr;
 | 
					 | 
				
			||||||
  EHRegistrationTy = nullptr;
 | 
					 | 
				
			||||||
  CXXEH3RegistrationTy = nullptr;
 | 
					 | 
				
			||||||
  SEH3RegistrationTy = nullptr;
 | 
					 | 
				
			||||||
  SEH4RegistrationTy = nullptr;
 | 
					 | 
				
			||||||
  return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const {
 | 
					 | 
				
			||||||
  // This pass should only insert a stack allocation, memory accesses, and
 | 
					 | 
				
			||||||
  // framerecovers.
 | 
					 | 
				
			||||||
  AU.setPreservesCFG();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool WinEHStatePass::runOnFunction(Function &F) {
 | 
					 | 
				
			||||||
  // Check the personality. Do nothing if this is not an MSVC personality.
 | 
					 | 
				
			||||||
  LandingPadInst *LP = nullptr;
 | 
					 | 
				
			||||||
  for (BasicBlock &BB : F) {
 | 
					 | 
				
			||||||
    LP = BB.getLandingPadInst();
 | 
					 | 
				
			||||||
    if (LP)
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (!LP)
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  PersonalityFn =
 | 
					 | 
				
			||||||
      dyn_cast<Function>(LP->getPersonalityFn()->stripPointerCasts());
 | 
					 | 
				
			||||||
  if (!PersonalityFn)
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  Personality = classifyEHPersonality(PersonalityFn);
 | 
					 | 
				
			||||||
  if (!isMSVCEHPersonality(Personality))
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  emitExceptionRegistrationRecord(&F);
 | 
					 | 
				
			||||||
  // FIXME: State insertion.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Reset per-function state.
 | 
					 | 
				
			||||||
  PersonalityFn = nullptr;
 | 
					 | 
				
			||||||
  Personality = EHPersonality::Unknown;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Get the common EH registration subobject:
 | 
					 | 
				
			||||||
///   struct EHRegistrationNode {
 | 
					 | 
				
			||||||
///     EHRegistrationNode *Next;
 | 
					 | 
				
			||||||
///     EXCEPTION_DISPOSITION (*Handler)(...);
 | 
					 | 
				
			||||||
///   };
 | 
					 | 
				
			||||||
Type *WinEHStatePass::getEHRegistrationType() {
 | 
					 | 
				
			||||||
  if (EHRegistrationTy)
 | 
					 | 
				
			||||||
    return EHRegistrationTy;
 | 
					 | 
				
			||||||
  LLVMContext &Context = TheModule->getContext();
 | 
					 | 
				
			||||||
  EHRegistrationTy = StructType::create(Context, "EHRegistrationNode");
 | 
					 | 
				
			||||||
  Type *FieldTys[] = {
 | 
					 | 
				
			||||||
      EHRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
 | 
					 | 
				
			||||||
      Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  EHRegistrationTy->setBody(FieldTys, false);
 | 
					 | 
				
			||||||
  return EHRegistrationTy;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// The __CxxFrameHandler3 registration node:
 | 
					 | 
				
			||||||
///   struct CXXExceptionRegistration {
 | 
					 | 
				
			||||||
///     void *SavedESP;
 | 
					 | 
				
			||||||
///     EHRegistrationNode SubRecord;
 | 
					 | 
				
			||||||
///     int32_t TryLevel;
 | 
					 | 
				
			||||||
///   };
 | 
					 | 
				
			||||||
Type *WinEHStatePass::getCXXEH3RegistrationType() {
 | 
					 | 
				
			||||||
  if (CXXEH3RegistrationTy)
 | 
					 | 
				
			||||||
    return CXXEH3RegistrationTy;
 | 
					 | 
				
			||||||
  LLVMContext &Context = TheModule->getContext();
 | 
					 | 
				
			||||||
  Type *FieldTys[] = {
 | 
					 | 
				
			||||||
      Type::getInt8PtrTy(Context), // void *SavedESP
 | 
					 | 
				
			||||||
      getEHRegistrationType(),     // EHRegistrationNode SubRecord
 | 
					 | 
				
			||||||
      Type::getInt32Ty(Context)    // int32_t TryLevel
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  CXXEH3RegistrationTy =
 | 
					 | 
				
			||||||
      StructType::create(FieldTys, "CXXExceptionRegistration");
 | 
					 | 
				
			||||||
  return CXXEH3RegistrationTy;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// The _except_handler3 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 {
 | 
					 | 
				
			||||||
///     void *SavedESP;
 | 
					 | 
				
			||||||
///     _EXCEPTION_POINTERS *ExceptionPointers;
 | 
					 | 
				
			||||||
///     EHRegistrationNode SubRecord;
 | 
					 | 
				
			||||||
///     int32_t EncodedScopeTable;
 | 
					 | 
				
			||||||
///     int32_t TryLevel;
 | 
					 | 
				
			||||||
///   };
 | 
					 | 
				
			||||||
Type *WinEHStatePass::getSEH4RegistrationType() {
 | 
					 | 
				
			||||||
  if (SEH4RegistrationTy)
 | 
					 | 
				
			||||||
    return SEH4RegistrationTy;
 | 
					 | 
				
			||||||
  LLVMContext &Context = TheModule->getContext();
 | 
					 | 
				
			||||||
  Type *FieldTys[] = {
 | 
					 | 
				
			||||||
      Type::getInt8PtrTy(Context), // void *SavedESP
 | 
					 | 
				
			||||||
      Type::getInt8PtrTy(Context), // void *ExceptionPointers
 | 
					 | 
				
			||||||
      getEHRegistrationType(),     // EHRegistrationNode SubRecord
 | 
					 | 
				
			||||||
      Type::getInt32Ty(Context),   // int32_t EncodedScopeTable
 | 
					 | 
				
			||||||
      Type::getInt32Ty(Context)    // int32_t TryLevel
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  SEH4RegistrationTy = StructType::create(FieldTys, "EH4ExceptionRegistration");
 | 
					 | 
				
			||||||
  return SEH4RegistrationTy;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Emit an exception registration record. These are stack allocations with the
 | 
					 | 
				
			||||||
// common subobject of two pointers: the previous registration record (the old
 | 
					 | 
				
			||||||
// fs:00) and the personality function for the current frame. The data before
 | 
					 | 
				
			||||||
// and after that is personality function specific.
 | 
					 | 
				
			||||||
void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
 | 
					 | 
				
			||||||
  assert(Personality == EHPersonality::MSVC_CXX ||
 | 
					 | 
				
			||||||
         Personality == EHPersonality::MSVC_X86SEH);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  StringRef PersonalityName = PersonalityFn->getName();
 | 
					 | 
				
			||||||
  IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
 | 
					 | 
				
			||||||
  Type *Int8PtrType = Builder.getInt8PtrTy();
 | 
					 | 
				
			||||||
  Value *SubRecord = nullptr;
 | 
					 | 
				
			||||||
  if (PersonalityName == "__CxxFrameHandler3") {
 | 
					 | 
				
			||||||
    Type *RegNodeTy = getCXXEH3RegistrationType();
 | 
					 | 
				
			||||||
    Value *RegNode = Builder.CreateAlloca(RegNodeTy);
 | 
					 | 
				
			||||||
    // FIXME: We can skip this in -GS- mode, when we figure that out.
 | 
					 | 
				
			||||||
    // SavedESP = llvm.stacksave()
 | 
					 | 
				
			||||||
    Value *SP = Builder.CreateCall(
 | 
					 | 
				
			||||||
        Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave));
 | 
					 | 
				
			||||||
    Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
 | 
					 | 
				
			||||||
    // TryLevel = -1
 | 
					 | 
				
			||||||
    Builder.CreateStore(Builder.getInt32(-1),
 | 
					 | 
				
			||||||
                        Builder.CreateStructGEP(RegNodeTy, RegNode, 2));
 | 
					 | 
				
			||||||
    // FIXME: 'Personality' is incorrect here. We need to generate a trampoline
 | 
					 | 
				
			||||||
    // that effectively gets the LSDA.
 | 
					 | 
				
			||||||
    SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
 | 
					 | 
				
			||||||
    linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
 | 
					 | 
				
			||||||
  } else if (PersonalityName == "_except_handler3") {
 | 
					 | 
				
			||||||
    Type *RegNodeTy = getSEH3RegistrationType();
 | 
					 | 
				
			||||||
    Value *RegNode = Builder.CreateAlloca(RegNodeTy);
 | 
					 | 
				
			||||||
    // TryLevel = -1
 | 
					 | 
				
			||||||
    Builder.CreateStore(Builder.getInt32(-1),
 | 
					 | 
				
			||||||
                        Builder.CreateStructGEP(RegNodeTy, RegNode, 2));
 | 
					 | 
				
			||||||
    // FIXME: Generalize llvm.eh.sjljl.lsda for this.
 | 
					 | 
				
			||||||
    // ScopeTable = nullptr
 | 
					 | 
				
			||||||
    Builder.CreateStore(Constant::getNullValue(Int8PtrType),
 | 
					 | 
				
			||||||
                        Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
 | 
					 | 
				
			||||||
    SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 0);
 | 
					 | 
				
			||||||
    linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
 | 
					 | 
				
			||||||
  } else if (PersonalityName == "_except_handler4") {
 | 
					 | 
				
			||||||
    Type *RegNodeTy = getSEH4RegistrationType();
 | 
					 | 
				
			||||||
    Value *RegNode = Builder.CreateAlloca(RegNodeTy);
 | 
					 | 
				
			||||||
    // SavedESP = llvm.stacksave()
 | 
					 | 
				
			||||||
    Value *SP = Builder.CreateCall(
 | 
					 | 
				
			||||||
        Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave));
 | 
					 | 
				
			||||||
    Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
 | 
					 | 
				
			||||||
    // TryLevel = -2
 | 
					 | 
				
			||||||
    Builder.CreateStore(Builder.getInt32(-2),
 | 
					 | 
				
			||||||
                        Builder.CreateStructGEP(RegNodeTy, RegNode, 4));
 | 
					 | 
				
			||||||
    // FIXME: Generalize llvm.eh.sjljl.lsda for this, and then do the stack
 | 
					 | 
				
			||||||
    // cookie xor.
 | 
					 | 
				
			||||||
    // ScopeTable = nullptr
 | 
					 | 
				
			||||||
    Builder.CreateStore(Builder.getInt32(0),
 | 
					 | 
				
			||||||
                        Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
 | 
					 | 
				
			||||||
    SubRecord = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
 | 
					 | 
				
			||||||
    linkExceptionRegistration(Builder, SubRecord, PersonalityFn);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    llvm_unreachable("unexpected personality function");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // FIXME: Insert an unlink before all returns.
 | 
					 | 
				
			||||||
  for (BasicBlock &BB : *F) {
 | 
					 | 
				
			||||||
    TerminatorInst *T = BB.getTerminator();
 | 
					 | 
				
			||||||
    if (!isa<ReturnInst>(T))
 | 
					 | 
				
			||||||
      continue;
 | 
					 | 
				
			||||||
    Builder.SetInsertPoint(T);
 | 
					 | 
				
			||||||
    unlinkExceptionRegistration(Builder, SubRecord);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
 | 
					 | 
				
			||||||
                                               Value *RegNode, Value *Handler) {
 | 
					 | 
				
			||||||
  Type *RegNodeTy = getEHRegistrationType();
 | 
					 | 
				
			||||||
  // Handler = Handler
 | 
					 | 
				
			||||||
  Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
 | 
					 | 
				
			||||||
  Builder.CreateStore(Handler, Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
 | 
					 | 
				
			||||||
  // Next = [fs:00]
 | 
					 | 
				
			||||||
  Constant *FSZero =
 | 
					 | 
				
			||||||
      Constant::getNullValue(RegNodeTy->getPointerTo()->getPointerTo(257));
 | 
					 | 
				
			||||||
  Value *Next = Builder.CreateLoad(FSZero);
 | 
					 | 
				
			||||||
  Builder.CreateStore(Next, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
 | 
					 | 
				
			||||||
  // [fs:00] = RegNode
 | 
					 | 
				
			||||||
  Builder.CreateStore(RegNode, FSZero);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder,
 | 
					 | 
				
			||||||
                                                 Value *RegNode) {
 | 
					 | 
				
			||||||
  // Clone RegNode into the current BB for better address mode folding.
 | 
					 | 
				
			||||||
  if (auto *GEP = dyn_cast<GetElementPtrInst>(RegNode)) {
 | 
					 | 
				
			||||||
    GEP = cast<GetElementPtrInst>(GEP->clone());
 | 
					 | 
				
			||||||
    Builder.Insert(GEP);
 | 
					 | 
				
			||||||
    RegNode = GEP;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  Type *RegNodeTy = getEHRegistrationType();
 | 
					 | 
				
			||||||
  // [fs:00] = RegNode->Next
 | 
					 | 
				
			||||||
  Value *Next =
 | 
					 | 
				
			||||||
      Builder.CreateLoad(Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
 | 
					 | 
				
			||||||
  Constant *FSZero =
 | 
					 | 
				
			||||||
      Constant::getNullValue(RegNodeTy->getPointerTo()->getPointerTo(257));
 | 
					 | 
				
			||||||
  Builder.CreateStore(Next, FSZero);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -4,7 +4,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
%frame.reverse = type { %Iter, %Iter }
 | 
					%frame.reverse = type { %Iter, %Iter }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
declare i32 @pers(...)
 | 
					 | 
				
			||||||
declare void @llvm.stackrestore(i8*)
 | 
					declare void @llvm.stackrestore(i8*)
 | 
				
			||||||
declare i8* @llvm.stacksave()
 | 
					declare i8* @llvm.stacksave()
 | 
				
			||||||
declare void @begin(%Iter* sret)
 | 
					declare void @begin(%Iter* sret)
 | 
				
			||||||
@@ -23,7 +22,8 @@ blah:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
; CHECK:  calll   __chkstk
 | 
					; CHECK:  calll   __chkstk
 | 
				
			||||||
; CHECK:  movl %esp, %[[beg:[^ ]*]]
 | 
					; CHECK:  movl %esp, %[[beg:[^ ]*]]
 | 
				
			||||||
; CHECK:  leal 12(%[[beg]]), %[[end:[^ ]*]]
 | 
					; CHECK:  movl %esp, %[[end:[^ ]*]]
 | 
				
			||||||
 | 
					; CHECK:  addl $12, %[[end]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  call void @begin(%Iter* sret %temp.lvalue)
 | 
					  call void @begin(%Iter* sret %temp.lvalue)
 | 
				
			||||||
; CHECK:  calll _begin
 | 
					; CHECK:  calll _begin
 | 
				
			||||||
@@ -49,7 +49,7 @@ invoke.cont5:                                     ; preds = %invoke.cont
 | 
				
			|||||||
  ret i32 0
 | 
					  ret i32 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lpad:                                             ; preds = %invoke.cont, %entry
 | 
					lpad:                                             ; preds = %invoke.cont, %entry
 | 
				
			||||||
  %lp = landingpad { i8*, i32 } personality i32 (...)* @pers
 | 
					  %lp = landingpad { i8*, i32 } personality i8* null
 | 
				
			||||||
          cleanup
 | 
					          cleanup
 | 
				
			||||||
  unreachable
 | 
					  unreachable
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,77 +0,0 @@
 | 
				
			|||||||
; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare void @may_throw_or_crash()
 | 
					 | 
				
			||||||
declare i32 @_except_handler3(...)
 | 
					 | 
				
			||||||
declare i32 @_except_handler4(...)
 | 
					 | 
				
			||||||
declare i32 @__CxxFrameHandler3(...)
 | 
					 | 
				
			||||||
declare void @llvm.eh.begincatch(i8*, i8*)
 | 
					 | 
				
			||||||
declare void @llvm.eh.endcatch()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
define void @use_except_handler3() {
 | 
					 | 
				
			||||||
  invoke void @may_throw_or_crash()
 | 
					 | 
				
			||||||
      to label %cont unwind label %catchall
 | 
					 | 
				
			||||||
cont:
 | 
					 | 
				
			||||||
  ret void
 | 
					 | 
				
			||||||
catchall:
 | 
					 | 
				
			||||||
  landingpad { i8*, i32 } personality i32 (...)* @_except_handler3
 | 
					 | 
				
			||||||
      catch i8* null
 | 
					 | 
				
			||||||
  br label %cont
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
; CHECK-LABEL: _use_except_handler3:
 | 
					 | 
				
			||||||
; CHECK: subl ${{[0-9]+}}, %esp
 | 
					 | 
				
			||||||
; CHECK: movl %fs:0, %[[next:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %[[next]], (%esp)
 | 
					 | 
				
			||||||
; CHECK: leal (%esp), %[[node:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %[[node]], %fs:0
 | 
					 | 
				
			||||||
; CHECK: calll _may_throw_or_crash
 | 
					 | 
				
			||||||
; CHECK: movl (%esp), %[[next:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %[[next]], %fs:0
 | 
					 | 
				
			||||||
; CHECK: retl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
define void @use_except_handler4() {
 | 
					 | 
				
			||||||
  invoke void @may_throw_or_crash()
 | 
					 | 
				
			||||||
      to label %cont unwind label %catchall
 | 
					 | 
				
			||||||
cont:
 | 
					 | 
				
			||||||
  ret void
 | 
					 | 
				
			||||||
catchall:
 | 
					 | 
				
			||||||
  landingpad { i8*, i32 } personality i32 (...)* @_except_handler4
 | 
					 | 
				
			||||||
      catch i8* null
 | 
					 | 
				
			||||||
  br label %cont
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
; CHECK-LABEL: _use_except_handler4:
 | 
					 | 
				
			||||||
; CHECK: subl ${{[0-9]+}}, %esp
 | 
					 | 
				
			||||||
; CHECK: leal 8(%esp), %[[node:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %fs:0, %[[next:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %[[next]], 8(%esp)
 | 
					 | 
				
			||||||
; CHECK: movl %[[node]], %fs:0
 | 
					 | 
				
			||||||
; CHECK: calll _may_throw_or_crash
 | 
					 | 
				
			||||||
; CHECK: movl 8(%esp), %[[next:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %[[next]], %fs:0
 | 
					 | 
				
			||||||
; CHECK: retl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
define void @use_CxxFrameHandler3() {
 | 
					 | 
				
			||||||
  invoke void @may_throw_or_crash()
 | 
					 | 
				
			||||||
      to label %cont unwind label %catchall
 | 
					 | 
				
			||||||
cont:
 | 
					 | 
				
			||||||
  ret void
 | 
					 | 
				
			||||||
catchall:
 | 
					 | 
				
			||||||
  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__CxxFrameHandler3
 | 
					 | 
				
			||||||
      catch i8* null
 | 
					 | 
				
			||||||
  %ehptr = extractvalue { i8*, i32 } %ehvals, 0
 | 
					 | 
				
			||||||
  call void @llvm.eh.begincatch(i8* %ehptr, i8* null)
 | 
					 | 
				
			||||||
  call void @llvm.eh.endcatch()
 | 
					 | 
				
			||||||
  br label %cont
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
; CHECK-LABEL: _use_CxxFrameHandler3:
 | 
					 | 
				
			||||||
; CHECK: subl ${{[0-9]+}}, %esp
 | 
					 | 
				
			||||||
; CHECK: leal 4(%esp), %[[node:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %fs:0, %[[next:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %[[next]], 4(%esp)
 | 
					 | 
				
			||||||
; CHECK: movl %[[node]], %fs:0
 | 
					 | 
				
			||||||
; CHECK: calll _may_throw_or_crash
 | 
					 | 
				
			||||||
; CHECK: movl 4(%esp), %[[next:[^ ,]*]]
 | 
					 | 
				
			||||||
; CHECK: movl %[[next]], %fs:0
 | 
					 | 
				
			||||||
; CHECK: retl
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user