@@ -61,6 +61,8 @@ static constexpr llvm::StringLiteral InitESIMDMethodName = "__init_esimd";
61
61
static constexpr llvm::StringLiteral InitSpecConstantsBuffer =
62
62
" __init_specialization_constants_buffer" ;
63
63
static constexpr llvm::StringLiteral FinalizeMethodName = " __finalize" ;
64
+ static constexpr llvm::StringLiteral LibstdcxxFailedAssertion =
65
+ " __failed_assertion" ;
64
66
constexpr unsigned MaxKernelArgsSize = 2048 ;
65
67
66
68
namespace {
@@ -320,6 +322,21 @@ static bool isSYCLKernelBodyFunction(FunctionDecl *FD) {
320
322
return FD->getOverloadedOperator () == OO_Call;
321
323
}
322
324
325
+ static bool isSYCLUndefinedAllowed (const FunctionDecl *Callee,
326
+ const SourceManager &SrcMgr) {
327
+ if (!Callee)
328
+ return false ;
329
+
330
+ // libstdc++-11 introduced an undefined function "void __failed_assertion()"
331
+ // which may lead to SemaSYCL check failure. However, this undefined function
332
+ // is used to trigger some compilation error when the check fails at compile
333
+ // time and will be ignored when the check succeeds. We allow calls to this
334
+ // function to support some important std functions in SYCL device.
335
+ return (Callee->getName () == LibstdcxxFailedAssertion) &&
336
+ Callee->getNumParams () == 0 && Callee->getReturnType ()->isVoidType () &&
337
+ SrcMgr.isInSystemHeader (Callee->getLocation ());
338
+ }
339
+
323
340
// Helper function to report conflicting function attributes.
324
341
// F - the function, A1 - function attribute, A2 - the attribute it conflicts
325
342
// with.
@@ -1032,23 +1049,6 @@ class KernelObjVisitor {
1032
1049
VisitRecordFields (Owner, Handlers...);
1033
1050
}
1034
1051
1035
- // FIXME: Can this be refactored/handled some other way?
1036
- template <typename ParentTy, typename ... HandlerTys>
1037
- void visitStreamRecord (const CXXRecordDecl *Owner, ParentTy &Parent,
1038
- CXXRecordDecl *Wrapper, QualType RecordTy,
1039
- HandlerTys &... Handlers) {
1040
- (void )std::initializer_list<int >{
1041
- (Handlers.enterStream (Owner, Parent, RecordTy), 0 )...};
1042
- for (const auto &Field : Wrapper->fields ()) {
1043
- QualType FieldTy = Field->getType ();
1044
- // Required to initialize accessors inside streams.
1045
- if (Util::isSyclAccessorType (FieldTy))
1046
- KF_FOR_EACH (handleSyclAccessorType, Field, FieldTy);
1047
- }
1048
- (void )std::initializer_list<int >{
1049
- (Handlers.leaveStream (Owner, Parent, RecordTy), 0 )...};
1050
- }
1051
-
1052
1052
template <typename ... HandlerTys>
1053
1053
void visitArrayElementImpl (const CXXRecordDecl *Owner, FieldDecl *ArrayField,
1054
1054
QualType ElementTy, uint64_t Index,
@@ -1123,12 +1123,9 @@ class KernelObjVisitor {
1123
1123
KF_FOR_EACH (handleSyclHalfType, Field, FieldTy);
1124
1124
else if (Util::isSyclSpecConstantType (FieldTy))
1125
1125
KF_FOR_EACH (handleSyclSpecConstantType, Field, FieldTy);
1126
- else if (Util::isSyclStreamType (FieldTy)) {
1127
- CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
1128
- // Handle accessors in stream class.
1126
+ else if (Util::isSyclStreamType (FieldTy))
1129
1127
KF_FOR_EACH (handleSyclStreamType, Field, FieldTy);
1130
- visitStreamRecord (Owner, Field, RD, FieldTy, Handlers...);
1131
- } else if (FieldTy->isStructureOrClassType ()) {
1128
+ else if (FieldTy->isStructureOrClassType ()) {
1132
1129
if (KF_FOR_EACH (handleStructType, Field, FieldTy)) {
1133
1130
CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
1134
1131
visitRecord (Owner, Field, RD, FieldTy, Handlers...);
@@ -1242,12 +1239,6 @@ class SyclKernelFieldHandlerBase {
1242
1239
virtual bool leaveStruct (const CXXRecordDecl *, FieldDecl *, QualType) {
1243
1240
return true ;
1244
1241
}
1245
- virtual bool enterStream (const CXXRecordDecl *, FieldDecl *, QualType) {
1246
- return true ;
1247
- }
1248
- virtual bool leaveStream (const CXXRecordDecl *, FieldDecl *, QualType) {
1249
- return true ;
1250
- }
1251
1242
virtual bool enterStruct (const CXXRecordDecl *, const CXXBaseSpecifier &,
1252
1243
QualType) {
1253
1244
return true ;
@@ -1695,18 +1686,6 @@ class SyclKernelDecompMarker : public SyclKernelFieldHandler {
1695
1686
return true ;
1696
1687
}
1697
1688
1698
- // Stream is always decomposed (and whether it gets decomposed is handled in
1699
- // handleSyclStreamType), but we need a CollectionStack entry to capture the
1700
- // accessors that get handled.
1701
- bool enterStream (const CXXRecordDecl *, FieldDecl *, QualType) final {
1702
- CollectionStack.push_back (false );
1703
- return true ;
1704
- }
1705
- bool leaveStream (const CXXRecordDecl *, FieldDecl *, QualType Ty) final {
1706
- CollectionStack.pop_back ();
1707
- return true ;
1708
- }
1709
-
1710
1689
bool enterStruct (const CXXRecordDecl *, FieldDecl *, QualType) final {
1711
1690
CollectionStack.push_back (false );
1712
1691
return true ;
@@ -1954,14 +1933,6 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
1954
1933
SemaRef.addSyclDeviceDecl (KernelDecl);
1955
1934
}
1956
1935
1957
- bool enterStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
1958
- return enterStruct (RD, FD, Ty);
1959
- }
1960
-
1961
- bool leaveStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
1962
- return leaveStruct (RD, FD, Ty);
1963
- }
1964
-
1965
1936
bool enterStruct (const CXXRecordDecl *, FieldDecl *, QualType) final {
1966
1937
++StructDepth;
1967
1938
return true ;
@@ -2097,8 +2068,7 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
2097
2068
}
2098
2069
2099
2070
bool handleSyclStreamType (FieldDecl *FD, QualType FieldTy) final {
2100
- addParam (FD, FieldTy);
2101
- return true ;
2071
+ return handleSpecialType (FD, FieldTy);
2102
2072
}
2103
2073
2104
2074
bool handleSyclStreamType (const CXXRecordDecl *, const CXXBaseSpecifier &,
@@ -2417,15 +2387,6 @@ class SyclOptReportCreator : public SyclKernelFieldHandler {
2417
2387
}
2418
2388
2419
2389
bool handleSyclStreamType (FieldDecl *FD, QualType FieldTy) final {
2420
- // For the current implementation of stream class, the Visitor 'handles'
2421
- // stream argument and then visits each accessor field in stream. Therefore
2422
- // handleSpecialType in this case only adds a single argument for stream.
2423
- // The arguments corresponding to accessors in stream are handled in
2424
- // handleSyclAccessorType. The opt-report therefore does not diffrentiate
2425
- // between the accessors in streams and accessors captured by SYCL kernel.
2426
- // Once stream API is modified to use __init(), the visitor will no longer
2427
- // visit the stream object and opt-report output for stream class will be
2428
- // similar to that of other special types.
2429
2390
return handleSpecialType (
2430
2391
FD, FieldTy, KernelArgDescription (KernelArgDescription::Stream));
2431
2392
}
@@ -2803,6 +2764,13 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler {
2803
2764
2804
2765
const auto *RecordDecl = Ty->getAsCXXRecordDecl ();
2805
2766
createSpecialMethodCall (RecordDecl, getInitMethodName (), BodyStmts);
2767
+ CXXMethodDecl *FinalizeMethod =
2768
+ getMethodByName (RecordDecl, FinalizeMethodName);
2769
+ // A finalize-method is expected for stream class.
2770
+ if (!FinalizeMethod && Util::isSyclStreamType (Ty))
2771
+ SemaRef.Diag (FD->getLocation (), diag::err_sycl_expected_finalize_method);
2772
+ else
2773
+ createSpecialMethodCall (RecordDecl, FinalizeMethodName, FinalizeStmts);
2806
2774
2807
2775
removeFieldMemberExpr (FD, Ty);
2808
2776
@@ -2896,9 +2864,7 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler {
2896
2864
}
2897
2865
2898
2866
bool handleSyclStreamType (FieldDecl *FD, QualType Ty) final {
2899
- // Streams just get copied as a new init.
2900
- addSimpleFieldInit (FD, Ty);
2901
- return true ;
2867
+ return handleSpecialType (FD, Ty);
2902
2868
}
2903
2869
2904
2870
bool handleSyclStreamType (const CXXRecordDecl *, const CXXBaseSpecifier &BS,
@@ -2975,31 +2941,6 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler {
2975
2941
handleSpecialType (KernelHandlerArg->getType ());
2976
2942
}
2977
2943
2978
- bool enterStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
2979
- ++StructDepth;
2980
- // Add a dummy init expression to catch the accessor initializers.
2981
- const auto *StreamDecl = Ty->getAsCXXRecordDecl ();
2982
- CollectionInitExprs.push_back (createInitListExpr (StreamDecl));
2983
-
2984
- addFieldMemberExpr (FD, Ty);
2985
- return true ;
2986
- }
2987
-
2988
- bool leaveStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
2989
- --StructDepth;
2990
- // Stream requires that its 'init' calls happen after its accessors init
2991
- // calls, so add them here instead.
2992
- const auto *StreamDecl = Ty->getAsCXXRecordDecl ();
2993
-
2994
- createSpecialMethodCall (StreamDecl, getInitMethodName (), BodyStmts);
2995
- createSpecialMethodCall (StreamDecl, FinalizeMethodName, FinalizeStmts);
2996
-
2997
- removeFieldMemberExpr (FD, Ty);
2998
-
2999
- CollectionInitExprs.pop_back ();
3000
- return true ;
3001
- }
3002
-
3003
2944
bool enterStruct (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
3004
2945
++StructDepth;
3005
2946
addCollectionInitListExpr (Ty->getAsCXXRecordDecl ());
@@ -3312,7 +3253,7 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
3312
3253
}
3313
3254
3314
3255
bool handleSyclStreamType (FieldDecl *FD, QualType FieldTy) final {
3315
- addParam (FD, FieldTy, SYCLIntegrationHeader::kind_std_layout );
3256
+ addParam (FD, FieldTy, SYCLIntegrationHeader::kind_stream );
3316
3257
return true ;
3317
3258
}
3318
3259
@@ -3344,18 +3285,6 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
3344
3285
SYCLIntegrationHeader::kind_specialization_constants_buffer, 0 );
3345
3286
}
3346
3287
3347
- bool enterStream (const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
3348
- ++StructDepth;
3349
- CurOffset += offsetOf (FD, Ty);
3350
- return true ;
3351
- }
3352
-
3353
- bool leaveStream (const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
3354
- --StructDepth;
3355
- CurOffset -= offsetOf (FD, Ty);
3356
- return true ;
3357
- }
3358
-
3359
3288
bool enterStruct (const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
3360
3289
++StructDepth;
3361
3290
CurOffset += offsetOf (FD, Ty);
@@ -4123,7 +4052,10 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller,
4123
4052
return ;
4124
4053
4125
4054
// Diagnose if this is an undefined function and it is not a builtin.
4126
- if (!Callee->isDefined () && !Callee->getBuiltinID ()) {
4055
+ // Currently, there is an exception of "__failed_assertion" in libstdc++-11,
4056
+ // this undefined function is used to trigger a compiling error.
4057
+ if (!Callee->isDefined () && !Callee->getBuiltinID () &&
4058
+ !isSYCLUndefinedAllowed (Callee, getSourceManager ())) {
4127
4059
Diag (Loc, diag::err_sycl_restrict) << Sema::KernelCallUndefinedFunction;
4128
4060
Diag (Callee->getLocation (), diag::note_previous_decl) << Callee;
4129
4061
Diag (Caller->getLocation (), diag::note_called_by) << Caller;
@@ -4161,6 +4093,7 @@ static const char *paramKind2Str(KernelParamKind K) {
4161
4093
CASE (accessor);
4162
4094
CASE (std_layout);
4163
4095
CASE (sampler);
4096
+ CASE (stream);
4164
4097
CASE (specialization_constants_buffer);
4165
4098
CASE (pointer);
4166
4099
}
0 commit comments