1593a894650e81be54173106ec266f0311cebebd3Stephen Hines/* 29999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines * Copyright 2011-2012, The Android Open Source Project 3593a894650e81be54173106ec266f0311cebebd3Stephen Hines * 4593a894650e81be54173106ec266f0311cebebd3Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License"); 5593a894650e81be54173106ec266f0311cebebd3Stephen Hines * you may not use this file except in compliance with the License. 6593a894650e81be54173106ec266f0311cebebd3Stephen Hines * You may obtain a copy of the License at 7593a894650e81be54173106ec266f0311cebebd3Stephen Hines * 8593a894650e81be54173106ec266f0311cebebd3Stephen Hines * http://www.apache.org/licenses/LICENSE-2.0 9593a894650e81be54173106ec266f0311cebebd3Stephen Hines * 10593a894650e81be54173106ec266f0311cebebd3Stephen Hines * Unless required by applicable law or agreed to in writing, software 11593a894650e81be54173106ec266f0311cebebd3Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 12593a894650e81be54173106ec266f0311cebebd3Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13593a894650e81be54173106ec266f0311cebebd3Stephen Hines * See the License for the specific language governing permissions and 14593a894650e81be54173106ec266f0311cebebd3Stephen Hines * limitations under the License. 15593a894650e81be54173106ec266f0311cebebd3Stephen Hines */ 16593a894650e81be54173106ec266f0311cebebd3Stephen Hines 17593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_rs_export_foreach.h" 18593a894650e81be54173106ec266f0311cebebd3Stephen Hines 19593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include <string> 20593a894650e81be54173106ec266f0311cebebd3Stephen Hines 21593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "clang/AST/ASTContext.h" 2223c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "clang/AST/Attr.h" 23593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "clang/AST/Decl.h" 24b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines#include "clang/AST/TypeLoc.h" 25593a894650e81be54173106ec266f0311cebebd3Stephen Hines 2623c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/DerivedTypes.h" 27593a894650e81be54173106ec266f0311cebebd3Stephen Hines 2818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross#include "bcinfo/MetadataExtractor.h" 2918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 30593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_assert.h" 31593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_rs_context.h" 32593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_rs_export_type.h" 33eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala#include "slang_rs_special_func.h" 3446e146e0cef555379699f06edb3b2d9673978703David Gross#include "slang_rs_special_kernel_param.h" 3512580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines#include "slang_version.h" 36593a894650e81be54173106ec266f0311cebebd3Stephen Hines 3718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossnamespace { 3818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 39cd7d3128f41a59692e5c59a2b81969616579aae4David Grossconst size_t RS_KERNEL_INPUT_LIMIT = 8; // see frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h 40cd7d3128f41a59692e5c59a2b81969616579aae4David Gross 41eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Walabool isRootRSFunc(const clang::FunctionDecl *FD) { 42eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala if (!FD) { 43eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala return false; 44eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala } 45eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala return FD->getName().equals("root"); 467cc6876212646f91cd718a72a1845a0563838fe9David Gross} 4718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 48eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala} // end anonymous namespace 49eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala 50593a894650e81be54173106ec266f0311cebebd3Stephen Hinesnamespace slang { 51593a894650e81be54173106ec266f0311cebebd3Stephen Hines 52b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// This function takes care of additional validation and construction of 53b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// parameters related to forEach_* reflection. 54b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesbool RSExportForEach::validateAndConstructParams( 55b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSContext *Context, const clang::FunctionDecl *FD) { 56b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 57b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines bool valid = true; 58b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 59b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines numParams = FD->getNumParams(); 60b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 617b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (Context->getTargetAPI() < SLANG_JB_TARGET_API) { 62482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet // Before JellyBean, we allowed only one kernel per file. It must be called "root". 637b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (!isRootRSFunc(FD)) { 64d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 65d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Non-root compute kernel %0() is " 66d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "not supported in SDK levels %1-%2") 67d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 68d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << (SLANG_JB_TARGET_API - 1); 697b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 707b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 717b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 727b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 73ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray mResultType = FD->getReturnType().getCanonicalType(); 740f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Compute kernel functions are defined differently when the 750f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // "__attribute__((kernel))" is set. 76b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar if (FD->hasAttr<clang::RenderScriptKernelAttr>()) { 77f075ffc10278e1c127bcf041fce7ce89d428f94cStephen Hines valid &= validateAndConstructKernelParams(Context, FD); 780f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } else { 79f075ffc10278e1c127bcf041fce7ce89d428f94cStephen Hines valid &= validateAndConstructOldStyleParams(Context, FD); 809ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 81c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 82f075ffc10278e1c127bcf041fce7ce89d428f94cStephen Hines valid &= setSignatureMetadata(Context, FD); 830f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet return valid; 840f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet} 859ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 8642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouilletbool RSExportForEach::validateAndConstructOldStyleParams( 8742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD) { 880f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet slangAssert(Context && FD); 899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // If numParams is 0, we already marked this as a graphics root(). 909ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(numParams > 0); 919ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 920f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet bool valid = true; 930f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 940f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Compute kernel functions of this style are required to return a void type. 950f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet clang::ASTContext &C = Context->getASTContext(); 969ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType != C.VoidTy) { 97d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 98d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() is required to return a " 99d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "void type") 100d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 101b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 102b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 103b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 104b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Validate remaining parameter types 105b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 10618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross size_t IndexOfFirstSpecialParameter = numParams; 107f075ffc10278e1c127bcf041fce7ce89d428f94cStephen Hines valid &= processSpecialParameters(Context, FD, &IndexOfFirstSpecialParameter); 1084ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 10918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // Validate the non-special parameters, which should all be found before the 11018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // first special parameter. 11118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross for (size_t i = 0; i < IndexOfFirstSpecialParameter; i++) { 11242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 11342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::QualType QT = PVD->getType().getCanonicalType(); 1144ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 11542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (!QT->isPointerType()) { 11642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 11742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() cannot have non-pointer " 1189764eb3be0f2dcaaefa62fddc9fbedf14784ae38Jean-Luc Brouillet "parameters besides special parameters (%1). Parameter '%2' is " 11918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "of type: '%3'") 12046e146e0cef555379699f06edb3b2d9673978703David Gross << FD->getName() << listSpecialKernelParameters(Context->getTargetAPI()) 12118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << PVD->getName() << PVD->getType().getAsString(); 12242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 12342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet continue; 12442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 1254ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 12642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // The only non-const pointer should be out. 12742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (!QT->getPointeeType().isConstQualified()) { 1285abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes if (mOut == nullptr) { 12942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mOut = PVD; 13042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 13142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 13242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() can only have one non-const " 13342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "pointer parameter. Parameters '%1' and '%2' are " 13442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "both non-const.") 13542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << FD->getName() << mOut->getName() << PVD->getName(); 13642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 13742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 13842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 1395abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes if (mIns.empty() && mOut == nullptr) { 140c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes mIns.push_back(PVD); 1415abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes } else if (mUsrData == nullptr) { 14242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mUsrData = PVD; 14342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 14442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError( 14542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet PVD->getLocation(), 14642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Unexpected parameter '%0' for compute kernel %1()") 14742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << PVD->getName() << FD->getName(); 14842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 14942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 1504ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1514ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1524ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 153c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (mIns.empty() && !mOut) { 154d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 155d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() must have at least one " 156d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameter for in or out") 157d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 1584ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1594ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1604ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 161b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return valid; 162b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} 163b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 16442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouilletbool RSExportForEach::validateAndConstructKernelParams( 16542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD) { 1669ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(Context && FD); 1679ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines bool valid = true; 1689ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::ASTContext &C = Context->getASTContext(); 1699ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1709ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (Context->getTargetAPI() < SLANG_JB_MR1_TARGET_API) { 171d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 172d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() targeting SDK levels " 173d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%1-%2 may not use pass-by-value with " 174d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "__attribute__((kernel))") 175d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 176d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << (SLANG_JB_MR1_TARGET_API - 1); 1779ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return false; 1789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 1799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1809ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Denote that we are indeed a pass-by-value kernel. 1810f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mIsKernelStyle = true; 182d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet mHasReturnType = (mResultType != C.VoidTy); 1839ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1849ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType->isPointerType()) { 18542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError( 18642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet FD->getTypeSpecStartLoc(), 18742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() cannot return a pointer type: '%1'") 188d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << mResultType.getAsString(); 1899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 1909ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 1919ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1929ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Validate remaining parameter types 1939ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 19418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross size_t IndexOfFirstSpecialParameter = numParams; 195f075ffc10278e1c127bcf041fce7ce89d428f94cStephen Hines valid &= processSpecialParameters(Context, FD, &IndexOfFirstSpecialParameter); 1969ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 19718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // Validate the non-special parameters, which should all be found before the 19818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // first special. 19918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross for (size_t i = 0; i < IndexOfFirstSpecialParameter; i++) { 20042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 201c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 202bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines if (Context->getTargetAPI() >= SLANG_M_TARGET_API || i == 0) { 203cd7d3128f41a59692e5c59a2b81969616579aae4David Gross if (i >= RS_KERNEL_INPUT_LIMIT) { 204cd7d3128f41a59692e5c59a2b81969616579aae4David Gross Context->ReportError(PVD->getLocation(), 205cd7d3128f41a59692e5c59a2b81969616579aae4David Gross "Invalid parameter '%0' for compute kernel %1(). " 206bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines "Kernels targeting SDK levels %2+ may not use " 207bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines "more than %3 input parameters.") << PVD->getName() << 208bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines FD->getName() << SLANG_M_TARGET_API << 209bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines int(RS_KERNEL_INPUT_LIMIT); 210cd7d3128f41a59692e5c59a2b81969616579aae4David Gross 211cd7d3128f41a59692e5c59a2b81969616579aae4David Gross } else { 212cd7d3128f41a59692e5c59a2b81969616579aae4David Gross mIns.push_back(PVD); 213cd7d3128f41a59692e5c59a2b81969616579aae4David Gross } 21442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 21542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 216c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "Invalid parameter '%0' for compute kernel %1(). " 217c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "Kernels targeting SDK levels %2-%3 may not use " 218c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "multiple input parameters.") << PVD->getName() << 219c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes FD->getName() << SLANG_MINIMUM_TARGET_API << 220bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines (SLANG_M_TARGET_API - 1); 22142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 22242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 22342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::QualType QT = PVD->getType().getCanonicalType(); 2249ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (QT->isPointerType()) { 225d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(PVD->getLocation(), 226d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() cannot have " 227d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameter '%1' of pointer type: '%2'") 228d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 2299ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2309ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2319ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2329ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2339ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Check that we have at least one allocation to use for dimensions. 234bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines if (valid && mIns.empty() && !mHasReturnType && Context->getTargetAPI() < SLANG_M_TARGET_API) { 235d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 236fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross "Compute kernel %0() targeting SDK levels " 237fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross "%1-%2 must have at least one " 238d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "input parameter or a non-void return " 239d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "type") 240fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross << FD->getName() << SLANG_MINIMUM_TARGET_API 241bd0a7ddceac6c135ea975cefbac73877a1f9dae7Stephen Hines << (SLANG_M_TARGET_API - 1); 2429ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2439ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2449ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 24542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet return valid; 24642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet} 2479ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2489764eb3be0f2dcaaefa62fddc9fbedf14784ae38Jean-Luc Brouillet// Process the optional special parameters: 2499764eb3be0f2dcaaefa62fddc9fbedf14784ae38Jean-Luc Brouillet// - Sets *IndexOfFirstSpecialParameter to the index of the first special parameter, or 2509764eb3be0f2dcaaefa62fddc9fbedf14784ae38Jean-Luc Brouillet// FD->getNumParams() if none are found. 25146e146e0cef555379699f06edb3b2d9673978703David Gross// - Add bits to mSpecialParameterSignatureMetadata for the found special parameters. 2529764eb3be0f2dcaaefa62fddc9fbedf14784ae38Jean-Luc Brouillet// Returns true if no errors. 2539764eb3be0f2dcaaefa62fddc9fbedf14784ae38Jean-Luc Brouilletbool RSExportForEach::processSpecialParameters( 25442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD, 25518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross size_t *IndexOfFirstSpecialParameter) { 25646e146e0cef555379699f06edb3b2d9673978703David Gross auto DiagnosticCallback = [FD] { 25746e146e0cef555379699f06edb3b2d9673978703David Gross std::ostringstream DiagnosticDescription; 25846e146e0cef555379699f06edb3b2d9673978703David Gross DiagnosticDescription << "compute kernel " << FD->getName().str() << "()"; 25946e146e0cef555379699f06edb3b2d9673978703David Gross return DiagnosticDescription.str(); 26046e146e0cef555379699f06edb3b2d9673978703David Gross }; 26146e146e0cef555379699f06edb3b2d9673978703David Gross return slang::processSpecialKernelParameters(Context, 26246e146e0cef555379699f06edb3b2d9673978703David Gross DiagnosticCallback, 26346e146e0cef555379699f06edb3b2d9673978703David Gross FD, 26446e146e0cef555379699f06edb3b2d9673978703David Gross IndexOfFirstSpecialParameter, 26546e146e0cef555379699f06edb3b2d9673978703David Gross &mSpecialParameterSignatureMetadata); 2660f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet} 2679ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2680f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouilletbool RSExportForEach::setSignatureMetadata(RSContext *Context, 2690f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet const clang::FunctionDecl *FD) { 2709ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata = 0; 2710f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet bool valid = true; 2720f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 2730f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (mIsKernelStyle) { 2745abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes slangAssert(mOut == nullptr); 2755abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes slangAssert(mUsrData == nullptr); 2760f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } else { 2770f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet slangAssert(!mHasReturnType); 2789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2800f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Set up the bitwise metadata encoding for runtime argument passing. 2810f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet const bool HasOut = mOut || mHasReturnType; 28218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (hasIns() ? bcinfo::MD_SIG_In : 0); 28318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (HasOut ? bcinfo::MD_SIG_Out : 0); 28418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (mUsrData ? bcinfo::MD_SIG_Usr : 0); 28518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (mIsKernelStyle ? bcinfo::MD_SIG_Kernel : 0); // pass-by-value 28618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= mSpecialParameterSignatureMetadata; 2870f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 2880f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { 2890f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // APIs before ICS cannot skip between parameters. It is ok, however, for 2900f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // them to omit further parameters (i.e. skipping X is ok if you skip Y). 29118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out | bcinfo::MD_SIG_Usr | 29218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross bcinfo::MD_SIG_X | bcinfo::MD_SIG_Y) && 29318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out | bcinfo::MD_SIG_Usr | 29418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross bcinfo::MD_SIG_X) && 29518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out | bcinfo::MD_SIG_Usr) && 29618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out) && 29718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In)) { 298d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 299d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() targeting SDK levels " 300d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%1-%2 may not skip parameters") 3010f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 3020f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet << (SLANG_ICS_TARGET_API - 1); 3030f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid = false; 3040f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } 3050f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } 3069ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return valid; 3079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines} 3089ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 309593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context, 310593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::FunctionDecl *FD) { 311b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 312593a894650e81be54173106ec266f0311cebebd3Stephen Hines llvm::StringRef Name = FD->getName(); 313b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportForEach *FE; 314593a894650e81be54173106ec266f0311cebebd3Stephen Hines 315593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 316593a894650e81be54173106ec266f0311cebebd3Stephen Hines 317c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE = new RSExportForEach(Context, Name); 318593a894650e81be54173106ec266f0311cebebd3Stephen Hines 319b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (!FE->validateAndConstructParams(Context, FD)) { 3205abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes return nullptr; 321593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 322593a894650e81be54173106ec266f0311cebebd3Stephen Hines 323593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 324593a894650e81be54173106ec266f0311cebebd3Stephen Hines 325eca0534a31b6185d6ab758f5e97acd7a4cb21e8eJean-Luc Brouillet std::string Id = CreateDummyName("helper_foreach_param", FE->getName()); 326593a894650e81be54173106ec266f0311cebebd3Stephen Hines 327593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Extract the usrData parameter (if we have one) 328b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mUsrData) { 329b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::ParmVarDecl *PVD = FE->mUsrData; 330593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 331593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(QT->isPointerType() && 332593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType().isConstQualified()); 333593a894650e81be54173106ec266f0311cebebd3Stephen Hines 334593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = Context->getASTContext(); 335593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() == 336593a894650e81be54173106ec266f0311cebebd3Stephen Hines C.VoidTy) { 337593a894650e81be54173106ec266f0311cebebd3Stephen Hines // In the case of using const void*, we can't reflect an appopriate 338593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Java type, so we fall back to just reflecting the ain/aout parameters 3395abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes FE->mUsrData = nullptr; 340593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 341b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl *RD = 342b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 343b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Ctx.getTranslationUnitDecl(), 344b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 345b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 346b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines &Ctx.Idents.get(Id)); 347b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 348593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl *FD = 349593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl::Create(Ctx, 350593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD, 351593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 352593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 353593a894650e81be54173106ec266f0311cebebd3Stephen Hines PVD->getIdentifier(), 354593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType(), 3555abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes nullptr, 3565abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes /* BitWidth = */ nullptr, 3571688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* Mutable = */ false, 35843730fe3c839af391efe6bdf56b0479860121924Shih-wei Liao /* HasInit = */ clang::ICIS_NoInit); 359593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD->addDecl(FD); 360b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RD->completeDefinition(); 361b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 362b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Create an export type iff we have a valid usrData type 363b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 364b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(!T.isNull()); 365b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 36613fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines RSExportType *ET = 36713fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines RSExportType::Create(Context, T.getTypePtr(), LegacyKernelArgument); 368b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 369ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines slangAssert(ET && "Failed to export a kernel"); 370b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 371b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 372b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "Parameter packet must be a record"); 373b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 374b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mParamPacketType = static_cast<RSExportRecordType *>(ET); 375593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 376593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 377593a894650e81be54173106ec266f0311cebebd3Stephen Hines 378a088faa4140ce179c38e56773f638b84c7120769Stephen Hines // Construct type information about inputs and outputs. Return null when 379a088faa4140ce179c38e56773f638b84c7120769Stephen Hines // there is an error exporting types. 380a088faa4140ce179c38e56773f638b84c7120769Stephen Hines 381a088faa4140ce179c38e56773f638b84c7120769Stephen Hines bool TypeExportError = false; 382d463956aa4e3e1a26eeb32dc9d705b4b59865041Stephen Hines 383a088faa4140ce179c38e56773f638b84c7120769Stephen Hines if (FE->hasIns()) { 384c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes for (InIter BI = FE->mIns.begin(), EI = FE->mIns.end(); BI != EI; BI++) { 385c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes const clang::Type *T = (*BI)->getType().getCanonicalType().getTypePtr(); 38613fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines ExportKind EK = (FE->mIsKernelStyle ? NotLegacyKernelArgument : 38713fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines LegacyKernelArgument); 38813fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines RSExportType *InExportType = RSExportType::Create(Context, T, EK); 389c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 390a088faa4140ce179c38e56773f638b84c7120769Stephen Hines // It is not an error if we don't export an input type for legacy 39113fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines // kernel arguments. This can happen in the case of a void pointer. 392a088faa4140ce179c38e56773f638b84c7120769Stephen Hines if (FE->mIsKernelStyle && !InExportType) { 393a088faa4140ce179c38e56773f638b84c7120769Stephen Hines TypeExportError = true; 394c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes } 395c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 396c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes FE->mInTypes.push_back(InExportType); 3979ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 398b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 399593a894650e81be54173106ec266f0311cebebd3Stephen Hines 4000f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (FE->mIsKernelStyle && FE->mHasReturnType) { 401a088faa4140ce179c38e56773f638b84c7120769Stephen Hines const clang::Type *ReturnType = FE->mResultType.getTypePtr(); 40213fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines FE->mOutType = RSExportType::Create(Context, ReturnType, 40313fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines NotLegacyKernelArgument); 404a088faa4140ce179c38e56773f638b84c7120769Stephen Hines TypeExportError |= !FE->mOutType; 4059ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (FE->mOut) { 406a088faa4140ce179c38e56773f638b84c7120769Stephen Hines const clang::Type *OutType = 407a088faa4140ce179c38e56773f638b84c7120769Stephen Hines FE->mOut->getType().getCanonicalType().getTypePtr(); 40813fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines FE->mOutType = RSExportType::Create(Context, OutType, LegacyKernelArgument); 409a088faa4140ce179c38e56773f638b84c7120769Stephen Hines // It is not an error if we don't export an output type. 410a088faa4140ce179c38e56773f638b84c7120769Stephen Hines // This can happen in the case of a void pointer. 411a088faa4140ce179c38e56773f638b84c7120769Stephen Hines } 412a088faa4140ce179c38e56773f638b84c7120769Stephen Hines 413a088faa4140ce179c38e56773f638b84c7120769Stephen Hines if (TypeExportError) { 414a088faa4140ce179c38e56773f638b84c7120769Stephen Hines slangAssert(Context->getDiagnostics()->hasErrorOccurred() && 415a088faa4140ce179c38e56773f638b84c7120769Stephen Hines "Error exporting type but no diagnostic message issued!"); 416a088faa4140ce179c38e56773f638b84c7120769Stephen Hines return nullptr; 417593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 418593a894650e81be54173106ec266f0311cebebd3Stephen Hines 419b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return FE; 420593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 421593a894650e81be54173106ec266f0311cebebd3Stephen Hines 422c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen HinesRSExportForEach *RSExportForEach::CreateDummyRoot(RSContext *Context) { 423c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines slangAssert(Context); 424c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines llvm::StringRef Name = "root"; 425c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines RSExportForEach *FE = new RSExportForEach(Context, Name); 426c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE->mDummyRoot = true; 427c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines return FE; 428c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines} 429c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines 430c9454afec1649846512993d0ef65a9f868976bb4Chris Wailesbool RSExportForEach::isRSForEachFunc(unsigned int targetAPI, 431c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes const clang::FunctionDecl *FD) { 432fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni if (!FD) { 433fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni return false; 434fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni } 435089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 436c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala // Anything tagged as a kernel("") is definitely used with ForEach. 437b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar if (FD->hasAttr<clang::RenderScriptKernelAttr>()) { 438b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar return true; 4399ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 4409ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 441eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala if (RSSpecialFunc::isGraphicsRootRSFunc(targetAPI, FD)) { 4429999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 4439999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 4449999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 4457b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Check if first parameter is a pointer (which is required for ForEach). 4467b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines unsigned int numParams = FD->getNumParams(); 4477b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 4487b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (numParams > 0) { 4497b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 4507b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 4517b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 4527b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (QT->isPointerType()) { 4537b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 4547b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 4557b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 4567b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Any non-graphics root() is automatically a ForEach candidate. 4577b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // At this point, however, we know that it is not going to be a valid 4587b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // compute root() function (due to not having a pointer parameter). We 4597b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // still want to return true here, so that we can issue appropriate 4607b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // diagnostics. 4617b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isRootRSFunc(FD)) { 4627b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 4637b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 4649999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 4659999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 4667b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 467593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 468593a894650e81be54173106ec266f0311cebebd3Stephen Hines 4691946749cebf4a64341d8210890688fef7d958c22Yang Niunsigned RSExportForEach::getNumInputs(unsigned int targetAPI, 4701946749cebf4a64341d8210890688fef7d958c22Yang Ni const clang::FunctionDecl *FD) { 4711946749cebf4a64341d8210890688fef7d958c22Yang Ni unsigned numInputs = 0; 472b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar for (const clang::ParmVarDecl* param : FD->parameters()) { 47346e146e0cef555379699f06edb3b2d9673978703David Gross if (!isSpecialKernelParameter(param->getName())) { 4741946749cebf4a64341d8210890688fef7d958c22Yang Ni numInputs++; 4751946749cebf4a64341d8210890688fef7d958c22Yang Ni } 4761946749cebf4a64341d8210890688fef7d958c22Yang Ni } 4771946749cebf4a64341d8210890688fef7d958c22Yang Ni 4781946749cebf4a64341d8210890688fef7d958c22Yang Ni return numInputs; 4791946749cebf4a64341d8210890688fef7d958c22Yang Ni} 4801946749cebf4a64341d8210890688fef7d958c22Yang Ni 481593a894650e81be54173106ec266f0311cebebd3Stephen Hines} // namespace slang 482