Vendor import of clang release_70 branch r339999:
https://llvm.org/svn/llvm-project/cfe/branches/release_70@339999
This commit is contained in:
parent
46faa67da1
commit
5a4cb1eb0c
@ -186,6 +186,12 @@ Windows Support
|
||||
Visual Studio's default stdafx.h setup now uses precompiled headers with
|
||||
clang-cl.
|
||||
|
||||
- The alternative entry point names
|
||||
(``wmain``/``WinMain``/``wWinMain``/``DllMain``) now are properly mangled
|
||||
as plain C names in C++ contexts when targeting MinGW, without having to
|
||||
explicit specify ``extern "C"``. (This was already the case for MSVC
|
||||
targets.)
|
||||
|
||||
- ...
|
||||
|
||||
|
||||
|
@ -2718,7 +2718,7 @@ public:
|
||||
/// predicate.
|
||||
void forEachMultiversionedFunctionVersion(
|
||||
const FunctionDecl *FD,
|
||||
llvm::function_ref<void(const FunctionDecl *)> Pred) const;
|
||||
llvm::function_ref<void(FunctionDecl *)> Pred) const;
|
||||
|
||||
const CXXConstructorDecl *
|
||||
getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
|
||||
|
@ -922,8 +922,11 @@ public:
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp for' has 'ordered' clause with
|
||||
/// parameter 2.
|
||||
class OMPOrderedClause : public OMPClause {
|
||||
class OMPOrderedClause final
|
||||
: public OMPClause,
|
||||
private llvm::TrailingObjects<OMPOrderedClause, Expr *> {
|
||||
friend class OMPClauseReader;
|
||||
friend TrailingObjects;
|
||||
|
||||
/// Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
@ -931,6 +934,26 @@ class OMPOrderedClause : public OMPClause {
|
||||
/// Number of for-loops.
|
||||
Stmt *NumForLoops = nullptr;
|
||||
|
||||
/// Real number of loops.
|
||||
unsigned NumberOfLoops = 0;
|
||||
|
||||
/// Build 'ordered' clause.
|
||||
///
|
||||
/// \param Num Expression, possibly associated with this clause.
|
||||
/// \param NumLoops Number of loops, associated with this clause.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPOrderedClause(Expr *Num, unsigned NumLoops, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
NumForLoops(Num), NumberOfLoops(NumLoops) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
explicit OMPOrderedClause(unsigned NumLoops)
|
||||
: OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()),
|
||||
NumberOfLoops(NumLoops) {}
|
||||
|
||||
/// Set the number of associated for-loops.
|
||||
void setNumForLoops(Expr *Num) { NumForLoops = Num; }
|
||||
|
||||
@ -938,17 +961,17 @@ public:
|
||||
/// Build 'ordered' clause.
|
||||
///
|
||||
/// \param Num Expression, possibly associated with this clause.
|
||||
/// \param NumLoops Number of loops, associated with this clause.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPOrderedClause(Expr *Num, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
NumForLoops(Num) {}
|
||||
static OMPOrderedClause *Create(const ASTContext &C, Expr *Num,
|
||||
unsigned NumLoops, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// Build an empty clause.
|
||||
explicit OMPOrderedClause()
|
||||
: OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {}
|
||||
static OMPOrderedClause* CreateEmpty(const ASTContext &C, unsigned NumLoops);
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
@ -959,6 +982,17 @@ public:
|
||||
/// Return the number of associated for-loops.
|
||||
Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
|
||||
|
||||
/// Set number of iterations for the specified loop.
|
||||
void setLoopNumIterations(unsigned NumLoop, Expr *NumIterations);
|
||||
/// Get number of iterations for all the loops.
|
||||
ArrayRef<Expr *> getLoopNumIterations() const;
|
||||
|
||||
/// Set loop counter for the specified loop.
|
||||
void setLoopCounter(unsigned NumLoop, Expr *Counter);
|
||||
/// Get loops counter for the specified loop.
|
||||
Expr *getLoopCunter(unsigned NumLoop);
|
||||
const Expr *getLoopCunter(unsigned NumLoop) const;
|
||||
|
||||
child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
@ -3087,24 +3121,32 @@ class OMPDependClause final
|
||||
/// Colon location.
|
||||
SourceLocation ColonLoc;
|
||||
|
||||
/// Number of loops, associated with the depend clause.
|
||||
unsigned NumLoops = 0;
|
||||
|
||||
/// Build clause with number of variables \a N.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param N Number of the variables in the clause.
|
||||
/// \param NumLoops Number of loops that is associated with this depend
|
||||
/// clause.
|
||||
OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, unsigned N)
|
||||
SourceLocation EndLoc, unsigned N, unsigned NumLoops)
|
||||
: OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc,
|
||||
EndLoc, N) {}
|
||||
EndLoc, N), NumLoops(NumLoops) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
///
|
||||
/// \param N Number of variables.
|
||||
explicit OMPDependClause(unsigned N)
|
||||
/// \param NumLoops Number of loops that is associated with this depend
|
||||
/// clause.
|
||||
explicit OMPDependClause(unsigned N, unsigned NumLoops)
|
||||
: OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(),
|
||||
SourceLocation(), SourceLocation(),
|
||||
N) {}
|
||||
N),
|
||||
NumLoops(NumLoops) {}
|
||||
|
||||
/// Set dependency kind.
|
||||
void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; }
|
||||
@ -3126,16 +3168,23 @@ public:
|
||||
/// \param DepLoc Location of the dependency type.
|
||||
/// \param ColonLoc Colon location.
|
||||
/// \param VL List of references to the variables.
|
||||
static OMPDependClause *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
|
||||
SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL);
|
||||
/// \param NumLoops Number of loops that is associated with this depend
|
||||
/// clause.
|
||||
static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc,
|
||||
OpenMPDependClauseKind DepKind,
|
||||
SourceLocation DepLoc, SourceLocation ColonLoc,
|
||||
ArrayRef<Expr *> VL, unsigned NumLoops);
|
||||
|
||||
/// Creates an empty clause with \a N variables.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param N The number of variables.
|
||||
static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N);
|
||||
/// \param NumLoops Number of loops that is associated with this depend
|
||||
/// clause.
|
||||
static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N,
|
||||
unsigned NumLoops);
|
||||
|
||||
/// Get dependency type.
|
||||
OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
|
||||
@ -3146,15 +3195,16 @@ public:
|
||||
/// Get colon location.
|
||||
SourceLocation getColonLoc() const { return ColonLoc; }
|
||||
|
||||
/// Set the loop counter value for the depend clauses with 'sink|source' kind
|
||||
/// of dependency. Required for codegen.
|
||||
void setCounterValue(Expr *V);
|
||||
/// Get number of loops associated with the clause.
|
||||
unsigned getNumLoops() const { return NumLoops; }
|
||||
|
||||
/// Get the loop counter value.
|
||||
Expr *getCounterValue();
|
||||
/// Set the loop data for the depend clauses with 'sink|source' kind of
|
||||
/// dependency.
|
||||
void setLoopData(unsigned NumLoop, Expr *Cnt);
|
||||
|
||||
/// Get the loop counter value.
|
||||
const Expr *getCounterValue() const;
|
||||
/// Get the loop data.
|
||||
Expr *getLoopData(unsigned NumLoop);
|
||||
const Expr *getLoopData(unsigned NumLoop) const;
|
||||
|
||||
child_range children() {
|
||||
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
|
@ -2938,9 +2938,10 @@ def OMPDeclareSimdDecl : Attr {
|
||||
}];
|
||||
}
|
||||
|
||||
def OMPDeclareTargetDecl : Attr {
|
||||
def OMPDeclareTargetDecl : InheritableAttr {
|
||||
let Spellings = [Pragma<"omp", "declare target">];
|
||||
let SemaHandler = 0;
|
||||
let Subjects = SubjectList<[Function, SharedVar]>;
|
||||
let Documentation = [OMPDeclareTargetDocs];
|
||||
let Args = [
|
||||
EnumArgument<"MapType", "MapTypeTy",
|
||||
@ -2953,6 +2954,15 @@ def OMPDeclareTargetDecl : Attr {
|
||||
if (getMapType() != MT_To)
|
||||
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
|
||||
}
|
||||
static llvm::Optional<MapTypeTy>
|
||||
isDeclareTargetDeclaration(const ValueDecl *VD) {
|
||||
if (!VD->hasAttrs())
|
||||
return llvm::None;
|
||||
if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
|
||||
return Attr->getMapType();
|
||||
|
||||
return llvm::None;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,6 @@ def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
|
||||
def NullPointerArithmetic : DiagGroup<"null-pointer-arithmetic">;
|
||||
def : DiagGroup<"effc++", [NonVirtualDtor]>;
|
||||
def OveralignedType : DiagGroup<"over-aligned">;
|
||||
def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">;
|
||||
def OldStyleCast : DiagGroup<"old-style-cast">;
|
||||
def : DiagGroup<"old-style-definition">;
|
||||
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
|
||||
|
@ -6465,12 +6465,12 @@ def warn_overaligned_type : Warning<
|
||||
"type %0 requires %1 bytes of alignment and the default allocator only "
|
||||
"guarantees %2 bytes">,
|
||||
InGroup<OveralignedType>, DefaultIgnore;
|
||||
def warn_aligned_allocation_unavailable :Warning<
|
||||
def err_aligned_allocation_unavailable : Error<
|
||||
"aligned %select{allocation|deallocation}0 function of type '%1' is only "
|
||||
"available on %2 %3 or newer">, InGroup<AlignedAllocationUnavailable>, DefaultError;
|
||||
"available on %2 %3 or newer">;
|
||||
def note_silence_unligned_allocation_unavailable : Note<
|
||||
"if you supply your own aligned allocation functions, use "
|
||||
"-Wno-aligned-allocation-unavailable to silence this diagnostic">;
|
||||
"-faligned-allocation to silence this diagnostic">;
|
||||
|
||||
def err_conditional_void_nonvoid : Error<
|
||||
"%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
|
||||
|
@ -1488,7 +1488,7 @@ def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Enable ARC-style weak references in Objective-C">;
|
||||
|
||||
// Objective-C ABI options.
|
||||
def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
|
||||
HelpText<"Specify the target Objective-C runtime kind and version">;
|
||||
def fobjc_abi_version_EQ : Joined<["-"], "fobjc-abi-version=">, Group<f_Group>;
|
||||
def fobjc_nonfragile_abi_version_EQ : Joined<["-"], "fobjc-nonfragile-abi-version=">, Group<f_Group>;
|
||||
|
@ -9798,20 +9798,16 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
||||
return true;
|
||||
|
||||
// If the decl is marked as `declare target`, it should be emitted.
|
||||
for (const auto *Decl : D->redecls()) {
|
||||
if (!Decl->hasAttrs())
|
||||
continue;
|
||||
if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>())
|
||||
if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link)
|
||||
return true;
|
||||
}
|
||||
if (const llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
|
||||
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
|
||||
return *Res != OMPDeclareTargetDeclAttr::MT_Link;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ASTContext::forEachMultiversionedFunctionVersion(
|
||||
const FunctionDecl *FD,
|
||||
llvm::function_ref<void(const FunctionDecl *)> Pred) const {
|
||||
llvm::function_ref<void(FunctionDecl *)> Pred) const {
|
||||
assert(FD->isMultiVersion() && "Only valid for multiversioned functions");
|
||||
llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls;
|
||||
FD = FD->getCanonicalDecl();
|
||||
|
@ -1091,6 +1091,10 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||
printTemplateParameters(FD->getTemplateParameterList(I));
|
||||
}
|
||||
VisitRedeclarableTemplateDecl(D);
|
||||
// Declare target attribute is special one, natural spelling for the pragma
|
||||
// assumes "ending" construct so print it here.
|
||||
if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
|
||||
Out << "#pragma omp end declare target\n";
|
||||
|
||||
// Never print "instantiations" for deduction guides (they don't really
|
||||
// have them).
|
||||
|
@ -445,7 +445,7 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
|
||||
mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD));
|
||||
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
|
||||
mangleVariableEncoding(VD);
|
||||
else
|
||||
else if (!isa<ObjCInterfaceDecl>(D))
|
||||
llvm_unreachable("Tried to mangle unexpected NamedDecl!");
|
||||
}
|
||||
|
||||
@ -1884,13 +1884,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
|
||||
llvm_unreachable("placeholder types shouldn't get to name mangling");
|
||||
|
||||
case BuiltinType::ObjCId:
|
||||
mangleArtificalTagType(TTK_Struct, "objc_object");
|
||||
mangleArtificalTagType(TTK_Struct, ".objc_object");
|
||||
break;
|
||||
case BuiltinType::ObjCClass:
|
||||
mangleArtificalTagType(TTK_Struct, "objc_class");
|
||||
mangleArtificalTagType(TTK_Struct, ".objc_class");
|
||||
break;
|
||||
case BuiltinType::ObjCSel:
|
||||
mangleArtificalTagType(TTK_Struct, "objc_selector");
|
||||
mangleArtificalTagType(TTK_Struct, ".objc_selector");
|
||||
break;
|
||||
|
||||
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
|
||||
@ -2570,9 +2570,10 @@ void MicrosoftCXXNameMangler::mangleType(const DependentAddressSpaceType *T,
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
|
||||
SourceRange) {
|
||||
// ObjC interfaces have structs underlying them.
|
||||
// ObjC interfaces are mangled as if they were structs with a name that is
|
||||
// not a valid C/C++ identifier
|
||||
mangleTagTypeKind(TTK_Struct);
|
||||
mangleName(T->getDecl());
|
||||
mangle(T->getDecl(), ".objc_cls_");
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
|
||||
@ -2590,11 +2591,11 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
|
||||
|
||||
Out << "?$";
|
||||
if (T->isObjCId())
|
||||
mangleSourceName("objc_object");
|
||||
mangleSourceName(".objc_object");
|
||||
else if (T->isObjCClass())
|
||||
mangleSourceName("objc_class");
|
||||
mangleSourceName(".objc_class");
|
||||
else
|
||||
mangleSourceName(T->getInterface()->getName());
|
||||
mangleSourceName((".objc_cls_" + T->getInterface()->getName()).str());
|
||||
|
||||
for (const auto &Q : T->quals())
|
||||
mangleObjCProtocol(Q);
|
||||
|
@ -181,6 +181,57 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num,
|
||||
unsigned NumLoops,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
|
||||
auto *Clause =
|
||||
new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc);
|
||||
for (unsigned I = 0; I < NumLoops; ++I) {
|
||||
Clause->setLoopNumIterations(I, nullptr);
|
||||
Clause->setLoopCounter(I, nullptr);
|
||||
}
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C,
|
||||
unsigned NumLoops) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
|
||||
auto *Clause = new (Mem) OMPOrderedClause(NumLoops);
|
||||
for (unsigned I = 0; I < NumLoops; ++I) {
|
||||
Clause->setLoopNumIterations(I, nullptr);
|
||||
Clause->setLoopCounter(I, nullptr);
|
||||
}
|
||||
return Clause;
|
||||
}
|
||||
|
||||
void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop,
|
||||
Expr *NumIterations) {
|
||||
assert(NumLoop < NumberOfLoops && "out of loops number.");
|
||||
getTrailingObjects<Expr *>()[NumLoop] = NumIterations;
|
||||
}
|
||||
|
||||
ArrayRef<Expr *> OMPOrderedClause::getLoopNumIterations() const {
|
||||
return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumberOfLoops);
|
||||
}
|
||||
|
||||
void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) {
|
||||
assert(NumLoop < NumberOfLoops && "out of loops number.");
|
||||
getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop] = Counter;
|
||||
}
|
||||
|
||||
Expr *OMPOrderedClause::getLoopCunter(unsigned NumLoop) {
|
||||
assert(NumLoop < NumberOfLoops && "out of loops number.");
|
||||
return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
|
||||
}
|
||||
|
||||
const Expr *OMPOrderedClause::getLoopCunter(unsigned NumLoop) const {
|
||||
assert(NumLoop < NumberOfLoops && "out of loops number.");
|
||||
return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
|
||||
}
|
||||
|
||||
void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
|
||||
assert(VL.size() == varlist_size() &&
|
||||
"Number of private copies is not the same as the preallocated buffer");
|
||||
@ -653,44 +704,58 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
|
||||
return new (Mem) OMPFlushClause(N);
|
||||
}
|
||||
|
||||
OMPDependClause *OMPDependClause::Create(
|
||||
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
|
||||
SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
|
||||
OMPDependClause *Clause =
|
||||
new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size());
|
||||
OMPDependClause *
|
||||
OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc,
|
||||
OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
|
||||
SourceLocation ColonLoc, ArrayRef<Expr *> VL,
|
||||
unsigned NumLoops) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops));
|
||||
OMPDependClause *Clause = new (Mem)
|
||||
OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
|
||||
Clause->setVarRefs(VL);
|
||||
Clause->setDependencyKind(DepKind);
|
||||
Clause->setDependencyLoc(DepLoc);
|
||||
Clause->setColonLoc(ColonLoc);
|
||||
Clause->setCounterValue(nullptr);
|
||||
for (unsigned I = 0 ; I < NumLoops; ++I)
|
||||
Clause->setLoopData(I, nullptr);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1));
|
||||
return new (Mem) OMPDependClause(N);
|
||||
OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N,
|
||||
unsigned NumLoops) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops));
|
||||
return new (Mem) OMPDependClause(N, NumLoops);
|
||||
}
|
||||
|
||||
void OMPDependClause::setCounterValue(Expr *V) {
|
||||
assert(getDependencyKind() == OMPC_DEPEND_sink ||
|
||||
getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
|
||||
*getVarRefs().end() = V;
|
||||
void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
|
||||
assert((getDependencyKind() == OMPC_DEPEND_sink ||
|
||||
getDependencyKind() == OMPC_DEPEND_source) &&
|
||||
NumLoop < NumLoops &&
|
||||
"Expected sink or source depend + loop index must be less number of "
|
||||
"loops.");
|
||||
auto It = std::next(getVarRefs().end(), NumLoop);
|
||||
*It = Cnt;
|
||||
}
|
||||
|
||||
const Expr *OMPDependClause::getCounterValue() const {
|
||||
auto *V = *getVarRefs().end();
|
||||
assert(getDependencyKind() == OMPC_DEPEND_sink ||
|
||||
getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
|
||||
return V;
|
||||
Expr *OMPDependClause::getLoopData(unsigned NumLoop) {
|
||||
assert((getDependencyKind() == OMPC_DEPEND_sink ||
|
||||
getDependencyKind() == OMPC_DEPEND_source) &&
|
||||
NumLoop < NumLoops &&
|
||||
"Expected sink or source depend + loop index must be less number of "
|
||||
"loops.");
|
||||
auto It = std::next(getVarRefs().end(), NumLoop);
|
||||
return *It;
|
||||
}
|
||||
|
||||
Expr *OMPDependClause::getCounterValue() {
|
||||
auto *V = *getVarRefs().end();
|
||||
assert(getDependencyKind() == OMPC_DEPEND_sink ||
|
||||
getDependencyKind() == OMPC_DEPEND_source || V == nullptr);
|
||||
return V;
|
||||
const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const {
|
||||
assert((getDependencyKind() == OMPC_DEPEND_sink ||
|
||||
getDependencyKind() == OMPC_DEPEND_source) &&
|
||||
NumLoop < NumLoops &&
|
||||
"Expected sink or source depend + loop index must be less number of "
|
||||
"loops.");
|
||||
auto It = std::next(getVarRefs().end(), NumLoop);
|
||||
return *It;
|
||||
}
|
||||
|
||||
unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
|
||||
|
@ -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()) {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -4912,7 +4912,8 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
|
||||
}
|
||||
if ((runtime.getKind() == ObjCRuntime::GNUstep) &&
|
||||
(runtime.getVersion() >= VersionTuple(2, 0)))
|
||||
if (!getToolChain().getTriple().isOSBinFormatELF()) {
|
||||
if (!getToolChain().getTriple().isOSBinFormatELF() &&
|
||||
!getToolChain().getTriple().isOSBinFormatCOFF()) {
|
||||
getToolChain().getDriver().Diag(
|
||||
diag::err_drv_gnustep_objc_runtime_incompatible_binary)
|
||||
<< runtime.getVersion().getMajor();
|
||||
|
@ -2035,7 +2035,11 @@ bool Darwin::isAlignedAllocationUnavailable() const {
|
||||
void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args,
|
||||
Action::OffloadKind DeviceOffloadKind) const {
|
||||
if (isAlignedAllocationUnavailable())
|
||||
// Pass "-faligned-alloc-unavailable" only when the user hasn't manually
|
||||
// enabled or disabled aligned allocations.
|
||||
if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
|
||||
options::OPT_fno_aligned_allocation) &&
|
||||
isAlignedAllocationUnavailable())
|
||||
CC1Args.push_back("-faligned-alloc-unavailable");
|
||||
}
|
||||
|
||||
|
@ -553,7 +553,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
|
||||
Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L");
|
||||
Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L");
|
||||
}
|
||||
if (LangOpts.AlignedAllocation)
|
||||
if (LangOpts.AlignedAllocation && !LangOpts.AlignedAllocationUnavailable)
|
||||
Builder.defineMacro("__cpp_aligned_new", "201606L");
|
||||
if (LangOpts.RelaxedTemplateTemplateArgs)
|
||||
Builder.defineMacro("__cpp_template_template_args", "201611L");
|
||||
|
@ -1747,9 +1747,9 @@ static void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
|
||||
StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling(
|
||||
S.getASTContext().getTargetInfo().getPlatformName());
|
||||
|
||||
S.Diag(Loc, diag::warn_aligned_allocation_unavailable)
|
||||
<< IsDelete << FD.getType().getAsString() << OSName
|
||||
<< alignedAllocMinVersion(T.getOS()).getAsString();
|
||||
S.Diag(Loc, diag::err_aligned_allocation_unavailable)
|
||||
<< IsDelete << FD.getType().getAsString() << OSName
|
||||
<< alignedAllocMinVersion(T.getOS()).getAsString();
|
||||
S.Diag(Loc, diag::note_silence_unligned_allocation_unavailable);
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,8 @@ public:
|
||||
};
|
||||
using OperatorOffsetTy =
|
||||
llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
|
||||
using DoacrossDependMapTy =
|
||||
llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
|
||||
|
||||
private:
|
||||
struct DSAInfo {
|
||||
@ -97,8 +99,6 @@ private:
|
||||
llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
|
||||
using CriticalsWithHintsTy =
|
||||
llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
|
||||
using DoacrossDependMapTy =
|
||||
llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
|
||||
struct ReductionData {
|
||||
using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
|
||||
SourceRange ReductionRange;
|
||||
@ -137,7 +137,7 @@ private:
|
||||
/// first argument (Expr *) contains optional argument of the
|
||||
/// 'ordered' clause, the second one is true if the regions has 'ordered'
|
||||
/// clause, false otherwise.
|
||||
llvm::PointerIntPair<const Expr *, 1, bool> OrderedRegion;
|
||||
llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
|
||||
bool NowaitRegion = false;
|
||||
bool CancelRegion = false;
|
||||
unsigned AssociatedLoops = 1;
|
||||
@ -398,23 +398,42 @@ public:
|
||||
}
|
||||
|
||||
/// Marks current region as ordered (it has an 'ordered' clause).
|
||||
void setOrderedRegion(bool IsOrdered, const Expr *Param) {
|
||||
void setOrderedRegion(bool IsOrdered, const Expr *Param,
|
||||
OMPOrderedClause *Clause) {
|
||||
assert(!isStackEmpty());
|
||||
Stack.back().first.back().OrderedRegion.setInt(IsOrdered);
|
||||
Stack.back().first.back().OrderedRegion.setPointer(Param);
|
||||
if (IsOrdered)
|
||||
Stack.back().first.back().OrderedRegion.emplace(Param, Clause);
|
||||
else
|
||||
Stack.back().first.back().OrderedRegion.reset();
|
||||
}
|
||||
/// Returns true, if region is ordered (has associated 'ordered' clause),
|
||||
/// false - otherwise.
|
||||
bool isOrderedRegion() const {
|
||||
if (isStackEmpty())
|
||||
return false;
|
||||
return Stack.back().first.rbegin()->OrderedRegion.hasValue();
|
||||
}
|
||||
/// Returns optional parameter for the ordered region.
|
||||
std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
|
||||
if (isStackEmpty() ||
|
||||
!Stack.back().first.rbegin()->OrderedRegion.hasValue())
|
||||
return std::make_pair(nullptr, nullptr);
|
||||
return Stack.back().first.rbegin()->OrderedRegion.getValue();
|
||||
}
|
||||
/// Returns true, if parent region is ordered (has associated
|
||||
/// 'ordered' clause), false - otherwise.
|
||||
bool isParentOrderedRegion() const {
|
||||
if (isStackEmpty() || Stack.back().first.size() == 1)
|
||||
return false;
|
||||
return std::next(Stack.back().first.rbegin())->OrderedRegion.getInt();
|
||||
return std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue();
|
||||
}
|
||||
/// Returns optional parameter for the ordered region.
|
||||
const Expr *getParentOrderedRegionParam() const {
|
||||
if (isStackEmpty() || Stack.back().first.size() == 1)
|
||||
return nullptr;
|
||||
return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer();
|
||||
std::pair<const Expr *, OMPOrderedClause *>
|
||||
getParentOrderedRegionParam() const {
|
||||
if (isStackEmpty() || Stack.back().first.size() == 1 ||
|
||||
!std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue())
|
||||
return std::make_pair(nullptr, nullptr);
|
||||
return std::next(Stack.back().first.rbegin())->OrderedRegion.getValue();
|
||||
}
|
||||
/// Marks current region as nowait (it has a 'nowait' clause).
|
||||
void setNowaitRegion(bool IsNowait = true) {
|
||||
@ -1239,17 +1258,6 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
|
||||
DSAStack->popFunction(OldFSI);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const {
|
||||
assert(LangOpts.OpenMP && "OpenMP is not allowed");
|
||||
|
||||
@ -1429,7 +1437,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const {
|
||||
// If the declaration is enclosed in a 'declare target' directive,
|
||||
// then it should not be captured.
|
||||
//
|
||||
if (isDeclareTargetDeclaration(VD))
|
||||
if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
|
||||
return nullptr;
|
||||
return VD;
|
||||
}
|
||||
@ -1968,7 +1976,7 @@ public:
|
||||
|
||||
// Skip internally declared static variables.
|
||||
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
|
||||
isDeclareTargetDeclaration(VD);
|
||||
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
|
||||
if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) &&
|
||||
(!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link))
|
||||
return;
|
||||
@ -3736,6 +3744,13 @@ public:
|
||||
Expr *buildCounterInit() const;
|
||||
/// Build step of the counter be used for codegen.
|
||||
Expr *buildCounterStep() const;
|
||||
/// Build loop data with counter value for depend clauses in ordered
|
||||
/// directives.
|
||||
Expr *
|
||||
buildOrderedLoopData(Scope *S, Expr *Counter,
|
||||
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
|
||||
SourceLocation Loc, Expr *Inc = nullptr,
|
||||
OverloadedOperatorKind OOK = OO_Amp);
|
||||
/// Return true if any expression is dependent.
|
||||
bool dependent() const;
|
||||
|
||||
@ -3900,7 +3915,12 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
|
||||
SemaRef.Diag(S->getLocStart(),
|
||||
diag::ext_omp_loop_not_canonical_init)
|
||||
<< S->getSourceRange();
|
||||
return setLCDeclAndLB(Var, nullptr, Var->getInit());
|
||||
return setLCDeclAndLB(
|
||||
Var,
|
||||
buildDeclRefExpr(SemaRef, Var,
|
||||
Var->getType().getNonReferenceType(),
|
||||
DS->getLocStart()),
|
||||
Var->getInit());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4262,7 +4282,8 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond(
|
||||
|
||||
/// Build reference expression to the counter be used for codegen.
|
||||
DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
|
||||
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const {
|
||||
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
|
||||
DSAStackTy &DSA) const {
|
||||
auto *VD = dyn_cast<VarDecl>(LCDecl);
|
||||
if (!VD) {
|
||||
VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
|
||||
@ -4302,6 +4323,63 @@ Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
|
||||
/// Build step of the counter be used for codegen.
|
||||
Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
|
||||
|
||||
Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
|
||||
Scope *S, Expr *Counter,
|
||||
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
|
||||
Expr *Inc, OverloadedOperatorKind OOK) {
|
||||
Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
|
||||
if (!Cnt)
|
||||
return nullptr;
|
||||
if (Inc) {
|
||||
assert((OOK == OO_Plus || OOK == OO_Minus) &&
|
||||
"Expected only + or - operations for depend clauses.");
|
||||
BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
|
||||
Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
|
||||
if (!Cnt)
|
||||
return nullptr;
|
||||
}
|
||||
ExprResult Diff;
|
||||
QualType VarType = LCDecl->getType().getNonReferenceType();
|
||||
if (VarType->isIntegerType() || VarType->isPointerType() ||
|
||||
SemaRef.getLangOpts().CPlusPlus) {
|
||||
// Upper - Lower
|
||||
Expr *Upper =
|
||||
TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get();
|
||||
Expr *Lower =
|
||||
TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
|
||||
if (!Upper || !Lower)
|
||||
return nullptr;
|
||||
|
||||
Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
|
||||
|
||||
if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) {
|
||||
// BuildBinOp already emitted error, this one is to point user to upper
|
||||
// and lower bound, and to tell what is passed to 'operator-'.
|
||||
SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx)
|
||||
<< Upper->getSourceRange() << Lower->getSourceRange();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Diff.isUsable())
|
||||
return nullptr;
|
||||
|
||||
// Parentheses (for dumping/debugging purposes only).
|
||||
Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
|
||||
if (!Diff.isUsable())
|
||||
return nullptr;
|
||||
|
||||
ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
|
||||
if (!NewStep.isUsable())
|
||||
return nullptr;
|
||||
// (Upper - Lower) / Step
|
||||
Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
|
||||
if (!Diff.isUsable())
|
||||
return nullptr;
|
||||
|
||||
return Diff.get();
|
||||
}
|
||||
|
||||
/// Iteration space of a single for loop.
|
||||
struct LoopIterationSpace final {
|
||||
/// Condition of the loop.
|
||||
@ -4361,7 +4439,8 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
|
||||
static bool checkOpenMPIterationSpace(
|
||||
OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
|
||||
unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
|
||||
Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,
|
||||
unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
|
||||
Expr *OrderedLoopCountExpr,
|
||||
Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
|
||||
LoopIterationSpace &ResultIterSpace,
|
||||
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
|
||||
@ -4371,9 +4450,9 @@ static bool checkOpenMPIterationSpace(
|
||||
if (!For) {
|
||||
SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
|
||||
<< (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
|
||||
<< getOpenMPDirectiveName(DKind) << NestedLoopCount
|
||||
<< getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
|
||||
<< (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
|
||||
if (NestedLoopCount > 1) {
|
||||
if (TotalNestedLoopCount > 1) {
|
||||
if (CollapseLoopCountExpr && OrderedLoopCountExpr)
|
||||
SemaRef.Diag(DSA.getConstructLoc(),
|
||||
diag::note_omp_collapse_ordered_expr)
|
||||
@ -4506,6 +4585,41 @@ static bool checkOpenMPIterationSpace(
|
||||
ResultIterSpace.PrivateCounterVar == nullptr ||
|
||||
ResultIterSpace.CounterInit == nullptr ||
|
||||
ResultIterSpace.CounterStep == nullptr);
|
||||
if (!HasErrors && DSA.isOrderedRegion()) {
|
||||
if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
|
||||
if (CurrentNestedLoopCount <
|
||||
DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
|
||||
DSA.getOrderedRegionParam().second->setLoopNumIterations(
|
||||
CurrentNestedLoopCount, ResultIterSpace.NumIterations);
|
||||
DSA.getOrderedRegionParam().second->setLoopCounter(
|
||||
CurrentNestedLoopCount, ResultIterSpace.CounterVar);
|
||||
}
|
||||
}
|
||||
for (auto &Pair : DSA.getDoacrossDependClauses()) {
|
||||
if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
|
||||
// Erroneous case - clause has some problems.
|
||||
continue;
|
||||
}
|
||||
if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
|
||||
Pair.second.size() <= CurrentNestedLoopCount) {
|
||||
// Erroneous case - clause has some problems.
|
||||
Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
|
||||
continue;
|
||||
}
|
||||
Expr *CntValue;
|
||||
if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
|
||||
CntValue = ISC.buildOrderedLoopData(
|
||||
DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
|
||||
Pair.first->getDependencyLoc());
|
||||
else
|
||||
CntValue = ISC.buildOrderedLoopData(
|
||||
DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
|
||||
Pair.first->getDependencyLoc(),
|
||||
Pair.second[CurrentNestedLoopCount].first,
|
||||
Pair.second[CurrentNestedLoopCount].second);
|
||||
Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
|
||||
}
|
||||
}
|
||||
|
||||
return HasErrors;
|
||||
}
|
||||
@ -4691,6 +4805,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
||||
if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
|
||||
NestedLoopCount = Result.getLimitedValue();
|
||||
}
|
||||
unsigned OrderedLoopCount = 1;
|
||||
if (OrderedLoopCountExpr) {
|
||||
// Found 'ordered' clause - calculate collapse number.
|
||||
llvm::APSInt Result;
|
||||
@ -4703,20 +4818,21 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
||||
diag::note_collapse_loop_count)
|
||||
<< CollapseLoopCountExpr->getSourceRange();
|
||||
}
|
||||
NestedLoopCount = Result.getLimitedValue();
|
||||
OrderedLoopCount = Result.getLimitedValue();
|
||||
}
|
||||
}
|
||||
// This is helper routine for loop directives (e.g., 'for', 'simd',
|
||||
// 'for simd', etc.).
|
||||
llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
|
||||
SmallVector<LoopIterationSpace, 4> IterSpaces;
|
||||
IterSpaces.resize(NestedLoopCount);
|
||||
IterSpaces.resize(std::max(OrderedLoopCount, NestedLoopCount));
|
||||
Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
|
||||
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
|
||||
if (checkOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
|
||||
NestedLoopCount, CollapseLoopCountExpr,
|
||||
OrderedLoopCountExpr, VarsWithImplicitDSA,
|
||||
IterSpaces[Cnt], Captures))
|
||||
if (checkOpenMPIterationSpace(
|
||||
DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
|
||||
std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
|
||||
OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
|
||||
Captures))
|
||||
return 0;
|
||||
// Move on to the next nested for loop, or to the loop body.
|
||||
// OpenMP [2.8.1, simd construct, Restrictions]
|
||||
@ -4725,6 +4841,27 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
||||
// any two loops.
|
||||
CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
|
||||
}
|
||||
for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) {
|
||||
if (checkOpenMPIterationSpace(
|
||||
DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
|
||||
std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
|
||||
OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
|
||||
Captures))
|
||||
return 0;
|
||||
if (Cnt > 0 && IterSpaces[Cnt].CounterVar) {
|
||||
// Handle initialization of captured loop iterator variables.
|
||||
auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
|
||||
if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
|
||||
Captures[DRE] = DRE;
|
||||
}
|
||||
}
|
||||
// Move on to the next nested for loop, or to the loop body.
|
||||
// OpenMP [2.8.1, simd construct, Restrictions]
|
||||
// All loops associated with the construct must be perfectly nested; that
|
||||
// is, there must be no intervening code nor any OpenMP directive between
|
||||
// any two loops.
|
||||
CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
|
||||
}
|
||||
|
||||
Built.clear(/* size */ NestedLoopCount);
|
||||
|
||||
@ -5104,7 +5241,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
||||
Built.Inits.resize(NestedLoopCount);
|
||||
Built.Updates.resize(NestedLoopCount);
|
||||
Built.Finals.resize(NestedLoopCount);
|
||||
SmallVector<Expr *, 4> LoopMultipliers;
|
||||
{
|
||||
ExprResult Div;
|
||||
// Go from inner nested loop to outer.
|
||||
@ -5174,7 +5310,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
||||
HasErrors = true;
|
||||
break;
|
||||
}
|
||||
LoopMultipliers.push_back(Div.get());
|
||||
}
|
||||
if (!Update.isUsable() || !Final.isUsable()) {
|
||||
HasErrors = true;
|
||||
@ -5222,55 +5357,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
||||
Built.DistCombinedFields.NLB = CombNextLB.get();
|
||||
Built.DistCombinedFields.NUB = CombNextUB.get();
|
||||
|
||||
Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get();
|
||||
// Fill data for doacross depend clauses.
|
||||
for (const auto &Pair : DSA.getDoacrossDependClauses()) {
|
||||
if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) {
|
||||
Pair.first->setCounterValue(CounterVal);
|
||||
} else {
|
||||
if (NestedLoopCount != Pair.second.size() ||
|
||||
NestedLoopCount != LoopMultipliers.size() + 1) {
|
||||
// Erroneous case - clause has some problems.
|
||||
Pair.first->setCounterValue(CounterVal);
|
||||
continue;
|
||||
}
|
||||
assert(Pair.first->getDependencyKind() == OMPC_DEPEND_sink);
|
||||
auto I = Pair.second.rbegin();
|
||||
auto IS = IterSpaces.rbegin();
|
||||
auto ILM = LoopMultipliers.rbegin();
|
||||
Expr *UpCounterVal = CounterVal;
|
||||
Expr *Multiplier = nullptr;
|
||||
for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) {
|
||||
if (I->first) {
|
||||
assert(IS->CounterStep);
|
||||
Expr *NormalizedOffset =
|
||||
SemaRef
|
||||
.BuildBinOp(CurScope, I->first->getExprLoc(), BO_Div,
|
||||
I->first, IS->CounterStep)
|
||||
.get();
|
||||
if (Multiplier) {
|
||||
NormalizedOffset =
|
||||
SemaRef
|
||||
.BuildBinOp(CurScope, I->first->getExprLoc(), BO_Mul,
|
||||
NormalizedOffset, Multiplier)
|
||||
.get();
|
||||
}
|
||||
assert(I->second == OO_Plus || I->second == OO_Minus);
|
||||
BinaryOperatorKind BOK = (I->second == OO_Plus) ? BO_Add : BO_Sub;
|
||||
UpCounterVal = SemaRef
|
||||
.BuildBinOp(CurScope, I->first->getExprLoc(), BOK,
|
||||
UpCounterVal, NormalizedOffset)
|
||||
.get();
|
||||
}
|
||||
Multiplier = *ILM;
|
||||
++I;
|
||||
++IS;
|
||||
++ILM;
|
||||
}
|
||||
Pair.first->setCounterValue(UpCounterVal);
|
||||
}
|
||||
}
|
||||
|
||||
return NestedLoopCount;
|
||||
}
|
||||
|
||||
@ -5838,12 +5924,12 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd)
|
||||
<< getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
|
||||
ErrorFound = true;
|
||||
} else if (DependFound && !DSAStack->getParentOrderedRegionParam()) {
|
||||
} else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) {
|
||||
Diag(DependFound->getLocStart(),
|
||||
diag::err_omp_ordered_directive_without_param);
|
||||
ErrorFound = true;
|
||||
} else if (TC || Clauses.empty()) {
|
||||
if (const Expr *Param = DSAStack->getParentOrderedRegionParam()) {
|
||||
if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
|
||||
SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc;
|
||||
Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
|
||||
<< (TC != nullptr);
|
||||
@ -8619,9 +8705,11 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
|
||||
} else {
|
||||
NumForLoops = nullptr;
|
||||
}
|
||||
DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops);
|
||||
return new (Context)
|
||||
OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc);
|
||||
auto *Clause = OMPOrderedClause::Create(
|
||||
Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
|
||||
StartLoc, LParenLoc, EndLoc);
|
||||
DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPSimpleClause(
|
||||
@ -11477,8 +11565,9 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
|
||||
DSAStackTy::OperatorOffsetTy OpsOffs;
|
||||
llvm::APSInt DepCounter(/*BitWidth=*/32);
|
||||
llvm::APSInt TotalDepCount(/*BitWidth=*/32);
|
||||
if (DepKind == OMPC_DEPEND_sink) {
|
||||
if (const Expr *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
|
||||
if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
|
||||
if (const Expr *OrderedCountExpr =
|
||||
DSAStack->getParentOrderedRegionParam().first) {
|
||||
TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
|
||||
TotalDepCount.setIsUnsigned(/*Val=*/true);
|
||||
}
|
||||
@ -11494,7 +11583,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
|
||||
SourceLocation ELoc = RefExpr->getExprLoc();
|
||||
Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
|
||||
if (DepKind == OMPC_DEPEND_sink) {
|
||||
if (DSAStack->getParentOrderedRegionParam() &&
|
||||
if (DSAStack->getParentOrderedRegionParam().first &&
|
||||
DepCounter >= TotalDepCount) {
|
||||
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
|
||||
continue;
|
||||
@ -11560,7 +11649,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
|
||||
continue;
|
||||
}
|
||||
if (!CurContext->isDependentContext() &&
|
||||
DSAStack->getParentOrderedRegionParam() &&
|
||||
DSAStack->getParentOrderedRegionParam().first &&
|
||||
DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
|
||||
const ValueDecl *VD =
|
||||
DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
|
||||
@ -11598,7 +11687,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
|
||||
|
||||
if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
|
||||
TotalDepCount > VarList.size() &&
|
||||
DSAStack->getParentOrderedRegionParam() &&
|
||||
DSAStack->getParentOrderedRegionParam().first &&
|
||||
DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
|
||||
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
|
||||
<< 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
|
||||
@ -11608,7 +11697,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
|
||||
return nullptr;
|
||||
|
||||
auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc,
|
||||
DepKind, DepLoc, ColonLoc, Vars);
|
||||
DepKind, DepLoc, ColonLoc, Vars,
|
||||
TotalDepCount.getZExtValue());
|
||||
if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
|
||||
DSAStack->isParentOrderedRegion())
|
||||
DSAStack->addDoacrossDependClause(C, OpsOffs);
|
||||
@ -13042,6 +13132,8 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
|
||||
D = FTD->getTemplatedDecl();
|
||||
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (FD->hasAttr<OMPDeclareTargetDeclAttr>() &&
|
||||
(FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
|
||||
@ -13052,16 +13144,6 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
|
||||
if (FTD->hasAttr<OMPDeclareTargetDeclAttr>() &&
|
||||
(FTD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() ==
|
||||
OMPDeclareTargetDeclAttr::MT_Link)) {
|
||||
assert(IdLoc.isValid() && "Source location is expected");
|
||||
Diag(IdLoc, diag::err_omp_function_in_link_clause);
|
||||
Diag(FTD->getLocation(), diag::note_defined_here) << FTD;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!E) {
|
||||
// Checking declaration inside declare target region.
|
||||
if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
|
||||
|
@ -5192,10 +5192,20 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
|
||||
bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
|
||||
TSK_ExplicitInstantiationDefinition;
|
||||
InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
|
||||
DefinitionRequired, true);
|
||||
if (Function->isDefined())
|
||||
Function->setInstantiationIsPending(false);
|
||||
if (Function->isMultiVersion()) {
|
||||
getASTContext().forEachMultiversionedFunctionVersion(
|
||||
Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) {
|
||||
InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true,
|
||||
DefinitionRequired, true);
|
||||
if (CurFD->isDefined())
|
||||
CurFD->setInstantiationIsPending(false);
|
||||
});
|
||||
} else {
|
||||
InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true,
|
||||
DefinitionRequired, true);
|
||||
if (Function->isDefined())
|
||||
Function->setInstantiationIsPending(false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1856,7 +1856,7 @@ OMPClause *OMPClauseReader::readClause() {
|
||||
C = new (Context) OMPScheduleClause();
|
||||
break;
|
||||
case OMPC_ordered:
|
||||
C = new (Context) OMPOrderedClause();
|
||||
C = OMPOrderedClause::CreateEmpty(Context, Reader->Record.readInt());
|
||||
break;
|
||||
case OMPC_nowait:
|
||||
C = new (Context) OMPNowaitClause();
|
||||
@ -1927,9 +1927,12 @@ OMPClause *OMPClauseReader::readClause() {
|
||||
case OMPC_flush:
|
||||
C = OMPFlushClause::CreateEmpty(Context, Reader->Record.readInt());
|
||||
break;
|
||||
case OMPC_depend:
|
||||
C = OMPDependClause::CreateEmpty(Context, Reader->Record.readInt());
|
||||
case OMPC_depend: {
|
||||
unsigned NumVars = Reader->Record.readInt();
|
||||
unsigned NumLoops = Reader->Record.readInt();
|
||||
C = OMPDependClause::CreateEmpty(Context, NumVars, NumLoops);
|
||||
break;
|
||||
}
|
||||
case OMPC_device:
|
||||
C = new (Context) OMPDeviceClause();
|
||||
break;
|
||||
@ -2087,6 +2090,10 @@ void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
|
||||
void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) {
|
||||
C->setNumForLoops(Reader->Record.readSubExpr());
|
||||
for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I)
|
||||
C->setLoopNumIterations(I, Reader->Record.readSubExpr());
|
||||
for (unsigned I = 0, E = C->NumberOfLoops; I < E; ++I)
|
||||
C->setLoopCounter(I, Reader->Record.readSubExpr());
|
||||
C->setLParenLoc(Reader->ReadSourceLocation());
|
||||
}
|
||||
|
||||
@ -2395,10 +2402,11 @@ void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
|
||||
unsigned NumVars = C->varlist_size();
|
||||
SmallVector<Expr *, 16> Vars;
|
||||
Vars.reserve(NumVars);
|
||||
for (unsigned i = 0; i != NumVars; ++i)
|
||||
for (unsigned I = 0; I != NumVars; ++I)
|
||||
Vars.push_back(Reader->Record.readSubExpr());
|
||||
C->setVarRefs(Vars);
|
||||
C->setCounterValue(Reader->Record.readSubExpr());
|
||||
for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
|
||||
C->setLoopData(I, Reader->Record.readSubExpr());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
|
||||
|
@ -1898,7 +1898,12 @@ void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {
|
||||
Record.push_back(C->getLoopNumIterations().size());
|
||||
Record.AddStmt(C->getNumForLoops());
|
||||
for (Expr *NumIter : C->getLoopNumIterations())
|
||||
Record.AddStmt(NumIter);
|
||||
for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I)
|
||||
Record.AddStmt(C->getLoopCunter(I));
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
}
|
||||
|
||||
@ -2102,13 +2107,15 @@ void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
|
||||
|
||||
void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Record.push_back(C->getNumLoops());
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
Record.push_back(C->getDependencyKind());
|
||||
Record.AddSourceLocation(C->getDependencyLoc());
|
||||
Record.AddSourceLocation(C->getColonLoc());
|
||||
for (auto *VE : C->varlists())
|
||||
Record.AddStmt(VE);
|
||||
Record.AddStmt(C->getCounterValue());
|
||||
for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
|
||||
Record.AddStmt(C->getLoopData(I));
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
|
||||
|
@ -111,13 +111,12 @@ int templ_use() {
|
||||
// CHECK: call i32 @_ZN5templIiE3fooEi.ifunc
|
||||
// CHECK: call i32 @_ZN5templIdE3fooEi.ifunc
|
||||
|
||||
|
||||
// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat
|
||||
// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge
|
||||
// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge
|
||||
// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2
|
||||
// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi
|
||||
//
|
||||
|
||||
// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat
|
||||
// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge
|
||||
// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge
|
||||
@ -135,3 +134,12 @@ int templ_use() {
|
||||
// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32)
|
||||
// CHECK: ret i32 2
|
||||
|
||||
// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.sse4.2
|
||||
// CHECK: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge
|
||||
// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.arch_ivybridge
|
||||
// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi
|
||||
|
||||
// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.sse4.2
|
||||
// CHECK: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge
|
||||
// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.arch_ivybridge
|
||||
// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi
|
||||
|
@ -1,4 +1,5 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-NEW
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s -check-prefix=CHECK-WIN
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-1.8 -o - %s | FileCheck %s -check-prefix=CHECK-OLD
|
||||
|
||||
// Almost minimal Objective-C file, check that it emits calls to the correct
|
||||
@ -49,9 +50,9 @@
|
||||
// CHECK-NEW: @.objc_null_class_alias = linkonce_odr hidden global { i8*, i8* } zeroinitializer, section "__objc_class_aliases", comdat, align 8
|
||||
// CHECK-NEW: @.objc_null_constant_string = linkonce_odr hidden global { i8*, i32, i32, i32, i32, i8* } zeroinitializer, section "__objc_constant_string", comdat, align 8
|
||||
// Make sure that the null symbols are not going to be removed, even by linking.
|
||||
// CHECK-NEW: @llvm.used = appending global [7 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata"
|
||||
// CHECK-NEW: @llvm.used = appending global [8 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }*, i8*, i8*, i64, i64, i64, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i64, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast (void ()** @.objc_ctor to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_selector to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_category to i8*), i8* bitcast ({ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @.objc_null_protocol to i8*), i8* bitcast ({ i8* }* @.objc_null_protocol_ref to i8*), i8* bitcast ({ i8*, i8* }* @.objc_null_class_alias to i8*), i8* bitcast ({ i8*, i32, i32, i32, i32, i8* }* @.objc_null_constant_string to i8*)], section "llvm.metadata"
|
||||
// Make sure that the load function and the reference to it are marked as used.
|
||||
// CHECK-NEW: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata"
|
||||
// CHECK-NEW: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*)], section "llvm.metadata"
|
||||
|
||||
// Check that we emit the load function in a comdat and that it does the right thing.
|
||||
// CHECK-NEW: define linkonce_odr hidden void @.objcv2_load_function() comdat {
|
||||
@ -67,3 +68,37 @@
|
||||
// CHECK-OLD-NEXT: entry:
|
||||
// CHECK-OLD-NEXT: call void ({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }*, ...) @__objc_exec_class({ i64, i64, i8*, { i64, { i8*, i8* }*, i16, i16, [4 x i8*] }* }* @4)
|
||||
|
||||
|
||||
|
||||
// Make sure all of our section boundary variables are emitted correctly.
|
||||
// CHECK-WIN-DAG: @__start___objc_selectors = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_selectors$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_selectors = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_selectors$z", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__start___objc_classes = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_classes$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_classes = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_classes$z", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__start___objc_class_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_refs$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_class_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_refs$z", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__start___objc_cats = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_cats$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_cats = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_cats$z", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__start___objc_protocols = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocols$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_protocols = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocols$z", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__start___objc_protocol_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocol_refs$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_protocol_refs = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_protocol_refs$z", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__start___objc_class_aliases = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_aliases$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_class_aliases = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_class_aliases$z", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__start___objc_constant_string = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_constant_string$a", comdat, align 1
|
||||
// CHECK-WIN-DAG: @__stop__objc_constant_string = linkonce_odr hidden global %.objc_section_sentinel zeroinitializer, section "__objc_constant_string$z", comdat, align 1
|
||||
// CHECK-WIN: @.objc_init = linkonce_odr hidden global { i64, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel*, %.objc_section_sentinel* } { i64 0, %.objc_section_sentinel* @__start___objc_selectors, %.objc_section_sentinel* @__stop__objc_selectors, %.objc_section_sentinel* @__start___objc_classes, %.objc_section_sentinel* @__stop__objc_classes, %.objc_section_sentinel* @__start___objc_class_refs, %.objc_section_sentinel* @__stop__objc_class_refs, %.objc_section_sentinel* @__start___objc_cats, %.objc_section_sentinel* @__stop__objc_cats, %.objc_section_sentinel* @__start___objc_protocols, %.objc_section_sentinel* @__stop__objc_protocols, %.objc_section_sentinel* @__start___objc_protocol_refs, %.objc_section_sentinel* @__stop__objc_protocol_refs, %.objc_section_sentinel* @__start___objc_class_aliases, %.objc_section_sentinel* @__stop__objc_class_aliases, %.objc_section_sentinel* @__start___objc_constant_string, %.objc_section_sentinel* @__stop__objc_constant_string }, comdat, align 8
|
||||
|
||||
// Make sure our init variable is in the correct section for late library init.
|
||||
// CHECK-WIN: @.objc_ctor = linkonce hidden constant void ()* @.objcv2_load_function, section ".CRT$XCLz", comdat
|
||||
|
||||
// We shouldn't have emitted any null placeholders on Windows.
|
||||
// CHECK-WIN: @llvm.used = appending global [2 x i8*] [i8* bitcast ({ { i8*, i8*, i8*, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8* }*, i8*, i8*, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8* }** @._OBJC_INIT_CLASS_X to i8*), i8* bitcast (void ()** @.objc_ctor to i8*)], section "llvm.metadata"
|
||||
// CHECK-WIN: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @.objcv2_load_function to i8*)], section "llvm.metadata"
|
||||
|
||||
// Check our load function is in a comdat.
|
||||
// CHECK-WIN: define linkonce_odr hidden void @.objcv2_load_function() comdat {
|
||||
|
||||
// Make sure we have dllimport on the load function
|
||||
// CHECK-WIN: declare dllimport void @__objc_load
|
||||
|
||||
|
@ -22,11 +22,11 @@
|
||||
|
||||
// Check that we're emitting the protocol and a correctly initialised
|
||||
// indirection variable.
|
||||
// CHECK: @._OBJC_PROTOCOL_X = global
|
||||
// CHECK: @._OBJC_PROTOCOL_X = global
|
||||
// CHECK-SAME: , section "__objc_protocols", comdat, align 8
|
||||
// CHECK: @._OBJC_REF_PROTOCOL_X = global
|
||||
// CHECK: @._OBJC_REF_PROTOCOL_X = linkonce_odr global
|
||||
// CHECK-SAME: @._OBJC_PROTOCOL_X
|
||||
// CHECK-SAME: , section "__objc_protocol_refs", align 8
|
||||
// CHECK-SAME: , section "__objc_protocol_refs", comdat, align 8
|
||||
|
||||
|
||||
// Check that we load from the indirection variable on protocol references.
|
||||
|
@ -10,7 +10,7 @@ void g() {
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: call i8* @"?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ]
|
||||
// CHECK: call i8* @"?f@@YAPAU.objc_object@@XZ"() [ "funclet"(token %1) ]
|
||||
// CHECK-NEXT: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]
|
||||
|
||||
// The corresponding f() call was invoked from the entry basic block.
|
||||
|
@ -9,7 +9,7 @@ struct A {
|
||||
|
||||
// Verify that we destruct things from left to right in the MS C++ ABI: a, b, c, d.
|
||||
//
|
||||
// CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAUobjc_object@@01@Z"
|
||||
// CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAU.objc_object@@01@Z"
|
||||
// CHECK: (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca)
|
||||
void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) {
|
||||
// CHECK: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* %{{.*}})
|
||||
|
@ -6,61 +6,61 @@
|
||||
@class I;
|
||||
|
||||
void f(id<P>, id, id<P>, id) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@PAUobjc_object@@01@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@PAU.objc_object@@01@Z"
|
||||
|
||||
void f(id, id<P>, id<P>, id) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAUobjc_object@@PAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU.objc_object@@PAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z"
|
||||
|
||||
void f(id<P>, id<P>) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z"
|
||||
|
||||
void f(id<P>) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(id<P, Q>) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
|
||||
void f(Class<P>) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(Class<P, Q>) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
|
||||
void f(I<P> *) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_cls_I@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(I<P, Q> *) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU?$.objc_cls_I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
|
||||
template <typename>
|
||||
struct S {};
|
||||
|
||||
void f(S<__unsafe_unretained id>) {}
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@PAUobjc_object@@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@PAU.objc_object@@@@@Z"
|
||||
|
||||
void f(S<__autoreleasing id>) {}
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@U?$Autoreleasing@PAU.objc_object@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(S<__strong id>) {}
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAUobjc_object@@@__ObjC@@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@U?$Strong@PAU.objc_object@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(S<__weak id>) {}
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAUobjc_object@@@__ObjC@@@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXU?$S@U?$Weak@PAU.objc_object@@@__ObjC@@@@@Z"
|
||||
|
||||
void w(__weak id) {}
|
||||
// CHECK-LABEL: "?w@@YAXPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?w@@YAXPAU.objc_object@@@Z"
|
||||
|
||||
void s(__strong id) {}
|
||||
// CHECK-LABEL: "?s@@YAXPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?s@@YAXPAU.objc_object@@@Z"
|
||||
|
||||
void a(__autoreleasing id) {}
|
||||
// CHECK-LABEL: "?a@@YAXPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?a@@YAXPAU.objc_object@@@Z"
|
||||
|
||||
void u(__unsafe_unretained id) {}
|
||||
// CHECK-LABEL: "?u@@YAXPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?u@@YAXPAU.objc_object@@@Z"
|
||||
|
||||
S<__autoreleasing id> g() { return S<__autoreleasing id>(); }
|
||||
// CHECK-LABEL: "?g@@YA?AU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@XZ"
|
||||
// CHECK-LABEL: "?g@@YA?AU?$S@U?$Autoreleasing@PAU.objc_object@@@__ObjC@@@@XZ"
|
||||
|
||||
__autoreleasing id h() { return nullptr; }
|
||||
// CHECK-LABEL: "?h@@YAPAUobjc_object@@XZ"
|
||||
// CHECK-LABEL: "?h@@YAPAU.objc_object@@XZ"
|
||||
|
@ -3,166 +3,166 @@
|
||||
@class I;
|
||||
|
||||
id kid;
|
||||
// CHECK: @"?kid@@3PAUobjc_object@@A" = dso_local global
|
||||
// CHECK: @"?kid@@3PAU.objc_object@@A" = dso_local global
|
||||
|
||||
Class klass;
|
||||
// CHECK: @"?klass@@3PAUobjc_class@@A" = dso_local global
|
||||
// CHECK: @"?klass@@3PAU.objc_class@@A" = dso_local global
|
||||
|
||||
I *kI;
|
||||
// CHECK: @"?kI@@3PAUI@@A" = dso_local global
|
||||
// CHECK: @"?kI@@3PAU.objc_cls_I@@A" = dso_local global
|
||||
|
||||
void f(I *) {}
|
||||
// CHECK-LABEL: "?f@@YAXPAUI@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPAU.objc_cls_I@@@Z"
|
||||
|
||||
void f(const I *) {}
|
||||
// CHECK-LABEL: "?f@@YAXPBUI@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXPBU.objc_cls_I@@@Z"
|
||||
|
||||
void f(I &) {}
|
||||
// CHECK-LABEL: "?f@@YAXAAUI@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXAAU.objc_cls_I@@@Z"
|
||||
|
||||
void f(const I &) {}
|
||||
// CHECK-LABEL: "?f@@YAXABUI@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAXABU.objc_cls_I@@@Z"
|
||||
|
||||
void f(const I &&) {}
|
||||
// CHECK-LABEL: "?f@@YAX$$QBUI@@@Z"
|
||||
// CHECK-LABEL: "?f@@YAX$$QBU.objc_cls_I@@@Z"
|
||||
|
||||
void g(id) {}
|
||||
// CHECK-LABEL: "?g@@YAXPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?g@@YAXPAU.objc_object@@@Z"
|
||||
|
||||
void g(id &) {}
|
||||
// CHECK-LABEL: "?g@@YAXAAPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?g@@YAXAAPAU.objc_object@@@Z"
|
||||
|
||||
void g(const id &) {}
|
||||
// CHECK-LABEL: "?g@@YAXABQAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?g@@YAXABQAU.objc_object@@@Z"
|
||||
|
||||
void g(id &&) {}
|
||||
// CHECK-LABEL: "?g@@YAX$$QAPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?g@@YAX$$QAPAU.objc_object@@@Z"
|
||||
|
||||
void h(Class) {}
|
||||
// CHECK-LABEL: "?h@@YAXPAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?h@@YAXPAU.objc_class@@@Z"
|
||||
|
||||
void h(Class &) {}
|
||||
// CHECK-LABEL: "?h@@YAXAAPAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?h@@YAXAAPAU.objc_class@@@Z"
|
||||
|
||||
void h(const Class &) {}
|
||||
// CHECK-LABEL: "?h@@YAXABQAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?h@@YAXABQAU.objc_class@@@Z"
|
||||
|
||||
void h(Class &&) {}
|
||||
// CHECK-LABEL: "?h@@YAX$$QAPAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?h@@YAX$$QAPAU.objc_class@@@Z"
|
||||
|
||||
I *i() { return nullptr; }
|
||||
// CHECK-LABEL: "?i@@YAPAUI@@XZ"
|
||||
// CHECK-LABEL: "?i@@YAPAU.objc_cls_I@@XZ"
|
||||
|
||||
const I *j() { return nullptr; }
|
||||
// CHECK-LABEL: "?j@@YAPBUI@@XZ"
|
||||
// CHECK-LABEL: "?j@@YAPBU.objc_cls_I@@XZ"
|
||||
|
||||
I &k() { return *kI; }
|
||||
// CHECK-LABEL: "?k@@YAAAUI@@XZ"
|
||||
// CHECK-LABEL: "?k@@YAAAU.objc_cls_I@@XZ"
|
||||
|
||||
const I &l() { return *kI; }
|
||||
// CHECK-LABEL: "?l@@YAABUI@@XZ"
|
||||
// CHECK-LABEL: "?l@@YAABU.objc_cls_I@@XZ"
|
||||
|
||||
void m(const id) {}
|
||||
// CHECK-LABEL: "?m@@YAXQAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?m@@YAXQAU.objc_object@@@Z"
|
||||
|
||||
void m(const I *) {}
|
||||
// CHECK-LABEL: "?m@@YAXPBUI@@@Z"
|
||||
// CHECK-LABEL: "?m@@YAXPBU.objc_cls_I@@@Z"
|
||||
|
||||
void n(SEL) {}
|
||||
// CHECK-LABEL: "?n@@YAXPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?n@@YAXPAU.objc_selector@@@Z"
|
||||
|
||||
void n(SEL *) {}
|
||||
// CHECK-LABEL: "?n@@YAXPAPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?n@@YAXPAPAU.objc_selector@@@Z"
|
||||
|
||||
void n(const SEL *) {}
|
||||
// CHECK-LABEL: "?n@@YAXPBQAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?n@@YAXPBQAU.objc_selector@@@Z"
|
||||
|
||||
void n(SEL &) {}
|
||||
// CHECK-LABEL: "?n@@YAXAAPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?n@@YAXAAPAU.objc_selector@@@Z"
|
||||
|
||||
void n(const SEL &) {}
|
||||
// CHECK-LABEL: "?n@@YAXABQAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?n@@YAXABQAU.objc_selector@@@Z"
|
||||
|
||||
void n(SEL &&) {}
|
||||
// CHECK-LABEL: "?n@@YAX$$QAPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?n@@YAX$$QAPAU.objc_selector@@@Z"
|
||||
|
||||
struct __declspec(dllexport) s {
|
||||
struct s &operator=(const struct s &) = delete;
|
||||
|
||||
void m(I *) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAUI@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAU.objc_cls_I@@@Z"
|
||||
|
||||
void m(const I *) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPBUI@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPBU.objc_cls_I@@@Z"
|
||||
|
||||
void m(I &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAUI@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAU.objc_cls_I@@@Z"
|
||||
|
||||
void m(const I &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXABUI@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXABU.objc_cls_I@@@Z"
|
||||
|
||||
void m(I &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAUI@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAU.objc_cls_I@@@Z"
|
||||
|
||||
void m(const I &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBUI@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBU.objc_cls_I@@@Z"
|
||||
|
||||
void m(id) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAU.objc_object@@@Z"
|
||||
|
||||
void m(id &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAPAU.objc_object@@@Z"
|
||||
|
||||
void m(id &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAPAU.objc_object@@@Z"
|
||||
|
||||
void m(const id &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXABQAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXABQAU.objc_object@@@Z"
|
||||
|
||||
void m(const id &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_object@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBQAU.objc_object@@@Z"
|
||||
|
||||
void m(Class *) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAPAU.objc_class@@@Z"
|
||||
|
||||
void m(const Class *) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPBQAU.objc_class@@@Z"
|
||||
|
||||
void m(Class) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAU.objc_class@@@Z"
|
||||
|
||||
void m(Class &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAPAU.objc_class@@@Z"
|
||||
|
||||
void m(const Class &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXABQAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXABQAU.objc_class@@@Z"
|
||||
|
||||
void m(Class &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAPAU.objc_class@@@Z"
|
||||
|
||||
void m(const Class &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_class@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBQAU.objc_class@@@Z"
|
||||
|
||||
void m(SEL) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAU.objc_selector@@@Z"
|
||||
|
||||
void m(SEL *) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPAPAU.objc_selector@@@Z"
|
||||
|
||||
void m(const SEL *) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXPBQAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXPBQAU.objc_selector@@@Z"
|
||||
|
||||
void m(SEL &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXAAPAU.objc_selector@@@Z"
|
||||
|
||||
void m(const SEL &) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAXABQAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAXABQAU.objc_selector@@@Z"
|
||||
|
||||
void m(SEL &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAPAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QAPAU.objc_selector@@@Z"
|
||||
|
||||
void m(const SEL &&) {}
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBQAUobjc_selector@@@Z"
|
||||
// CHECK-LABEL: "?m@s@@QAAX$$QBQAU.objc_selector@@@Z"
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -179,14 +179,14 @@ struct t {
|
||||
};
|
||||
|
||||
template struct t<id>;
|
||||
// CHECK-LABEL: "??0?$t@PAUobjc_object@@@@QAA@XZ"
|
||||
// CHECK-LABEL: "??0?$t@PAU.objc_object@@@@QAA@XZ"
|
||||
|
||||
template struct t<remove_pointer<id>::type>;
|
||||
// CHECK-LABEL: "??0?$t@Uobjc_object@@@@QAA@XZ"
|
||||
// CHECK-LABEL: "??0?$t@U.objc_object@@@@QAA@XZ"
|
||||
|
||||
template struct t<SEL>;
|
||||
// CHECK-LABEL: "??0?$t@PAUobjc_selector@@@@QAA@XZ"
|
||||
// CHECK-LABEL: "??0?$t@PAU.objc_selector@@@@QAA@XZ"
|
||||
|
||||
template struct t<remove_pointer<SEL>::type>;
|
||||
// CHECK-LABEL: "??0?$t@Uobjc_selector@@@@QAA@XZ"
|
||||
// CHECK-LABEL: "??0?$t@U.objc_selector@@@@QAA@XZ"
|
||||
|
||||
|
@ -51,4 +51,13 @@
|
||||
// RUN: -c -### %s 2>&1 \
|
||||
// RUN: | FileCheck %s -check-prefix=AVAILABLE
|
||||
//
|
||||
// Check that passing -faligned-allocation or -fno-aligned-allocation stops the
|
||||
// driver from passing -faligned-alloc-unavailable to cc1.
|
||||
//
|
||||
// RUN: %clang -target x86_64-apple-macosx10.12 -faligned-allocation -c -### %s 2>&1 \
|
||||
// RUN: | FileCheck %s -check-prefix=AVAILABLE
|
||||
//
|
||||
// RUN: %clang -target x86_64-apple-macosx10.12 -fno-aligned-allocation -c -### %s 2>&1 \
|
||||
// RUN: | FileCheck %s -check-prefix=AVAILABLE
|
||||
|
||||
// AVAILABLE-NOT: "-faligned-alloc-unavailable"
|
||||
|
23
test/Lexer/aligned-allocation.cpp
Normal file
23
test/Lexer/aligned-allocation.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \
|
||||
// RUN: -DEXPECT_DEFINED
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \
|
||||
// RUN: -faligned-alloc-unavailable
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++17 -verify %s \
|
||||
// RUN: -faligned-allocation -faligned-alloc-unavailable
|
||||
|
||||
// Test that __cpp_aligned_new is not defined when CC1 is passed
|
||||
// -faligned-alloc-unavailable by the Darwin driver, even when aligned
|
||||
// allocation is actually enabled.
|
||||
|
||||
// expected-no-diagnostics
|
||||
#ifdef EXPECT_DEFINED
|
||||
# ifndef __cpp_aligned_new
|
||||
# error "__cpp_aligned_new" should be defined
|
||||
# endif
|
||||
#else
|
||||
# ifdef __cpp_aligned_new
|
||||
# error "__cpp_aligned_new" should not be defined
|
||||
# endif
|
||||
#endif
|
@ -150,11 +150,35 @@ struct SSSTt {
|
||||
// CHECK: #pragma omp end declare target
|
||||
// CHECK: int b;
|
||||
|
||||
#pragma omp declare target
|
||||
template <typename T>
|
||||
T baz() { return T(); }
|
||||
#pragma omp end declare target
|
||||
|
||||
template <>
|
||||
int baz() { return 1; }
|
||||
|
||||
// CHECK: #pragma omp declare target
|
||||
// CHECK: template <typename T> T baz() {
|
||||
// CHECK: return T();
|
||||
// CHECK: }
|
||||
// CHECK: #pragma omp end declare target
|
||||
// CHECK: #pragma omp declare target
|
||||
// CHECK: template<> float baz<float>() {
|
||||
// CHECK: return float();
|
||||
// CHECK: }
|
||||
// CHECK: template<> int baz<int>() {
|
||||
// CHECK: return 1;
|
||||
// CHECK: }
|
||||
// CHECK: #pragma omp end declare target
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
foo();
|
||||
foo_c();
|
||||
foo_cpp();
|
||||
test1();
|
||||
baz<float>();
|
||||
baz<int>();
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -19,17 +19,19 @@ void foo();
|
||||
// CHECK-LABEL: @main()
|
||||
int main() {
|
||||
int i;
|
||||
// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]],
|
||||
// CHECK: [[DIMS:%.+]] = alloca [1 x [[KMP_DIM]]],
|
||||
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
|
||||
// CHECK: icmp
|
||||
// CHECK-NEXT: br i1 %
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
|
||||
// CHECK: [[CAST:%.+]] = bitcast [1 x [[KMP_DIM]]]* [[DIMS]] to i8*
|
||||
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
|
||||
// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
|
||||
// CHECK: store i64 %{{.+}}, i64* %
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
|
||||
// CHECK: store i64 1, i64* %
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
|
||||
// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
|
||||
// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
#pragma omp for ordered(1)
|
||||
@ -37,18 +39,26 @@ int main() {
|
||||
a[i] = b[i] + 1;
|
||||
foo();
|
||||
// CHECK: call void [[FOO:.+]](
|
||||
// CHECK: load i32, i32* [[CNT:%.+]],
|
||||
// CHECK: load i32, i32* [[I:%.+]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
#pragma omp ordered depend(source)
|
||||
c[i] = c[i] + 1;
|
||||
foo();
|
||||
// CHECK: call void [[FOO]]
|
||||
// CHECK: load i32, i32* [[CNT]],
|
||||
// CHECK: load i32, i32* [[I]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
#pragma omp ordered depend(sink : i - 2)
|
||||
d[i] = a[i - 2];
|
||||
|
@ -19,17 +19,19 @@ void foo();
|
||||
// CHECK-LABEL: @main()
|
||||
int main() {
|
||||
int i;
|
||||
// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]],
|
||||
// CHECK: [[DIMS:%.+]] = alloca [1 x [[KMP_DIM]]],
|
||||
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
|
||||
// CHECK: icmp
|
||||
// CHECK-NEXT: br i1 %
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
|
||||
// CHECK: [[CAST:%.+]] = bitcast [1 x [[KMP_DIM]]]* [[DIMS]] to i8*
|
||||
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
|
||||
// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
|
||||
// CHECK: store i64 %{{.+}}, i64* %
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
|
||||
// CHECK: store i64 1, i64* %
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
|
||||
// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
|
||||
// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
#pragma omp for ordered(1)
|
||||
@ -37,18 +39,26 @@ int main() {
|
||||
a[i] = b[i] + 1;
|
||||
foo();
|
||||
// CHECK: invoke void [[FOO:.+]](
|
||||
// CHECK: load i32, i32* [[CNT:%.+]],
|
||||
// CHECK: load i32, i32* [[I:%.+]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
#pragma omp ordered depend(source)
|
||||
c[i] = c[i] + 1;
|
||||
foo();
|
||||
// CHECK: invoke void [[FOO]]
|
||||
// CHECK: load i32, i32* [[CNT]],
|
||||
// CHECK: load i32, i32* [[I]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
#pragma omp ordered depend(sink : i - 2)
|
||||
d[i] = a[i - 2];
|
||||
@ -75,41 +85,84 @@ struct TestStruct {
|
||||
T bar(T, T, T);
|
||||
void baz(T, T);
|
||||
TestStruct() {
|
||||
// CHECK: [[CNT:%.+]] = alloca i64,
|
||||
// CHECK: [[DIMS:%.+]] = alloca [[KMP_DIM]],
|
||||
// CHECK: [[DIMS:%.+]] = alloca [2 x [[KMP_DIM]]],
|
||||
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
|
||||
// CHECK: icmp
|
||||
// CHECK-NEXT: br i1 %
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
|
||||
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 1
|
||||
// CHECK: store i64 %{{.+}}, i64* %
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIMS]], i32 0, i32 2
|
||||
// CHECK: [[CAST:%.+]] = bitcast [2 x [[KMP_DIM]]]* [[DIMS]] to i8*
|
||||
// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 48, i1 false)
|
||||
// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
|
||||
// CHECK: store i64 10, i64* %
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
|
||||
// CHECK: store i64 1, i64* %
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIMS]] to i8*
|
||||
// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
|
||||
// CHECK: call void @__kmpc_for_static_init_8(
|
||||
// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 1
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
|
||||
// CHECK: store i64 %{{.+}}, i64* %
|
||||
// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
|
||||
// CHECK: store i64 1, i64* %
|
||||
// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
|
||||
// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
|
||||
// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 2, i8* [[CAST]])
|
||||
// CHECK: call void @__kmpc_for_static_init_4(
|
||||
#pragma omp for ordered(2)
|
||||
for (T j = 0; j < M; j++)
|
||||
for (i = 0; i < n; i += 2) {
|
||||
a[i][j] = foo(i, j);
|
||||
// CHECK: invoke {{.+TestStruct.+foo}}
|
||||
// CHECK: load i64, i64* [[CNT]],
|
||||
// CHECK-NEXT: sub nsw i64 %{{.+}}, 1
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
// CHECK-NEXT: load i64, i64* [[CNT]],
|
||||
// CHECK-NEXT: load i32, i32* %
|
||||
// CHECK-NEXT: mul nsw i32 1, %
|
||||
// CHECK: load i32*, i32** %
|
||||
// CHECK: load i32, i32* %
|
||||
// CHECK: load i32, i32* %
|
||||
// CHECK: load i32, i32* [[J:%.+]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: sub nsw i64 %
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF:%.+]],
|
||||
// CHECK-NEXT: load i32, i32* [[I]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 2
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
// CHECK-NEXT: load i32, i32* [[J:%.+]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]],
|
||||
// CHECK-NEXT: load i32, i32* [[I]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 2
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
#pragma omp ordered depend(sink : j, i - 2) depend(sink : j - 1, i)
|
||||
b[i][j] = bar(a[i][j], b[i - 1][j], b[i][j - 1]);
|
||||
// CHECK: invoke {{.+TestStruct.+bar}}
|
||||
// CHECK: load i64, i64* [[CNT]],
|
||||
// CHECK: load i32*, i32** %
|
||||
// CHECK: load i32, i32* %
|
||||
// CHECK: load i32, i32* %
|
||||
// CHECK: load i32, i32* [[J]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 1
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
|
||||
// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]],
|
||||
// CHECK-NEXT: load i32, i32* [[I]],
|
||||
// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
|
||||
// CHECK-NEXT: sdiv i32 %{{.+}}, 2
|
||||
// CHECK-NEXT: sext i32 %{{.+}} to i64
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
|
||||
// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
|
||||
// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
|
||||
// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
|
||||
#pragma omp ordered depend(source)
|
||||
baz(a[i][j], b[i][j]);
|
||||
|
@ -48,7 +48,7 @@ class S8 : public S7<S1> {
|
||||
|
||||
public:
|
||||
S8(int v) : S7<S1>(v){
|
||||
#pragma omp parallel for simd private(a) private(this->a) private(S7<S1>::a)
|
||||
#pragma omp parallel for simd private(a) private(this->a) private(S7 <S1>::a)
|
||||
for (int k = 0; k < a.a; ++k)
|
||||
++this->a.a;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
// RUN: clang-diff -ast-dump-json %s -- \
|
||||
// RUN: | '%python' -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
|
||||
// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
|
||||
// RUN: | FileCheck %s
|
||||
|
||||
// CHECK: "begin": 301,
|
||||
// CHECK: "begin": 311,
|
||||
// CHECK: "type": "FieldDecl",
|
||||
// CHECK: "end": 321,
|
||||
// CHECK: "end": 319,
|
||||
// CHECK: "type": "CXXRecordDecl",
|
||||
class A {
|
||||
int x;
|
||||
|
Loading…
x
Reference in New Issue
Block a user