trans: Reimplement unwinding on MSVC
This commit transitions the compiler to using the new exception handling instructions in LLVM for implementing unwinding for MSVC. This affects both 32 and 64-bit MSVC as they're both now using SEH-based strategies. In terms of standard library support, lots more details about how SEH unwinding is implemented can be found in the commits. In terms of trans, this change necessitated a few modifications: * Branches were added to detect when the old landingpad instruction is used or the new cleanuppad instruction is used to `trans::cleanup`. * The return value from `cleanuppad` is not stored in an `alloca` (because it cannot be). * Each block in trans now has an `Option<LandingPad>` instead of `is_lpad: bool` for indicating whether it's in a landing pad or not. The new exception handling intrinsics require that on MSVC each `call` inside of a landing pad is annotated with which landing pad that it's in. This change to the basic block means that whenever a `call` or `invoke` instruction is generated we know whether to annotate it as part of a cleanuppad or not. * Lots of modifications were made to the instruction builders to construct the new instructions as well as pass the tagging information for the call/invoke instructions. * The translation of the `try` intrinsics for MSVC has been overhauled to use the new `catchpad` instruction. The filter function is now also a rustc-generated function instead of a purely libstd-defined function. The libstd definition still exists, it just has a stable ABI across architectures and leaves some of the really weird implementation details to the compiler (e.g. the `localescape` and `localrecover` intrinsics).
This commit is contained in:
parent
d1cace17af
commit
3e9589c0f4
21 changed files with 1126 additions and 420 deletions
|
@ -987,3 +987,181 @@ LLVMRustBuildLandingPad(LLVMBuilderRef Builder,
|
|||
LLVMValueRef F) {
|
||||
return LLVMBuildLandingPad(Builder, Ty, PersFn, NumClauses, Name);
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCleanupPad(LLVMBuilderRef Builder,
|
||||
LLVMValueRef ParentPad,
|
||||
unsigned ArgCnt,
|
||||
LLVMValueRef *LLArgs,
|
||||
const char *Name) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
Value **Args = unwrap(LLArgs);
|
||||
if (ParentPad == NULL) {
|
||||
Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
|
||||
ParentPad = wrap(Constant::getNullValue(Ty));
|
||||
}
|
||||
return wrap(unwrap(Builder)->CreateCleanupPad(unwrap(ParentPad),
|
||||
ArrayRef<Value*>(Args, ArgCnt),
|
||||
Name));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCleanupRet(LLVMBuilderRef Builder,
|
||||
LLVMValueRef CleanupPad,
|
||||
LLVMBasicBlockRef UnwindBB) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
|
||||
return wrap(unwrap(Builder)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCatchPad(LLVMBuilderRef Builder,
|
||||
LLVMValueRef ParentPad,
|
||||
unsigned ArgCnt,
|
||||
LLVMValueRef *LLArgs,
|
||||
const char *Name) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
Value **Args = unwrap(LLArgs);
|
||||
return wrap(unwrap(Builder)->CreateCatchPad(unwrap(ParentPad),
|
||||
ArrayRef<Value*>(Args, ArgCnt),
|
||||
Name));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCatchRet(LLVMBuilderRef Builder,
|
||||
LLVMValueRef Pad,
|
||||
LLVMBasicBlockRef BB) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
return wrap(unwrap(Builder)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
|
||||
unwrap(BB)));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCatchSwitch(LLVMBuilderRef Builder,
|
||||
LLVMValueRef ParentPad,
|
||||
LLVMBasicBlockRef BB,
|
||||
unsigned NumHandlers,
|
||||
const char *Name) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
if (ParentPad == NULL) {
|
||||
Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
|
||||
ParentPad = wrap(Constant::getNullValue(Ty));
|
||||
}
|
||||
return wrap(unwrap(Builder)->CreateCatchSwitch(unwrap(ParentPad),
|
||||
unwrap(BB),
|
||||
NumHandlers,
|
||||
Name));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
|
||||
LLVMBasicBlockRef Handler) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
Value *CatchSwitch = unwrap(CatchSwitchRef);
|
||||
cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
LLVMRustSetPersonalityFn(LLVMBuilderRef B,
|
||||
LLVMValueRef Personality) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
unwrap(B)->GetInsertBlock()
|
||||
->getParent()
|
||||
->setPersonalityFn(cast<Function>(unwrap(Personality)));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
extern "C" OperandBundleDef*
|
||||
LLVMRustBuildOperandBundleDef(const char *Name,
|
||||
LLVMValueRef *Inputs,
|
||||
unsigned NumInputs) {
|
||||
return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
LLVMRustFreeOperandBundleDef(OperandBundleDef* Bundle) {
|
||||
delete Bundle;
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCall(LLVMBuilderRef B,
|
||||
LLVMValueRef Fn,
|
||||
LLVMValueRef *Args,
|
||||
unsigned NumArgs,
|
||||
OperandBundleDef *Bundle,
|
||||
const char *Name) {
|
||||
unsigned len = Bundle ? 1 : 0;
|
||||
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
|
||||
return wrap(unwrap(B)->CreateCall(unwrap(Fn),
|
||||
makeArrayRef(unwrap(Args), NumArgs),
|
||||
Bundles,
|
||||
Name));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildInvoke(LLVMBuilderRef B,
|
||||
LLVMValueRef Fn,
|
||||
LLVMValueRef *Args,
|
||||
unsigned NumArgs,
|
||||
LLVMBasicBlockRef Then,
|
||||
LLVMBasicBlockRef Catch,
|
||||
OperandBundleDef *Bundle,
|
||||
const char *Name) {
|
||||
unsigned len = Bundle ? 1 : 0;
|
||||
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
|
||||
return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
|
||||
makeArrayRef(unwrap(Args), NumArgs),
|
||||
Bundles,
|
||||
Name));
|
||||
}
|
||||
#else
|
||||
extern "C" void*
|
||||
LLVMRustBuildOperandBundleDef(const char *Name,
|
||||
LLVMValueRef *Inputs,
|
||||
unsigned NumInputs) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
LLVMRustFreeOperandBundleDef(void* Bundle) {
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildCall(LLVMBuilderRef B,
|
||||
LLVMValueRef Fn,
|
||||
LLVMValueRef *Args,
|
||||
unsigned NumArgs,
|
||||
void *Bundle,
|
||||
const char *Name) {
|
||||
return LLVMBuildCall(B, Fn, Args, NumArgs, Name);
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustBuildInvoke(LLVMBuilderRef B,
|
||||
LLVMValueRef Fn,
|
||||
LLVMValueRef *Args,
|
||||
unsigned NumArgs,
|
||||
LLVMBasicBlockRef Then,
|
||||
LLVMBasicBlockRef Catch,
|
||||
void *Bundle,
|
||||
const char *Name) {
|
||||
return LLVMBuildInvoke(B, Fn, Args, NumArgs, Then, Catch, Name);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue