Skip to content

Commit 042aeee

Browse files
committed
First impl. pragma oss assert
Closes llvm#80
1 parent c2ae418 commit 042aeee

28 files changed

+406
-7
lines changed

clang/include/clang/AST/DeclOmpSs.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,65 @@ class OSSDeclareReductionDecl final : public ValueDecl, public DeclContext {
141141
}
142142
};
143143

144+
/// This represents '#pragma oss assert ...' directive.
145+
///
146+
/// \code
147+
/// #pragma oss assert("stacksize=4M")
148+
/// int main() {}
149+
/// \endcode
150+
///
151+
class OSSAssertDecl final
152+
: public Decl, private llvm::TrailingObjects<OSSAssertDecl, Expr *> {
153+
friend class ASTDeclReader;
154+
friend TrailingObjects;
155+
156+
unsigned NumVars;
157+
158+
virtual void anchor();
159+
160+
OSSAssertDecl(Kind DK, DeclContext *DC, SourceLocation L) :
161+
Decl(DK, DC, L), NumVars(0) { }
162+
163+
ArrayRef<const Expr *> getVars() const {
164+
return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
165+
}
166+
167+
MutableArrayRef<Expr *> getVars() {
168+
return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
169+
}
170+
171+
void setVars(ArrayRef<Expr *> VL);
172+
173+
public:
174+
static OSSAssertDecl *Create(
175+
ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef<Expr *> VL);
176+
177+
static OSSAssertDecl *CreateDeserialized(
178+
ASTContext &C, unsigned ID, unsigned N);
179+
180+
typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
181+
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
182+
typedef llvm::iterator_range<varlist_iterator> varlist_range;
183+
typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
184+
185+
unsigned varlist_size() const { return NumVars; }
186+
bool varlist_empty() const { return NumVars == 0; }
187+
188+
varlist_range varlists() {
189+
return varlist_range(varlist_begin(), varlist_end());
190+
}
191+
varlist_const_range varlists() const {
192+
return varlist_const_range(varlist_begin(), varlist_end());
193+
}
194+
varlist_iterator varlist_begin() { return getVars().begin(); }
195+
varlist_iterator varlist_end() { return getVars().end(); }
196+
varlist_const_iterator varlist_begin() const { return getVars().begin(); }
197+
varlist_const_iterator varlist_end() const { return getVars().end(); }
198+
199+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
200+
static bool classofKind(Kind K) { return K == OSSAssert; }
201+
};
202+
144203
} // end namespace clang
145204

146205
#endif

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,7 @@ DEF_TRAVERSE_DECL(OMPRequiresDecl, {
16091609
}
16101610
})
16111611

