summaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-08-18 08:26:59 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-08-18 08:26:59 +0000
commit5a4cb1eb0c4e2560397c009da45d57bb1ebb6135 (patch)
tree4b0e7bd16ff6d9639594693aca2d6931a71b1dec /lib/CodeGen
parent46faa67da1d7e9450e8fa363f6633e2c68e33ff1 (diff)
Notes
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGException.cpp7
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp261
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp58
-rw-r--r--lib/CodeGen/CGObjCRuntime.h3
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp128
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.h8
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp14
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp33
-rw-r--r--lib/CodeGen/CodeGenFunction.h4
9 files changed, 347 insertions, 169 deletions
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index a2ff102e1ab4..5890b407e767 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -1829,7 +1829,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
- const FunctionDecl *ParentSEHFn = ParentCGF.CurSEHParent;
+ const NamedDecl *ParentSEHFn = ParentCGF.CurSEHParent;
assert(ParentSEHFn && "No CurSEHParent!");
MangleContext &Mangler = CGM.getCXXABI().getMangleContext();
if (IsFilter)
@@ -1972,6 +1972,11 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
return Builder.CreateZExt(&*AI, Int32Ty);
}
+void CodeGenFunction::pushSEHCleanup(CleanupKind Kind,
+ llvm::Function *FinallyFunc) {
+ EHStack.pushCleanup<PerformSEHFinally>(Kind, FinallyFunc);
+}
+
void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 915738b8b301..622c8bfb500f 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();
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index a43885c0f9a2..64a9df2bfc0d 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -15,6 +15,7 @@
#include "CGObjCRuntime.h"
#include "CGCleanup.h"
+#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@@ -22,6 +23,7 @@
#include "clang/AST/StmtObjC.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/CallSite.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -120,6 +122,8 @@ namespace {
const Stmt *Body;
llvm::BasicBlock *Block;
llvm::Constant *TypeInfo;
+ /// Flags used to differentiate cleanups and catchalls in Windows SEH
+ unsigned Flags;
};
struct CallObjCEndCatch final : EHScopeStack::Cleanup {
@@ -148,13 +152,17 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
if (S.getNumCatchStmts())
Cont = CGF.getJumpDestInCurrentScope("eh.cont");
+ bool useFunclets = EHPersonality::get(CGF).usesFuncletPads();
+
CodeGenFunction::FinallyInfo FinallyInfo;
- if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
- FinallyInfo.enter(CGF, Finally->getFinallyBody(),
- beginCatchFn, endCatchFn, exceptionRethrowFn);
+ if (!useFunclets)
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
+ FinallyInfo.enter(CGF, Finally->getFinallyBody(),
+ beginCatchFn, endCatchFn, exceptionRethrowFn);
SmallVector<CatchHandler, 8> Handlers;
+
// Enter the catch, if there is one.
if (S.getNumCatchStmts()) {
for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
@@ -166,10 +174,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
Handler.Variable = CatchDecl;
Handler.Body = CatchStmt->getCatchBody();
Handler.Block = CGF.createBasicBlock("catch");
+ Handler.Flags = 0;
// @catch(...) always matches.
if (!CatchDecl) {
- Handler.TypeInfo = nullptr; // catch-all
+ auto catchAll = getCatchAllTypeInfo();
+ Handler.TypeInfo = catchAll.RTTI;
+ Handler.Flags = catchAll.Flags;
// Don't consider any other catches.
break;
}
@@ -179,9 +190,31 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
- Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
+ Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block);
}
+ if (useFunclets)
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) {
+ CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+ if (!CGF.CurSEHParent)
+ CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl);
+ // Outline the finally block.
+ const Stmt *FinallyBlock = Finally->getFinallyBody();
+ HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock);
+
+ // Emit the original filter expression, convert to i32, and return.
+ HelperCGF.EmitStmt(FinallyBlock);
+
+ HelperCGF.FinishFunction(FinallyBlock->getLocEnd());
+
+ llvm::Function *FinallyFunc = HelperCGF.CurFn;
+
+
+ // Push a cleanup for __finally blocks.
+ CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc);
+ }
+
+
// Emit the try body.
CGF.EmitStmt(S.getTryBody());
@@ -197,6 +230,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CatchHandler &Handler = Handlers[I];
CGF.EmitBlock(Handler.Block);
+ llvm::CatchPadInst *CPI = nullptr;
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad);
+ if (useFunclets)
+ if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) {
+ CGF.CurrentFuncletPad = CPI;
+ CPI->setOperand(2, CGF.getExceptionSlot().getPointer());
+ }
llvm::Value *RawExn = CGF.getExceptionFromSlot();
// Enter the catch.
@@ -223,6 +263,8 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CGF.EmitAutoVarDecl(*CatchParam);
EmitInitOfCatchParam(CGF, CastExn, CatchParam);
}
+ if (CPI)
+ CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
CGF.ObjCEHValueStack.push_back(Exn);
CGF.EmitStmt(Handler.Body);
@@ -232,13 +274,13 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
cleanups.ForceCleanup();
CGF.EmitBranchThroughCleanup(Cont);
- }
+ }
// Go back to the try-statement fallthrough.
CGF.Builder.restoreIP(SavedIP);
// Pop out of the finally.
- if (S.getFinallyStmt())
+ if (!useFunclets && S.getFinallyStmt())
FinallyInfo.exit(CGF);
if (Cont.isValid())
@@ -277,7 +319,7 @@ namespace {
: SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
+ CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg);
}
};
}
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index ce082a61eb5e..78d5aba4128e 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -17,6 +17,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CGOBJCRUNTIME_H
#include "CGBuilder.h"
#include "CGCall.h"
+#include "CGCleanup.h"
#include "CGValue.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h" // Selector
@@ -141,6 +142,8 @@ public:
/// error to Sema.
virtual llvm::Constant *GetEHType(QualType T) = 0;
+ virtual CatchTypeInfo getCatchAllTypeInfo() { return { nullptr, 0 }; }
+
/// Generate a constant string object.
virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0;
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index fa850155df4f..4454c719864f 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -897,25 +897,6 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
}
-static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
-isDeclareTargetDeclaration(const ValueDecl *VD) {
- for (const Decl *D : VD->redecls()) {
- if (!D->hasAttrs())
- continue;
- if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
- return Attr->getMapType();
- }
- if (const auto *V = dyn_cast<VarDecl>(VD)) {
- if (const VarDecl *TD = V->getTemplateInstantiationPattern())
- return isDeclareTargetDeclaration(TD);
- } else if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
- if (const auto *TD = FD->getTemplateInstantiationPattern())
- return isDeclareTargetDeclaration(TD);
- }
-
- return llvm::None;
-}
-
LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
return CGF.EmitOMPSharedLValue(E);
}
@@ -2417,7 +2398,7 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) {
if (CGM.getLangOpts().OpenMPSimd)
return Address::invalid();
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD);
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
SmallString<64> PtrName;
{
@@ -2639,7 +2620,7 @@ bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
llvm::GlobalVariable *Addr,
bool PerformInit) {
Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD);
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link)
return false;
VD = VD->getDefinition(CGM.getContext());
@@ -6945,7 +6926,7 @@ private:
if (const auto *VD =
dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD))
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
if (*Res == OMPDeclareTargetDeclAttr::MT_Link) {
IsLink = true;
BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
@@ -7436,7 +7417,7 @@ public:
if (!VD)
continue;
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD);
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
continue;
StructRangeInfoTy PartialStruct;
@@ -8066,7 +8047,7 @@ bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
scanForTargetRegionsFunctions(FD->getBody(), CGM.getMangledName(GD));
// Do not to emit function if it is not marked as declare target.
- return !isDeclareTargetDeclaration(FD) &&
+ return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD) &&
AlreadyEmittedTargetFunctions.count(FD->getCanonicalDecl()) == 0;
}
@@ -8093,14 +8074,15 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
// Do not to emit variable if it is not marked as declare target.
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(cast<VarDecl>(GD.getDecl()));
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
+ cast<VarDecl>(GD.getDecl()));
return !Res || *Res == OMPDeclareTargetDeclAttr::MT_Link;
}
void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
llvm::Constant *Addr) {
if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- isDeclareTargetDeclaration(VD)) {
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
StringRef VarName;
CharUnits VarSize;
@@ -8173,7 +8155,7 @@ bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
const FunctionDecl *FD = D->getCanonicalDecl();
// Do not to emit function if it is marked as declare target as it was already
// emitted.
- if (isDeclareTargetDeclaration(D)) {
+ if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
if (D->hasBody() && AlreadyEmittedTargetFunctions.count(FD) == 0) {
if (auto *F = dyn_cast_or_null<llvm::Function>(
CGM.GetGlobalValue(CGM.getMangledName(GD))))
@@ -8782,7 +8764,8 @@ public:
} // namespace
void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) {
+ const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) {
if (!CGF.HaveInsertPoint())
return;
@@ -8805,32 +8788,45 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
} else {
RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
}
+ llvm::APInt Size(/*numBits=*/32, NumIterations.size());
+ QualType ArrayTy =
+ C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
- Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims");
- CGF.EmitNullInitialization(DimsAddr, KmpDimTy);
+ Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
+ CGF.EmitNullInitialization(DimsAddr, ArrayTy);
enum { LowerFD = 0, UpperFD, StrideFD };
// Fill dims with data.
- LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy);
- // dims.upper = num_iterations;
- LValue UpperLVal =
- CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD));
- llvm::Value *NumIterVal = CGF.EmitScalarConversion(
- CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(),
- Int64Ty, D.getNumIterations()->getExprLoc());
- CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
- // dims.stride = 1;
- LValue StrideLVal =
- CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD));
- CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
- StrideLVal);
+ for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
+ LValue DimsLVal =
+ CGF.MakeAddrLValue(CGF.Builder.CreateConstArrayGEP(
+ DimsAddr, I, C.getTypeSizeInChars(KmpDimTy)),
+ KmpDimTy);
+ // dims.upper = num_iterations;
+ LValue UpperLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), UpperFD));
+ llvm::Value *NumIterVal =
+ CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
+ D.getNumIterations()->getType(), Int64Ty,
+ D.getNumIterations()->getExprLoc());
+ CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
+ // dims.stride = 1;
+ LValue StrideLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), StrideFD));
+ CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
+ StrideLVal);
+ }
// Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
// kmp_int32 num_dims, struct kmp_dim * dims);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()),
- getThreadID(CGF, D.getLocStart()),
- llvm::ConstantInt::getSigned(CGM.Int32Ty, 1),
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- DimsAddr.getPointer(), CGM.VoidPtrTy)};
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, D.getLocStart()),
+ getThreadID(CGF, D.getLocStart()),
+ llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder
+ .CreateConstArrayGEP(DimsAddr, 0, C.getTypeSizeInChars(KmpDimTy))
+ .getPointer(),
+ CGM.VoidPtrTy)};
llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init);
CGF.EmitRuntimeCall(RTLFn, Args);
@@ -8845,16 +8841,29 @@ void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
const OMPDependClause *C) {
QualType Int64Ty =
CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
- const Expr *CounterVal = C->getCounterValue();
- assert(CounterVal);
- llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal),
- CounterVal->getType(), Int64Ty,
- CounterVal->getExprLoc());
- Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr");
- CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()),
- getThreadID(CGF, C->getLocStart()),
- CntAddr.getPointer()};
+ llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
+ QualType ArrayTy = CGM.getContext().getConstantArrayType(
+ Int64Ty, Size, ArrayType::Normal, 0);
+ Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
+ for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
+ const Expr *CounterVal = C->getLoopData(I);
+ assert(CounterVal);
+ llvm::Value *CntVal = CGF.EmitScalarConversion(
+ CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
+ CounterVal->getExprLoc());
+ CGF.EmitStoreOfScalar(
+ CntVal,
+ CGF.Builder.CreateConstArrayGEP(
+ CntAddr, I, CGM.getContext().getTypeSizeInChars(Int64Ty)),
+ /*Volatile=*/false, Int64Ty);
+ }
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, C->getLocStart()),
+ getThreadID(CGF, C->getLocStart()),
+ CGF.Builder
+ .CreateConstArrayGEP(CntAddr, 0,
+ CGM.getContext().getTypeSizeInChars(Int64Ty))
+ .getPointer()};
llvm::Value *RTLFn;
if (C->getDependencyKind() == OMPC_DEPEND_source) {
RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
@@ -9169,7 +9178,8 @@ void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
}
void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) {
+ const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) {
llvm_unreachable("Not supported in SIMD-only mode");
}
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 01ff0c20fd66..94731b64ebdb 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -1465,8 +1465,8 @@ public:
/// Emit initialization for doacross loop nesting support.
/// \param D Loop-based construct used in doacross nesting construct.
- virtual void emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D);
+ virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations);
/// Emit code for doacross ordered directive with 'depend' clause.
/// \param C 'depend' clause with 'sink|source' dependency kind.
@@ -2051,8 +2051,8 @@ public:
/// Emit initialization for doacross loop nesting support.
/// \param D Loop-based construct used in doacross nesting construct.
- void emitDoacrossInit(CodeGenFunction &CGF,
- const OMPLoopDirective &D) override;
+ void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
+ ArrayRef<Expr *> NumIterations) override;
/// Emit code for doacross ordered directive with 'depend' clause.
/// \param C 'depend' clause with 'sink|source' dependency kind.
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 036b5371fe0b..2768a8eb1857 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -191,20 +191,10 @@ class CheckVarsEscapingDeclContext final
bool AllEscaped = false;
bool IsForCombinedParallelRegion = false;
- static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
- isDeclareTargetDeclaration(const ValueDecl *VD) {
- for (const Decl *D : VD->redecls()) {
- if (!D->hasAttrs())
- continue;
- if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>())
- return Attr->getMapType();
- }
- return llvm::None;
- }
-
void markAsEscaped(const ValueDecl *VD) {
// Do not globalize declare target variables.
- if (!isa<VarDecl>(VD) || isDeclareTargetDeclaration(VD))
+ if (!isa<VarDecl>(VD) ||
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
return;
VD = cast<ValueDecl>(VD->getCanonicalDecl());
// Variables captured by value must be globalized.
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 0d343f84c71f..03102f04aa9c 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1509,6 +1509,23 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters(
}
++I;
}
+ // Privatize extra loop counters used in loops for ordered(n) clauses.
+ for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
+ if (!C->getNumForLoops())
+ continue;
+ for (unsigned I = S.getCollapsedNumber(),
+ E = C->getLoopNumIterations().size();
+ I < E; ++I) {
+ const auto *DRE = cast<DeclRefExpr>(C->getLoopCunter(I));
+ const auto *VD = cast<VarDecl>(DRE->getDecl());
+ // Override only those variables that are really emitted already.
+ if (LocalDeclMap.count(VD)) {
+ (void)LoopScope.addPrivate(VD, [this, DRE, VD]() {
+ return CreateMemTemp(DRE->getType(), VD->getName());
+ });
+ }
+ }
+ }
}
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
@@ -2244,7 +2261,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
bool Ordered = false;
if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
if (OrderedClause->getNumForLoops())
- RT.emitDoacrossInit(*this, S);
+ RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
else
Ordered = true;
}
@@ -4943,6 +4960,20 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
CGF.EmitVarDecl(*VD);
}
}
+ for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
+ if (!C->getNumForLoops())
+ continue;
+ for (unsigned I = LD->getCollapsedNumber(),
+ E = C->getLoopNumIterations().size();
+ I < E; ++I) {
+ if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
+ cast<DeclRefExpr>(C->getLoopCunter(I))->getDecl())) {
+ // Emit only those that were not explicitly referenced in clauses.
+ if (!CGF.LocalDeclMap.count(VD))
+ CGF.EmitVarDecl(*VD);
+ }
+ }
+ }
}
CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index f9e284232972..878923a85bdf 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -470,7 +470,7 @@ public:
/// potentially set the return value.
bool SawAsmBlock = false;
- const FunctionDecl *CurSEHParent = nullptr;
+ const NamedDecl *CurSEHParent = nullptr;
/// True if the current function is an outlined SEH helper. This can be a
/// finally block or filter expression.
@@ -2878,6 +2878,8 @@ public:
void EnterSEHTryStmt(const SEHTryStmt &S);
void ExitSEHTryStmt(const SEHTryStmt &S);
+ void pushSEHCleanup(CleanupKind kind,
+ llvm::Function *FinallyFunc);
void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter,
const Stmt *OutlinedStmt);