summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGObjCGNU.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp261
1 files changed, 178 insertions, 83 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 915738b8b3019..622c8bfb500f4 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -18,6 +18,7 @@
#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "CGCXXABI.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -178,6 +179,9 @@ protected:
/// runtime provides some LLVM passes that can use this to do things like
/// automatic IMP caching and speculative inlining.
unsigned msgSendMDKind;
+ /// Does the current target use SEH-based exceptions? False implies
+ /// Itanium-style DWARF unwinding.
+ bool usesSEHExceptions;
/// Helper to check if we are targeting a specific runtime version or later.
bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) {
@@ -217,6 +221,7 @@ protected:
llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true,
llvm::GlobalValue::LinkOnceODRLinkage, value, name);
+ GV->setComdat(TheModule.getOrInsertComdat(name));
if (Private)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
ConstStr = GV;
@@ -510,8 +515,8 @@ protected:
/// Returns a selector with the specified type encoding. An empty string is
/// used to return an untyped selector (with the types field set to NULL).
- virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding);
+ virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding);
/// Returns the name of ivar offset variables. In the GNUstep v1 ABI, this
/// contains the class and ivar names, in the v2 ABI this contains the type
@@ -810,8 +815,12 @@ class CGObjCGNUstep : public CGObjCGNU {
// Slot_t objc_slot_lookup_super(struct objc_super*, SEL);
SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
PtrToObjCSuperTy, SelectorTy);
- // If we're in ObjC++ mode, then we want to make
- if (CGM.getLangOpts().CPlusPlus) {
+ // If we're in ObjC++ mode, then we want to make
+ if (usesSEHExceptions) {
+ llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
+ // void objc_exception_rethrow(void)
+ ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
+ } else if (CGM.getLangOpts().CPlusPlus) {
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
// void *__cxa_begin_catch(void *e)
EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
@@ -888,22 +897,25 @@ class CGObjCGNUstep : public CGObjCGNU {
/// This is the ABI that provides a clean break with the legacy GCC ABI and
/// cleans up a number of things that were added to work around 1980s linkers.
class CGObjCGNUstep2 : public CGObjCGNUstep {
- /// The section for selectors.
- static constexpr const char *const SelSection = "__objc_selectors";
- /// The section for classes.
- static constexpr const char *const ClsSection = "__objc_classes";
- /// The section for references to classes.
- static constexpr const char *const ClsRefSection = "__objc_class_refs";
- /// The section for categories.
- static constexpr const char *const CatSection = "__objc_cats";
- /// The section for protocols.
- static constexpr const char *const ProtocolSection = "__objc_protocols";
- /// The section for protocol references.
- static constexpr const char *const ProtocolRefSection = "__objc_protocol_refs";
- /// The section for class aliases
- static constexpr const char *const ClassAliasSection = "__objc_class_aliases";
- /// The section for constexpr constant strings
- static constexpr const char *const ConstantStringSection = "__objc_constant_string";
+ enum SectionKind
+ {
+ SelectorSection = 0,
+ ClassSection,
+ ClassReferenceSection,
+ CategorySection,
+ ProtocolSection,
+ ProtocolReferenceSection,
+ ClassAliasSection,
+ ConstantStringSection
+ };
+ static const char *const SectionsBaseNames[8];
+ template<SectionKind K>
+ std::string sectionName() {
+ std::string name(SectionsBaseNames[K]);
+ if (CGM.getTriple().isOSBinFormatCOFF())
+ name += "$m";
+ return name;
+ }
/// The GCC ABI superclass message lookup function. Takes a pointer to a
/// structure describing the receiver and the class, and a selector as
/// arguments. Returns the IMP for the corresponding method.
@@ -1069,7 +1081,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
isNamed ? StringRef(StringName) : ".objc_string",
Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
: llvm::GlobalValue::PrivateLinkage);
- ObjCStrGV->setSection(ConstantStringSection);
+ ObjCStrGV->setSection(sectionName<ConstantStringSection>());
if (isNamed) {
ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
@@ -1247,9 +1259,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
assert(!TheModule.getGlobalVariable(RefName));
// Emit a reference symbol.
auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
- false, llvm::GlobalValue::ExternalLinkage,
+ false, llvm::GlobalValue::LinkOnceODRLinkage,
llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName);
- GV->setSection(ProtocolRefSection);
+ GV->setComdat(TheModule.getOrInsertComdat(RefName));
+ GV->setSection(sectionName<ProtocolReferenceSection>());
GV->setAlignment(CGM.getPointerAlign().getQuantity());
Ref = GV;
}
@@ -1282,9 +1295,22 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
EmittedProtocol = true;
+ auto SymName = SymbolForProtocol(ProtocolName);
+ auto *OldGV = TheModule.getGlobalVariable(SymName);
+
// Use the protocol definition, if there is one.
if (const ObjCProtocolDecl *Def = PD->getDefinition())
PD = Def;
+ else {
+ // If there is no definition, then create an external linkage symbol and
+ // hope that someone else fills it in for us (and fail to link if they
+ // don't).
+ assert(!OldGV);
+ Protocol = new llvm::GlobalVariable(TheModule, ProtocolTy,
+ /*isConstant*/false,
+ llvm::GlobalValue::ExternalLinkage, nullptr, SymName);
+ return Protocol;
+ }
SmallVector<llvm::Constant*, 16> Protocols;
for (const auto *PI : PD->protocols())
@@ -1301,8 +1327,6 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
EmitProtocolMethodList(PD->class_methods(), ClassMethodList,
OptionalClassMethodList);
- auto SymName = SymbolForProtocol(ProtocolName);
- auto *OldGV = TheModule.getGlobalVariable(SymName);
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
ConstantInitBuilder builder(CGM);
@@ -1326,7 +1350,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
- GV->setSection(ProtocolSection);
+ GV->setSection(sectionName<ProtocolSection>());
GV->setComdat(TheModule.getOrInsertComdat(SymName));
if (OldGV) {
OldGV->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GV,
@@ -1342,8 +1366,8 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
return Val;
return llvm::ConstantExpr::getBitCast(Val, Ty);
}
- llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding) override {
+ llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding) override {
return GetConstantSelector(Sel, TypeEncoding);
}
llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
@@ -1359,6 +1383,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
TypeEncoding);
auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(),
true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName);
+ GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
TypesGlobal = GV;
}
@@ -1387,12 +1412,41 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- GV->setSection(SelSection);
+ GV->setSection(sectionName<SelectorSection>());
auto *SelVal = EnforceType(GV, SelectorTy);
return SelVal;
}
+ llvm::StructType *emptyStruct = nullptr;
+
+ /// Return pointers to the start and end of a section. On ELF platforms, we
+ /// use the __start_ and __stop_ symbols that GNU-compatible linkers will set
+ /// to the start and end of section names, as long as those section names are
+ /// valid identifiers and the symbols are referenced but not defined. On
+ /// Windows, we use the fact that MSVC-compatible linkers will lexically sort
+ /// by subsections and place everything that we want to reference in a middle
+ /// subsection and then insert zero-sized symbols in subsections a and z.
std::pair<llvm::Constant*,llvm::Constant*>
GetSectionBounds(StringRef Section) {
+ if (CGM.getTriple().isOSBinFormatCOFF()) {
+ if (emptyStruct == nullptr) {
+ emptyStruct = llvm::StructType::create(VMContext, ".objc_section_sentinel");
+ emptyStruct->setBody({}, /*isPacked*/true);
+ }
+ auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
+ auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
+ auto *Sym = new llvm::GlobalVariable(TheModule, emptyStruct,
+ /*isConstant*/false,
+ llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
+ Section);
+ Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ Sym->setSection((Section + SecSuffix).str());
+ Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
+ Section).str()));
+ Sym->setAlignment(1);
+ return Sym;
+ };
+ return { Sym("__start_", "$a"), Sym("__stop", "$z") };
+ }
auto *Start = new llvm::GlobalVariable(TheModule, PtrTy,
/*isConstant*/false,
llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") +
@@ -1405,6 +1459,9 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
return { Start, Stop };
}
+ CatchTypeInfo getCatchAllTypeInfo() override {
+ return CGM.getCXXABI().getCatchAllTypeInfo();
+ }
llvm::Function *ModuleInitFunction() override {
llvm::Function *LoadFunction = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
@@ -1420,19 +1477,11 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
ConstantInitBuilder builder(CGM);
auto InitStructBuilder = builder.beginStruct();
InitStructBuilder.addInt(Int64Ty, 0);
- auto addSection = [&](const char *section) {
- auto bounds = GetSectionBounds(section);
+ for (auto *s : SectionsBaseNames) {
+ auto bounds = GetSectionBounds(s);
InitStructBuilder.add(bounds.first);
InitStructBuilder.add(bounds.second);
};
- addSection(SelSection);
- addSection(ClsSection);
- addSection(ClsRefSection);
- addSection(CatSection);
- addSection(ProtocolSection);
- addSection(ProtocolRefSection);
- addSection(ClassAliasSection);
- addSection(ConstantStringSection);
auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init",
CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
@@ -1451,18 +1500,23 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
// Check that this hasn't been renamed. This shouldn't happen, because
// this function should be called precisely once.
assert(InitVar->getName() == ".objc_ctor");
- InitVar->setSection(".ctors");
+ // In Windows, initialisers are sorted by the suffix. XCL is for library
+ // initialisers, which run before user initialisers. We are running
+ // Objective-C loads at the end of library load. This means +load methods
+ // will run before any other static constructors, but that static
+ // constructors can see a fully initialised Objective-C state.
+ if (CGM.getTriple().isOSBinFormatCOFF())
+ InitVar->setSection(".CRT$XCLz");
+ else
+ InitVar->setSection(".ctors");
InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor"));
- CGM.addCompilerUsedGlobal(InitVar);
+ CGM.addUsedGlobal(InitVar);
for (auto *C : Categories) {
auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts());
- Cat->setSection(CatSection);
+ Cat->setSection(sectionName<CategorySection>());
CGM.addUsedGlobal(Cat);
}
- // Add a null value fore each special section so that we can always
- // guarantee that the _start and _stop symbols will exist and be
- // meaningful.
auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init,
StringRef Section) {
auto nullBuilder = builder.beginStruct();
@@ -1476,38 +1530,48 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
CGM.addUsedGlobal(GV);
return GV;
};
- createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr}, SelSection);
- if (Categories.empty())
- createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
- NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr}, CatSection);
- if (!EmittedClass) {
- createNullGlobal(".objc_null_cls_init_ref", NULLPtr, ClsSection);
- createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
- ClsRefSection);
- }
- if (!EmittedProtocol)
- createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
- NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
- NULLPtr}, ProtocolSection);
- if (!EmittedProtocolRef)
- createNullGlobal(".objc_null_protocol_ref", {NULLPtr}, ProtocolRefSection);
- if (!ClassAliases.empty())
- for (auto clsAlias : ClassAliases)
- createNullGlobal(std::string(".objc_class_alias") +
- clsAlias.second, { MakeConstantString(clsAlias.second),
- GetClassVar(clsAlias.first) }, ClassAliasSection);
- else
- createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
- ClassAliasSection);
- if (ConstantStrings.empty()) {
- auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
- createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
- i32Zero, i32Zero, i32Zero, NULLPtr }, ConstantStringSection);
+ for (auto clsAlias : ClassAliases)
+ createNullGlobal(std::string(".objc_class_alias") +
+ clsAlias.second, { MakeConstantString(clsAlias.second),
+ GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
+ // On ELF platforms, add a null value for each special section so that we
+ // can always guarantee that the _start and _stop symbols will exist and be
+ // meaningful. This is not required on COFF platforms, where our start and
+ // stop symbols will create the section.
+ if (!CGM.getTriple().isOSBinFormatCOFF()) {
+ createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr},
+ sectionName<SelectorSection>());
+ if (Categories.empty())
+ createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
+ sectionName<CategorySection>());
+ if (!EmittedClass) {
+ createNullGlobal(".objc_null_cls_init_ref", NULLPtr,
+ sectionName<ClassReferenceSection>());
+ createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
+ sectionName<ClassReferenceSection>());
+ }
+ if (!EmittedProtocol)
+ createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
+ NULLPtr}, sectionName<ProtocolSection>());
+ if (!EmittedProtocolRef)
+ createNullGlobal(".objc_null_protocol_ref", {NULLPtr},
+ sectionName<ProtocolReferenceSection>());
+ if (ClassAliases.empty())
+ createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
+ sectionName<ClassAliasSection>());
+ if (ConstantStrings.empty()) {
+ auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
+ createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
+ i32Zero, i32Zero, i32Zero, NULLPtr },
+ sectionName<ConstantStringSection>());
+ }
}
ConstantStrings.clear();
Categories.clear();
Classes.clear();
- return nullptr;//CGObjCGNU::ModuleInitFunction();
+ return nullptr;
}
/// In the v2 ABI, ivar offset variables use the type encoding in their name
/// to trigger linker failures if the types don't match.
@@ -1774,7 +1838,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
}
auto *classRefSymbol = GetClassVar(className);
- classRefSymbol->setSection(ClsRefSection);
+ classRefSymbol->setSection(sectionName<ClassReferenceSection>());
classRefSymbol->setInitializer(llvm::ConstantExpr::getBitCast(classStruct, IdTy));
@@ -1805,7 +1869,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
auto classInitRef = new llvm::GlobalVariable(TheModule,
classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage,
classStruct, "._OBJC_INIT_CLASS_" + className);
- classInitRef->setSection(ClsSection);
+ classInitRef->setSection(sectionName<ClassSection>());
CGM.addUsedGlobal(classInitRef);
EmittedClass = true;
@@ -1829,6 +1893,18 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
};
+const char *const CGObjCGNUstep2::SectionsBaseNames[8] =
+{
+"__objc_selectors",
+"__objc_classes",
+"__objc_class_refs",
+"__objc_cats",
+"__objc_protocols",
+"__objc_protocol_refs",
+"__objc_class_aliases",
+"__objc_constant_string"
+};
+
/// Support for the ObjFW runtime.
class CGObjCObjFW: public CGObjCGNU {
protected:
@@ -1931,6 +2007,8 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
+ usesSEHExceptions =
+ cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
CodeGenTypes &Types = CGM.getTypes();
IntTy = cast<llvm::IntegerType>(
@@ -2121,8 +2199,8 @@ llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
return Value;
}
-llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding) {
+llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
+ const std::string &TypeEncoding) {
SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
llvm::GlobalAlias *SelValue = nullptr;
@@ -2155,13 +2233,13 @@ Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
- return GetSelector(CGF, Sel, std::string());
+ return GetTypedSelector(CGF, Sel, std::string());
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) {
std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method);
- return GetSelector(CGF, Method->getSelector(), SelTypes);
+ return GetTypedSelector(CGF, Method->getSelector(), SelTypes);
}
llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
@@ -2186,6 +2264,9 @@ llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
}
llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
+ if (usesSEHExceptions)
+ return CGM.getCXXABI().getAddrOfRTTIDescriptor(T);
+
if (!CGM.getLangOpts().CPlusPlus)
return CGObjCGNU::GetEHType(T);
@@ -3726,6 +3807,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
const ObjCAtThrowStmt &S,
bool ClearInsertionPoint) {
llvm::Value *ExceptionAsObject;
+ bool isRethrow = false;
if (const Expr *ThrowExpr = S.getThrowExpr()) {
llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
@@ -3734,11 +3816,24 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
"Unexpected rethrow outside @catch block.");
ExceptionAsObject = CGF.ObjCEHValueStack.back();
+ isRethrow = true;
+ }
+ if (isRethrow && usesSEHExceptions) {
+ // For SEH, ExceptionAsObject may be undef, because the catch handler is
+ // not passed it for catchalls and so it is not visible to the catch
+ // funclet. The real thrown object will still be live on the stack at this
+ // point and will be rethrown. If we are explicitly rethrowing the object
+ // that was passed into the `@catch` block, then this code path is not
+ // reached and we will instead call `objc_exception_throw` with an explicit
+ // argument.
+ CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn).setDoesNotReturn();
+ }
+ else {
+ ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
+ llvm::CallSite Throw =
+ CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
+ Throw.setDoesNotReturn();
}
- ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
- llvm::CallSite Throw =
- CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
- Throw.setDoesNotReturn();
CGF.Builder.CreateUnreachable();
if (ClearInsertionPoint)
CGF.Builder.ClearInsertionPoint();