1612+
// OmpSs-2
16121613
DEF_TRAVERSE_DECL(OSSDeclareReductionDecl, {
16131614
TRY_TO(TraverseStmt(D->getCombiner()));
16141615
if (auto *Initializer = D->getInitializer())
@@ -1617,6 +1618,12 @@ DEF_TRAVERSE_DECL(OSSDeclareReductionDecl, {
16171618
return true;
16181619
})
16191620

1621+
DEF_TRAVERSE_DECL(OSSAssertDecl, {
1622+
for (auto *I : D->varlists()) {
1623+
TRY_TO(TraverseStmt(I));
1624+
}
1625+
})
1626+
16201627
DEF_TRAVERSE_DECL(OMPDeclareReductionDecl, {
16211628
TRY_TO(TraverseStmt(D->getCombiner()));
16221629
if (auto *Initializer = D->getInitializer())

clang/include/clang/Basic/DeclNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def Block : DeclNode<Decl, "blocks">, DeclContext;
9999
def Captured : DeclNode<Decl>, DeclContext;
100100
def ClassScopeFunctionSpecialization : DeclNode<Decl>;
101101
def Import : DeclNode<Decl>;
102+
def OSSAssert : DeclNode<Decl>;
102103
def OMPThreadPrivate : DeclNode<Decl>;
103104
def OMPAllocate : DeclNode<Decl>;
104105
def OMPRequires : DeclNode<Decl>;

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,8 @@ def err_oss_expected_multidep_iterator_identifier : Error<
12691269
"expected iterator identifier">;
12701270
def err_oss_expected_multidep_separator : Error<
12711271
"expected ':'%select{| or ';'}0">;
1272+
def err_oss_expected_string_literal : Error<
1273+
"expected string literal">;
12721274

12731275
// OpenMP support.
12741276
def warn_pragma_omp_ignored : Warning<

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10971,6 +10971,8 @@ def err_oss_loop_not_canonical_incr : Error<
1097110971
def err_oss_wrong_var_in_declare_reduction : Error<"only %select{'omp_priv' or 'omp_orig'|'omp_in' or 'omp_out'}0 variables are allowed in %select{initializer|combiner}0 expression">;
1097210972
def err_oss_multidep_discrete_empty : Error<
1097310973
"expected a non-empty list">;
10974+
def err_oss_invalid_scope : Error <
10975+
"'#pragma oss %0' directive must appear only in file scope">;
1097410976
} // end of OmpSs component.
1097510977

1097610978

clang/include/clang/Basic/OmpSsKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ OMPSS_DIRECTIVE(task)
5757
OMPSS_DIRECTIVE(taskloop)
5858
OMPSS_DIRECTIVE(taskwait)
5959
OMPSS_DIRECTIVE(release)
60+
OMPSS_DIRECTIVE(assert)
6061

6162
// OmpSs clauses.
6263
OMPSS_CLAUSE(if, OSSIfClause)

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ namespace clang {
166166
class OMPRequiresDecl;
167167
class OMPDeclareReductionDecl;
168168
class OMPDeclareSimdDecl;
169+
class OSSAssertDecl;
169170
class OSSDeclareReductionDecl;
170171
class OSSTaskDecl;
171172
class OMPClause;
@@ -11163,6 +11164,9 @@ class Sema final {
1116311164
ArrayRef<Expr *> MultiDepSteps, ArrayRef<bool> MultiDepSizeOrSection,
1116411165
Expr *DepExpr);
1116511166

11167+
/// Called on well-formed '#pragma oss assert'.
11168+
DeclGroupPtrTy ActOnOmpSsAssertDirective(SourceLocation Loc, Expr *E);
11169+
1116611170
/// Check if the specified type is allowed to be used in 'oss declare
1116711171
/// reduction' construct.
1116811172
QualType ActOnOmpSsDeclareReductionType(SourceLocation TyLoc,

clang/lib/AST/ASTContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10599,7 +10599,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
1059910599
return true;
1060010600
else if (isa<PragmaDetectMismatchDecl>(D))
1060110601
return true;
10602-
else if (isa<OMPRequiresDecl>(D))
10602+
else if (isa<OMPRequiresDecl>(D) || isa<OSSAssertDecl>(D))
1060310603
return true;
1060410604
else if (isa<OMPThreadPrivateDecl>(D))
1060510605
return !D->getDeclContext()->isDependentContext();

clang/lib/AST/DeclBase.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
852852
case ObjCCategory:
853853
case ObjCCategoryImpl:
854854
case Import:
855+
case OSSAssert:
855856
case OMPThreadPrivate:
856857
case OMPAllocate:
857858
case OMPRequires:

clang/lib/AST/DeclOmpSs.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,32 @@ OSSDeclareReductionDecl::getPrevDeclInScope() const {
5757
PrevDeclInScope.get(getASTContext().getExternalSource()));
5858
}
5959

60+
//===----------------------------------------------------------------------===//
61+
// OSSAssertDecl Implementation.
62+
//===----------------------------------------------------------------------===//
63+
64+
void OSSAssertDecl::anchor() { }
65+
66+
OSSAssertDecl *OSSAssertDecl::Create(
67+
ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef<Expr *> VL) {
68+
OSSAssertDecl *D =
69+
new (C, DC, additionalSizeToAlloc<Expr *>(VL.size()))
70+
OSSAssertDecl(OSSAssert, DC, L);
71+
D->NumVars = VL.size();
72+
D->setVars(VL);
73+
return D;
74+
}
75+
76+
OSSAssertDecl *OSSAssertDecl::CreateDeserialized(
77+
ASTContext &C, unsigned ID, unsigned N) {
78+
OSSAssertDecl *D = new (C, ID, additionalSizeToAlloc<Expr *>(N))
79+
OSSAssertDecl(OSSAssert, nullptr, SourceLocation());
80+
D->NumVars = N;
81+
return D;
82+
}
83+
84+
void OSSAssertDecl::setVars(ArrayRef<Expr *> VL) {
85+
assert(VL.size() == NumVars &&
86+
"Number of variables is not the same as the preallocated buffer");
87+
std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>());
88+
}

clang/lib/AST/DeclPrinter.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ namespace {
107107
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
108108
// OmpSs
109109
void VisitOSSDeclareReductionDecl(OSSDeclareReductionDecl *D);
110+
void VisitOSSAssertDecl(OSSAssertDecl *D);
111+
110112
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);
111113
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);
112114

@@ -443,7 +445,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
443445
if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) ||
444446
isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) ||
445447
isa<OMPAllocateDecl>(*D) ||
446-
isa<OSSDeclareReductionDecl>(*D))
448+
isa<OSSDeclareReductionDecl>(*D) ||
449+
isa<OSSAssertDecl>(*D))
447450
Terminator = nullptr;
448451
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
449452
Terminator = nullptr;
@@ -1736,6 +1739,20 @@ void DeclPrinter::VisitOSSDeclareReductionDecl(OSSDeclareReductionDecl *D) {
17361739
}
17371740
}
17381741

