@@ -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.
@@ -1034,23 +1051,6 @@ class KernelObjVisitor {
1034
1051
VisitRecordFields (Owner, Handlers...);
1035
1052
}
1036
1053
1037
- // FIXME: Can this be refactored/handled some other way?
1038
- template <typename ParentTy, typename ... HandlerTys>
1039
- void visitStreamRecord (const CXXRecordDecl *Owner, ParentTy &Parent,
1040
- CXXRecordDecl *Wrapper, QualType RecordTy,
1041
- HandlerTys &... Handlers) {
1042
- (void )std::initializer_list<int >{
1043
- (Handlers.enterStream (Owner, Parent, RecordTy), 0 )...};
1044
- for (const auto &Field : Wrapper->fields ()) {
1045
- QualType FieldTy = Field->getType ();
1046
- // Required to initialize accessors inside streams.
1047
- if (Util::isSyclAccessorType (FieldTy))
1048
- KF_FOR_EACH (handleSyclAccessorType, Field, FieldTy);
1049
- }
1050
- (void )std::initializer_list<int >{
1051
- (Handlers.leaveStream (Owner, Parent, RecordTy), 0 )...};
1052
- }
1053
-
1054
1054
template <typename ... HandlerTys>
1055
1055
void visitArrayElementImpl (const CXXRecordDecl *Owner, FieldDecl *ArrayField,
1056
1056
QualType ElementTy, uint64_t Index,
@@ -1125,12 +1125,9 @@ class KernelObjVisitor {
1125
1125
KF_FOR_EACH (handleSyclHalfType, Field, FieldTy);
1126
1126
else if (Util::isSyclSpecConstantType (FieldTy))
1127
1127
KF_FOR_EACH (handleSyclSpecConstantType, Field, FieldTy);
1128
- else if (Util::isSyclStreamType (FieldTy)) {
1129
- CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
1130
- // Handle accessors in stream class.
1128
+ else if (Util::isSyclStreamType (FieldTy))
1131
1129
KF_FOR_EACH (handleSyclStreamType, Field, FieldTy);
1132
- visitStreamRecord (Owner, Field, RD, FieldTy, Handlers...);
1133
- } else if (FieldTy->isStructureOrClassType ()) {
1130
+ else if (FieldTy->isStructureOrClassType ()) {
1134
1131
if (KF_FOR_EACH (handleStructType, Field, FieldTy)) {
1135
1132
CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
1136
1133
visitRecord (Owner, Field, RD, FieldTy, Handlers...);
@@ -1244,12 +1241,6 @@ class SyclKernelFieldHandlerBase {
1244
1241
virtual bool leaveStruct (const CXXRecordDecl *, FieldDecl *, QualType) {
1245
1242
return true ;
1246
1243
}
1247
- virtual bool enterStream (const CXXRecordDecl *, FieldDecl *, QualType) {
1248
- return true ;
1249
- }
1250
- virtual bool leaveStream (const CXXRecordDecl *, FieldDecl *, QualType) {
1251
- return true ;
1252
- }
1253
1244
virtual bool enterStruct (const CXXRecordDecl *, const CXXBaseSpecifier &,
1254
1245
QualType) {
1255
1246
return true ;
@@ -1697,18 +1688,6 @@ class SyclKernelDecompMarker : public SyclKernelFieldHandler {
1697
1688
return true ;
1698
1689
}
1699
1690
1700
- // Stream is always decomposed (and whether it gets decomposed is handled in
1701
- // handleSyclStreamType), but we need a CollectionStack entry to capture the
1702
- // accessors that get handled.
1703
- bool enterStream (const CXXRecordDecl *, FieldDecl *, QualType) final {
1704
- CollectionStack.push_back (false );
1705
- return true ;
1706
- }
1707
- bool leaveStream (const CXXRecordDecl *, FieldDecl *, QualType Ty) final {
1708
- CollectionStack.pop_back ();
1709
- return true ;
1710
- }
1711
-
1712
1691
bool enterStruct (const CXXRecordDecl *, FieldDecl *, QualType) final {
1713
1692
CollectionStack.push_back (false );
1714
1693
return true ;
@@ -1956,14 +1935,6 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
1956
1935
SemaRef.addSyclDeviceDecl (KernelDecl);
1957
1936
}
1958
1937
1959
- bool enterStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
1960
- return enterStruct (RD, FD, Ty);
1961
- }
1962
-
1963
- bool leaveStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
1964
- return leaveStruct (RD, FD, Ty);
1965
- }
1966
-
1967
1938
bool enterStruct (const CXXRecordDecl *, FieldDecl *, QualType) final {
1968
1939
++StructDepth;
1969
1940
return true ;
@@ -2099,8 +2070,7 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler {
2099
2070
}
2100
2071
2101
2072
bool handleSyclStreamType (FieldDecl *FD, QualType FieldTy) final {
2102
- addParam (FD, FieldTy);
2103
- return true ;
2073
+ return handleSpecialType (FD, FieldTy);
2104
2074
}
2105
2075
2106
2076
bool handleSyclStreamType (const CXXRecordDecl *, const CXXBaseSpecifier &,
@@ -2419,15 +2389,6 @@ class SyclOptReportCreator : public SyclKernelFieldHandler {
2419
2389
}
2420
2390
2421
2391
bool handleSyclStreamType (FieldDecl *FD, QualType FieldTy) final {
2422
- // For the current implementation of stream class, the Visitor 'handles'
2423
- // stream argument and then visits each accessor field in stream. Therefore
2424
- // handleSpecialType in this case only adds a single argument for stream.
2425
- // The arguments corresponding to accessors in stream are handled in
2426
- // handleSyclAccessorType. The opt-report therefore does not diffrentiate
2427
- // between the accessors in streams and accessors captured by SYCL kernel.
2428
- // Once stream API is modified to use __init(), the visitor will no longer
2429
- // visit the stream object and opt-report output for stream class will be
2430
- // similar to that of other special types.
2431
2392
return handleSpecialType (
2432
2393
FD, FieldTy, KernelArgDescription (KernelArgDescription::Stream));
2433
2394
}
@@ -2805,6 +2766,13 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler {
2805
2766
2806
2767
const auto *RecordDecl = Ty->getAsCXXRecordDecl ();
2807
2768
createSpecialMethodCall (RecordDecl, getInitMethodName (), BodyStmts);
2769
+ CXXMethodDecl *FinalizeMethod =
2770
+ getMethodByName (RecordDecl, FinalizeMethodName);
2771
+ // A finalize-method is expected for stream class.
2772
+ if (!FinalizeMethod && Util::isSyclStreamType (Ty))
2773
+ SemaRef.Diag (FD->getLocation (), diag::err_sycl_expected_finalize_method);
2774
+ else
2775
+ createSpecialMethodCall (RecordDecl, FinalizeMethodName, FinalizeStmts);
2808
2776
2809
2777
removeFieldMemberExpr (FD, Ty);
2810
2778
@@ -2898,9 +2866,7 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler {
2898
2866
}
2899
2867
2900
2868
bool handleSyclStreamType (FieldDecl *FD, QualType Ty) final {
2901
- // Streams just get copied as a new init.
2902
- addSimpleFieldInit (FD, Ty);
2903
- return true ;
2869
+ return handleSpecialType (FD, Ty);
2904
2870
}
2905
2871
2906
2872
bool handleSyclStreamType (const CXXRecordDecl *, const CXXBaseSpecifier &BS,
@@ -2977,31 +2943,6 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler {
2977
2943
handleSpecialType (KernelHandlerArg->getType ());
2978
2944
}
2979
2945
2980
- bool enterStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
2981
- ++StructDepth;
2982
- // Add a dummy init expression to catch the accessor initializers.
2983
- const auto *StreamDecl = Ty->getAsCXXRecordDecl ();
2984
- CollectionInitExprs.push_back (createInitListExpr (StreamDecl));
2985
-
2986
- addFieldMemberExpr (FD, Ty);
2987
- return true ;
2988
- }
2989
-
2990
- bool leaveStream (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
2991
- --StructDepth;
2992
- // Stream requires that its 'init' calls happen after its accessors init
2993
- // calls, so add them here instead.
2994
- const auto *StreamDecl = Ty->getAsCXXRecordDecl ();
2995
-
2996
- createSpecialMethodCall (StreamDecl, getInitMethodName (), BodyStmts);
2997
- createSpecialMethodCall (StreamDecl, FinalizeMethodName, FinalizeStmts);
2998
-
2999
- removeFieldMemberExpr (FD, Ty);
3000
-
3001
- CollectionInitExprs.pop_back ();
3002
- return true ;
3003
- }
3004
-
3005
2946
bool enterStruct (const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
3006
2947
++StructDepth;
3007
2948
addCollectionInitListExpr (Ty->getAsCXXRecordDecl ());
@@ -3315,7 +3256,7 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
3315
3256
}
3316
3257
3317
3258
bool handleSyclStreamType (FieldDecl *FD, QualType FieldTy) final {
3318
- addParam (FD, FieldTy, SYCLIntegrationHeader::kind_std_layout );
3259
+ addParam (FD, FieldTy, SYCLIntegrationHeader::kind_stream );
3319
3260
return true ;
3320
3261
}
3321
3262
@@ -3347,18 +3288,6 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
3347
3288
SYCLIntegrationHeader::kind_specialization_constants_buffer, 0 );
3348
3289
}
3349
3290
3350
- bool enterStream (const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
3351
- ++StructDepth;
3352
- CurOffset += offsetOf (FD, Ty);
3353
- return true ;
3354
- }
3355
-
3356
- bool leaveStream (const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
3357
- --StructDepth;
3358
- CurOffset -= offsetOf (FD, Ty);
3359
- return true ;
3360
- }
3361
-
3362
3291
bool enterStruct (const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
3363
3292
++StructDepth;
3364
3293
CurOffset += offsetOf (FD, Ty);
@@ -4122,7 +4051,10 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller,
4122
4051
return ;
4123
4052
4124
4053
// Diagnose if this is an undefined function and it is not a builtin.
4125
- if (!Callee->isDefined () && !Callee->getBuiltinID ()) {
4054
+ // Currently, there is an exception of "__failed_assertion" in libstdc++-11,
4055
+ // this undefined function is used to trigger a compiling error.
4056
+ if (!Callee->isDefined () && !Callee->getBuiltinID () &&
4057
+ !isSYCLUndefinedAllowed (Callee, getSourceManager ())) {
4126
4058
Diag (Loc, diag::err_sycl_restrict) << Sema::KernelCallUndefinedFunction;
4127
4059
Diag (Callee->getLocation (), diag::note_previous_decl) << Callee;
4128
4060
Diag (Caller->getLocation (), diag::note_called_by) << Caller;
@@ -4160,6 +4092,7 @@ static const char *paramKind2Str(KernelParamKind K) {
4160
4092
CASE (accessor);
4161
4093
CASE (std_layout);
4162
4094
CASE (sampler);
4095
+ CASE (stream);
4163
4096
CASE (specialization_constants_buffer);
4164
4097
CASE (pointer);
4165
4098
}
0 commit comments