forked from ldc-developers/ldc
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Partially working C++ exception catching.
This adds catch (C++) (..) {..} statements to enable catching C++ exceptions of any type. The std::type_info generated by Clang for that type is added alongside LDC's ClassInfo catch clauses in the EH landing pad, and when _d_eh_personality encounters C++ exceptions it will let a C++ handler query the catches and determine the right selector.
The std::type_info pointers are wrapped inside a D class since there would be no way to discriminate between raw type_info* pointers and ClassInfo, and LLVM allows little LSDA customization so the catch clause can only be one global variable pointer, no additional info allowed.
The remaining issue is that _cxa_begin_catch returns null instead of the exception object, so the example segfaults at e.what().- Loading branch information
Showing
19 changed files
with
346 additions
and
22 deletions.
There are no files selected for viewing
Submodule clang
updated
2 files
| +31 −10 | lib/CodeGen/CGException.cpp | |
| +40 −0 | lib/CodeGen/CGException.h |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // Contributed by Elie Morisse, same license DMD uses | ||
|
|
||
| #include "cpp/cppstatement.h" | ||
|
|
||
| namespace cpp | ||
| { | ||
|
|
||
| Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler) | ||
| : ::Catch(loc, t, id, handler) | ||
| { | ||
| } | ||
|
|
||
| ::Catch *Catch::syntaxCopy() | ||
| { | ||
| Catch *c = new Catch(loc, | ||
| type ? type->syntaxCopy() : NULL, | ||
| ident, | ||
| (handler ? handler->syntaxCopy() : NULL)); | ||
| c->internalCatch = internalCatch; | ||
| return c; | ||
| } | ||
|
|
||
| bool LangPlugin::doesHandleCatch(LINK lang) | ||
| { | ||
| return lang == LINKcpp; | ||
| } | ||
|
|
||
| ::Catch *LangPlugin::createCatch(Loc loc, Type *t, | ||
| Identifier *id, Statement *handler) | ||
| { | ||
| return new Catch(loc, t, id, handler); | ||
| } | ||
|
|
||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // Contributed by Elie Morisse, same license DMD uses | ||
|
|
||
| #ifndef DMD_CPP_CPPSTATEMENT_H | ||
| #define DMD_CPP_CPPSTATEMENT_H | ||
|
|
||
| #ifdef __DMC__ | ||
| #pragma once | ||
| #endif /* __DMC__ */ | ||
|
|
||
| #include "root.h" | ||
| #include "statement.h" | ||
| #include "cpp/calypso.h" | ||
|
|
||
| namespace cpp | ||
| { | ||
| struct IrCatch; | ||
|
|
||
| class Catch : public ::Catch | ||
| { | ||
| public: | ||
| CALYPSO_LANGPLUGIN | ||
|
|
||
| Catch(Loc loc, Type *t, Identifier *id, Statement *handler); | ||
| ::Catch *syntaxCopy() override; | ||
|
|
||
| bool onlyCatchThrowable() override { return false; } | ||
|
|
||
| IrCatch *ir = nullptr; | ||
| }; | ||
|
|
||
| } | ||
|
|
||
| #endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| // Contributed by Elie Morisse, same license DMD uses | ||
| #include "cpp/astunit.h" | ||
| #include "cpp/calypso.h" | ||
| #include "cpp/cppstatement.h" | ||
| #include "cpp/cpptypes.h" | ||
|
|
||
| #include "ir/irfunction.h" | ||
| #include "ir/irtypeclass.h" | ||
| #include "gen/irstate.h" | ||
| #include "gen/llvmhelpers.h" | ||
| #include "gen/rttibuilder.h" | ||
| #include "gen/tollvm.h" | ||
|
|
||
| #include "clang/lib/CodeGen/CGCXXABI.h" | ||
| #include "clang/lib/CodeGen/CGException.h" | ||
| #include "clang/lib/CodeGen/CodeGenFunction.h" | ||
|
|
||
| namespace cpp | ||
| { | ||
|
|
||
| using llvm::cast; | ||
| using llvm::dyn_cast; | ||
| using llvm::isa; | ||
|
|
||
| namespace clangCG = clang::CodeGen; | ||
|
|
||
| struct IrCatch | ||
| { | ||
| clangCG::CodeGenFunction::RunCleanupsScope *CatchScope = nullptr; // may be overkill | ||
| }; | ||
|
|
||
| IrCatch *getIrCatch(cpp::Catch *cj) | ||
| { | ||
| if (!cj->ir) | ||
| cj->ir = new IrCatch; | ||
| return cj->ir; | ||
| } | ||
|
|
||
| void LangPlugin::toBeginCatch(IRState *irs, ::Catch *cj) | ||
| { | ||
| auto c_cj = static_cast<cpp::Catch*>(cj); | ||
| auto irc = getIrCatch(c_cj); | ||
| llvm::Value* ehPtr = irs->func()->getOrCreateEhPtrSlot(); | ||
| ehPtr = irs->ir->CreateLoad(ehPtr); | ||
|
|
||
| updateCGFInsertPoint(); | ||
|
|
||
| // Enter a cleanup scope, including the catch variable and the | ||
| // end-catch. | ||
| irc->CatchScope = new clangCG::CodeGenFunction::RunCleanupsScope(*CGF()); | ||
|
|
||
| // For catches handling a specific type, create storage for it. | ||
| // We will set it in the code that branches from the landing pads | ||
| // (there might be more than one) to catchBB. | ||
| if (cj->var) { | ||
| // // Use the same storage for all exceptions that are not accessed in | ||
| // // nested functions | ||
| // if (!cj->var->nestedrefs.dim) { | ||
| // assert(!isIrLocalCreated(cj->var)); | ||
| // IrLocal* irLocal = getIrLocal(cj->var, true); | ||
| // irLocal->value = DtoBitCast(ehPtr, getPtrToType(llCatchVarType)); | ||
| // } else { | ||
| // This will alloca if we haven't already and take care of nested refs | ||
| DtoDeclarationExp(cj->var); | ||
| IrLocal* irLocal = getIrLocal(cj->var); | ||
|
|
||
| auto CatchParamTy = TypeMapper().toType(cj->loc, cj->var->type, | ||
| irs->func()->decl->scope); | ||
| auto CatchParamAlign = clang::CharUnits(); | ||
|
|
||
| clangCG::InitCatchParam(*CGF(), ehPtr, CatchParamTy, CatchParamAlign, | ||
| nullptr, irLocal->value, clang::SourceLocation()); | ||
| // } | ||
| } | ||
| else | ||
| clangCG::CallBeginCatch(*CGF(), ehPtr, false); | ||
| } | ||
|
|
||
| void LangPlugin::toEndCatch(IRState *irs, ::Catch *cj) | ||
| { | ||
| auto c_cj = static_cast<cpp::Catch*>(cj); | ||
|
|
||
| // Call __cxa_end_catch, fall out through the catch cleanups. | ||
| c_cj->ir->CatchScope->ForceCleanup(); | ||
| delete c_cj->ir->CatchScope; | ||
| } | ||
|
|
||
| llvm::Constant *LangPlugin::toCatchScopeType(IRState *irs, Type *t) | ||
| { | ||
| auto loc = irs->func()->decl->loc; | ||
| auto ThrowType = TypeMapper().toType(loc, t, irs->func()->decl->scope); | ||
|
|
||
| auto TypeInfo = CGM->GetAddrOfRTTIDescriptor(ThrowType, /*ForEH=*/true); | ||
| auto& wrapper = type_infoWrappers[TypeInfo]; | ||
|
|
||
| if (!wrapper) | ||
| { | ||
| if (!type_info_ptr) | ||
| type_info_ptr = ::ClassDeclaration::exception->parent->search( | ||
| loc, Identifier::idPool("__cpp_type_info_ptr"))->isClassDeclaration(); | ||
|
|
||
| assert(type_info_ptr); | ||
|
|
||
| RTTIBuilder b(type_info_ptr); | ||
| b.push(TypeInfo); | ||
|
|
||
| auto initType = cast<llvm::StructType>(static_cast<IrTypeClass*>(type_info_ptr->type->ctype)->getMemoryLLType()); | ||
| auto finalinit = b.get_constant(initType); | ||
|
|
||
| llvm::SmallString<256> InitName("_D"); | ||
| llvm::raw_svector_ostream Out(InitName); | ||
| CGM->getCXXABI().getMangleContext().mangleCXXRTTI(ThrowType, Out); | ||
| Out.flush(); | ||
| InitName.append("7__tiwrap"); | ||
|
|
||
| wrapper = getOrCreateGlobal(irs->func()->decl->loc, | ||
| gIR->module, initType, true, llvm::GlobalValue::ExternalLinkage, NULL, InitName); | ||
| wrapper->setAlignment(DtoAlignment(type_info_ptr->type)); | ||
| wrapper->setInitializer(finalinit); | ||
| wrapper->setLinkage(DtoLinkage(type_info_ptr).first); | ||
| } | ||
|
|
||
| return wrapper; | ||
| } | ||
|
|
||
| } | ||
|
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.