1742+
void DeclPrinter::VisitOSSAssertDecl(OSSAssertDecl *D) {
1743+
Out << "#pragma oss assert";
1744+
if (!D->varlist_empty()) {
1745+
for (OSSAssertDecl::varlist_iterator I = D->varlist_begin(),
1746+
E = D->varlist_end();
1747+
I != E; ++I) {
1748+
Out << (I == D->varlist_begin() ? '(' : ',');
1749+
StringLiteral *SL = cast<StringLiteral>(*I);
1750+
SL->printPretty(Out, nullptr, Policy, Indentation);
1751+
}
1752+
Out << ")";
1753+
}
1754+
}
1755+
17391756
void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
17401757
if (const TypeConstraint *TC = TTP->getTypeConstraint())
17411758
TC->print(Out, Policy);

clang/lib/Basic/OmpSsKinds.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ bool clang::isAllowedClauseForDirective(OmpSsDirectiveKind DKind,
239239
}
240240
break;
241241
case OSSD_declare_reduction:
242+
case OSSD_assert:
242243
case OSSD_unknown:
243244
break;
244245
}

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
123123
case Decl::OMPCapturedExpr:
124124
case Decl::OMPRequires:
125125
case Decl::OSSDeclareReduction:
126+
case Decl::OSSAssert:
126127
case Decl::Empty:
127128
case Decl::Concept:
128129
case Decl::LifetimeExtendedTemporary:
@@ -2586,3 +2587,17 @@ void CodeGenModule::EmitOMPDeclareMapper(const OMPDeclareMapperDecl *D,
25862587
void CodeGenModule::EmitOMPRequiresDecl(const OMPRequiresDecl *D) {
25872588
getOpenMPRuntime().processRequiresDirective(D);
25882589
}
2590+
2591+
void CodeGenModule::EmitOSSAssertDecl(const OSSAssertDecl *D) {
2592+
// Add a new assert entry to OmpSs-2 metadata
2593+
llvm::Metadata *Key = llvm::MDString::get(getLLVMContext(), "assert");
2594+
SmallVector<llvm::Metadata *, 4> List;
2595+
for (OSSAssertDecl::varlist_const_iterator I = D->varlist_begin(),
2596+
E = D->varlist_end();
2597+
I != E; ++I) {
2598+
const StringLiteral *SL = cast<StringLiteral>(*I);
2599+
llvm::Metadata *Value = llvm::MDString::get(getLLVMContext(), SL->getString());
2600+
List.push_back(llvm::MDTuple::get(getLLVMContext(), {Key, Value}));
2601+
}
2602+
getOmpSsRuntime().addMetadata(List);
2603+
}

clang/lib/CodeGen/CGOmpSsRuntime.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,3 +2915,13 @@ void CGOmpSsRuntime::emitLoopCall(CodeGenFunction &CGF,
29152915
TaskAllocaInsertPt->eraseFromParent();
29162916

29172917
}
2918+
2919+
void CGOmpSsRuntime::addMetadata(ArrayRef<llvm::Metadata *> List) {
2920+
MetadataList.append(List.begin(), List.end());
2921+
}
2922+
2923+
llvm::MDNode *CGOmpSsRuntime::getMetadataNode() {
2924+
if (MetadataList.empty())
2925+
return nullptr;
2926+
return llvm::MDTuple::get(CGM.getLLVMContext(), MetadataList);
2927+
}

clang/lib/CodeGen/CGOmpSsRuntime.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ class CGOmpSsRuntime {
167167
using GenericCXXNonPodMethodDefsTy = llvm::DenseMap<const CXXMethodDecl *, llvm::Function *>;
168168
GenericCXXNonPodMethodDefsTy GenericCXXNonPodMethodDefs;
169169

170+
// List of OmpSs-2 specific metadata to be added to llvm.module.flags
171+
SmallVector<llvm::Metadata *, 4> MetadataList;
172+
170173
void EmitDSAShared(
171174
CodeGenFunction &CGF, const Expr *E,
172175
SmallVectorImpl<llvm::OperandBundleDef> &TaskInfo,
@@ -284,6 +287,11 @@ class CGOmpSsRuntime {
284287
const OSSTaskDataTy &Data,
285288
const OSSLoopDataTy &LoopData);
286289

290+
// Add all the metadata to OmpSs-2 metadata list.
291+
void addMetadata(ArrayRef<llvm::Metadata *> List);
292+
// Get OmpSs-2 metadata list as a single metadata node.
293+
llvm::MDNode *getMetadataNode();
294+
287295
};
288296

289297
} // namespace CodeGen

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,13 @@ void CodeGenModule::Release() {
616616
!LangOpts.isSignReturnAddressWithAKey());
617617
}
618618

