diff options
-rw-r--r-- | slang_rs_export_foreach.cpp | 110 | ||||
-rw-r--r-- | slang_rs_export_foreach.h | 15 | ||||
-rw-r--r-- | slang_version.h | 1 |
3 files changed, 71 insertions, 55 deletions
diff --git a/slang_rs_export_foreach.cpp b/slang_rs_export_foreach.cpp index b2e82af..ae4d707 100644 --- a/slang_rs_export_foreach.cpp +++ b/slang_rs_export_foreach.cpp @@ -57,7 +57,6 @@ bool RSExportForEach::validateAndConstructParams( RSContext *Context, const clang::FunctionDecl *FD) { slangAssert(Context && FD); bool valid = true; - clang::ASTContext &C = Context->getASTContext(); clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); numParams = FD->getNumParams(); @@ -77,17 +76,28 @@ bool RSExportForEach::validateAndConstructParams( } mResultType = FD->getResultType().getCanonicalType(); - // Compute kernel functions are required to return a void type or - // be marked explicitly as a kernel. In the case of - // "__attribute__((kernel))", we handle validation differently. + // Compute kernel functions are defined differently when the + // "__attribute__((kernel))" is set. if (FD->hasAttr<clang::KernelAttr>()) { - return validateAndConstructKernelParams(Context, FD); + valid |= validateAndConstructKernelParams(Context, FD); + } else { + valid |= validateAndConstructOldStyleParams(Context, FD); } + valid |= setSignatureMetadata(Context, FD); + return valid; +} +bool RSExportForEach::validateAndConstructOldStyleParams(RSContext *Context, + const clang::FunctionDecl *FD) { + slangAssert(Context && FD); // If numParams is 0, we already marked this as a graphics root(). slangAssert(numParams > 0); - // Compute kernel functions of this type are required to return a void type. + bool valid = true; + clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); + + // Compute kernel functions of this style are required to return a void type. + clang::ASTContext &C = Context->getASTContext(); if (mResultType != C.VoidTy) { DiagEngine->Report( clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()), @@ -194,36 +204,6 @@ bool RSExportForEach::validateAndConstructParams( i++; } - mSignatureMetadata = 0; - if (valid) { - // Set up the bitwise metadata encoding for runtime argument passing. - mSignatureMetadata |= (mIn ? 0x01 : 0); - mSignatureMetadata |= (mOut ? 0x02 : 0); - mSignatureMetadata |= (mUsrData ? 0x04 : 0); - mSignatureMetadata |= (mX ? 0x08 : 0); - mSignatureMetadata |= (mY ? 0x10 : 0); - } - - if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { - // APIs before ICS cannot skip between parameters. It is ok, however, for - // them to omit further parameters (i.e. skipping X is ok if you skip Y). - if (mSignatureMetadata != 0x1f && // In, Out, UsrData, X, Y - mSignatureMetadata != 0x0f && // In, Out, UsrData, X - mSignatureMetadata != 0x07 && // In, Out, UsrData - mSignatureMetadata != 0x03 && // In, Out - mSignatureMetadata != 0x01) { // In - DiagEngine->Report( - clang::FullSourceLoc(FD->getLocation(), - DiagEngine->getSourceManager()), - DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, - "Compute kernel %0() targeting SDK levels " - "%1-%2 may not skip parameters")) - << FD->getName() << SLANG_MINIMUM_TARGET_API - << (SLANG_ICS_TARGET_API - 1); - valid = false; - } - } - return valid; } @@ -249,10 +229,10 @@ bool RSExportForEach::validateAndConstructKernelParams(RSContext *Context, } // Denote that we are indeed a pass-by-value kernel. - mKernel = true; + mIsKernelStyle = true; if (mResultType != C.VoidTy) { - mReturn = true; + mHasReturnType = true; } if (mResultType->isPointerType()) { @@ -304,7 +284,7 @@ bool RSExportForEach::validateAndConstructKernelParams(RSContext *Context, } // Check that we have at least one allocation to use for dimensions. - if (valid && !mIn && !mReturn) { + if (valid && !mIn && !mHasReturnType) { DiagEngine->Report( clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()), @@ -369,24 +349,54 @@ bool RSExportForEach::validateAndConstructKernelParams(RSContext *Context, i++; // advance parameter pointer } + return valid; +} +bool RSExportForEach::setSignatureMetadata(RSContext *Context, + const clang::FunctionDecl *FD) { mSignatureMetadata = 0; - if (valid) { - // Set up the bitwise metadata encoding for runtime argument passing. - mSignatureMetadata |= (mIn ? 0x01 : 0); + bool valid = true; + + if (mIsKernelStyle) { slangAssert(mOut == NULL); - mSignatureMetadata |= (mReturn ? 0x02 : 0); slangAssert(mUsrData == NULL); - mSignatureMetadata |= (mUsrData ? 0x04 : 0); - mSignatureMetadata |= (mX ? 0x08 : 0); - mSignatureMetadata |= (mY ? 0x10 : 0); - mSignatureMetadata |= (mKernel ? 0x20 : 0); // pass-by-value + } else { + slangAssert(!mHasReturnType); } + // Set up the bitwise metadata encoding for runtime argument passing. + // TODO: If this bit field is re-used from C++ code, define the values in a header. + const bool HasOut = mOut || mHasReturnType; + mSignatureMetadata |= (mIn ? 0x01 : 0); + mSignatureMetadata |= (HasOut ? 0x02 : 0); + mSignatureMetadata |= (mUsrData ? 0x04 : 0); + mSignatureMetadata |= (mX ? 0x08 : 0); + mSignatureMetadata |= (mY ? 0x10 : 0); + mSignatureMetadata |= (mIsKernelStyle ? 0x20 : 0); // pass-by-value + + if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { + // APIs before ICS cannot skip between parameters. It is ok, however, for + // them to omit further parameters (i.e. skipping X is ok if you skip Y). + if (mSignatureMetadata != 0x1f && // In, Out, UsrData, X, Y + mSignatureMetadata != 0x0f && // In, Out, UsrData, X + mSignatureMetadata != 0x07 && // In, Out, UsrData + mSignatureMetadata != 0x03 && // In, Out + mSignatureMetadata != 0x01) { // In + clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); + DiagEngine->Report(clang::FullSourceLoc(FD->getLocation(), + DiagEngine->getSourceManager()), + DiagEngine->getCustomDiagID( + clang::DiagnosticsEngine::Error, + "Compute kernel %0() targeting SDK levels " + "%1-%2 may not skip parameters")) + << FD->getName() << SLANG_MINIMUM_TARGET_API + << (SLANG_ICS_TARGET_API - 1); + valid = false; + } + } return valid; } - RSExportForEach *RSExportForEach::Create(RSContext *Context, const clang::FunctionDecl *FD) { slangAssert(Context && FD); @@ -464,12 +474,12 @@ RSExportForEach *RSExportForEach::Create(RSContext *Context, if (FE->mIn) { const clang::Type *T = FE->mIn->getType().getCanonicalType().getTypePtr(); FE->mInType = RSExportType::Create(Context, T); - if (FE->mKernel) { + if (FE->mIsKernelStyle) { slangAssert(FE->mInType); } } - if (FE->mKernel && FE->mReturn) { + if (FE->mIsKernelStyle && FE->mHasReturnType) { const clang::Type *T = FE->mResultType.getTypePtr(); FE->mOutType = RSExportType::Create(Context, T); slangAssert(FE->mOutType); diff --git a/slang_rs_export_foreach.h b/slang_rs_export_foreach.h index 6cacc60..14266d5 100644 --- a/slang_rs_export_foreach.h +++ b/slang_rs_export_foreach.h @@ -54,8 +54,8 @@ class RSExportForEach : public RSExportable { const clang::ParmVarDecl *mAr; clang::QualType mResultType; // return type (if present). - bool mReturn; // does this kernel have a return type? - bool mKernel; // is this a pass-by-value kernel? + bool mHasReturnType; // does this kernel have a return type? + bool mIsKernelStyle; // is this a pass-by-value kernel? bool mDummyRoot; @@ -65,17 +65,22 @@ class RSExportForEach : public RSExportable { mName(Name.data(), Name.size()), mParamPacketType(NULL), mInType(NULL), mOutType(NULL), numParams(0), mSignatureMetadata(0), mIn(NULL), mOut(NULL), mUsrData(NULL), mX(NULL), mY(NULL), mZ(NULL), - mAr(NULL), mResultType(clang::QualType()), mReturn(false), - mKernel(false), mDummyRoot(false) { + mAr(NULL), mResultType(clang::QualType()), mHasReturnType(false), + mIsKernelStyle(false), mDummyRoot(false) { return; } bool validateAndConstructParams(RSContext *Context, const clang::FunctionDecl *FD); + bool validateAndConstructOldStyleParams(RSContext *Context, + const clang::FunctionDecl *FD); + bool validateAndConstructKernelParams(RSContext *Context, const clang::FunctionDecl *FD); + bool setSignatureMetadata(RSContext *Context, + const clang::FunctionDecl *FD); public: static RSExportForEach *Create(RSContext *Context, const clang::FunctionDecl *FD); @@ -103,7 +108,7 @@ class RSExportForEach : public RSExportable { } inline bool hasReturn() const { - return mReturn; + return mHasReturnType; } inline const RSExportType *getInType() const { diff --git a/slang_version.h b/slang_version.h index 287dc3e..e42f1a5 100644 --- a/slang_version.h +++ b/slang_version.h @@ -22,6 +22,7 @@ // HC -> Honeycomb // ICS -> Ice Cream Sandwich // JB -> Jelly Bean +// KK -> KitKat enum SlangTargetAPI { SLANG_MINIMUM_TARGET_API = 11, SLANG_HC_TARGET_API = 11, |