619+
// Add our llvm.oss.flags to llvm.module.flags
620+
if (LangOpts.OmpSs) {
621+
if (llvm::MDNode *MDN = getOmpSsRuntime().getMetadataNode()) {
622+
getModule().addModuleFlag(llvm::Module::Error, "OmpSs-2 Metadata", MDN);
623+
}
624+
}
625+
619626
if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) {
620627
// Indicate whether __nvvm_reflect should be configured to flush denormal
621628
// floating point values to 0. (This corresponds to its "__CUDA_FTZ"
@@ -5699,6 +5706,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
56995706
case Decl::OSSDeclareReduction:
57005707
break;
57015708

5709+
case Decl::OSSAssert:
5710+
EmitOSSAssertDecl(cast<OSSAssertDecl>(D));
5711+
break;
5712+
57025713
case Decl::OMPRequires:
57035714
EmitOMPRequiresDecl(cast<OMPRequiresDecl>(D));
57045715
break;

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,10 @@ class CodeGenModule : public CodeGenTypeCache {
13261326
/// \param D Requires declaration
13271327
void EmitOMPRequiresDecl(const OMPRequiresDecl *D);
13281328

1329+
/// Emit a code for assert directive.
1330+
/// \param D Assert declaration
1331+
void EmitOSSAssertDecl(const OSSAssertDecl *D);
1332+
13291333
/// Returns whether the given record has hidden LTO visibility and therefore
13301334
/// may participate in (single-module) CFI and whole-program vtable
13311335
/// optimization.

clang/lib/Parse/ParseOmpSs.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,40 @@ Parser::DeclGroupPtrTy Parser::ParseOmpSsDeclarativeDirectiveWithExtDecl(
498498
Actions.EndOmpSsDSABlock(nullptr);
499499
return Ret;
500500
}
501+
case OSSD_assert: {
502+
ConsumeToken();
503+
504+
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_ompss_end);
505+
if (T.expectAndConsume(
506+
diag::err_expected_lparen_after, getOmpSsDirectiveName(DKind)))
507+
break;
508+
509+
bool IsCorrect = true;
510+
ExprResult Res;
511+
if (isTokenStringLiteral()) {
512+
Res = ParseStringLiteralExpression();
513+
} else {
514+
Diag(Tok, diag::err_oss_expected_string_literal);
515+
SkipUntil(tok::r_paren, StopBeforeMatch);
516+
IsCorrect = false;
517+
}
518+
519+
IsCorrect = !T.consumeClose() && Res.isUsable() && IsCorrect;
520+
521+
if (IsCorrect) {
522+
// Need to check for extra tokens.
523+
if (Tok.isNot(tok::annot_pragma_ompss_end)) {
524+
Diag(Tok, diag::warn_oss_extra_tokens_at_eol)
525+
<< getOmpSsDirectiveName(DKind);
526+
while (Tok.isNot(tok::annot_pragma_ompss_end))
527+
ConsumeAnyToken();
528+
}
529+
// Skip the last annot_pragma_ompss_end.
530+
ConsumeAnnotationToken();
531+
return Actions.ActOnOmpSsAssertDirective(Loc, Res.get());
532+
}
533+
break;
534+
}
501535
case OSSD_declare_task:
502536
case OSSD_task_for:
503537
case OSSD_taskloop:
@@ -645,6 +679,7 @@ StmtResult Parser::ParseOmpSsDeclarativeOrExecutableDirective(
645679
SkipUntil(tok::annot_pragma_ompss_end);
646680
break;
647681
case OSSD_declare_task:
682+
case OSSD_assert:
648683
Diag(Tok, diag::err_oss_unexpected_directive)
649684
<< 1 << getOmpSsDirectiveName(DKind);
650685
SkipUntil(tok::annot_pragma_ompss_end);

0 commit comments

Comments
 (0)