slang_rs_export_foreach.cpp revision fb78d4c6604bd243578ce8071e31f68c023d82cf
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" 3312580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines#include "slang_version.h" 34593a894650e81be54173106ec266f0311cebebd3Stephen Hines 3518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossnamespace { 3618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 37cd7d3128f41a59692e5c59a2b81969616579aae4David Grossconst size_t RS_KERNEL_INPUT_LIMIT = 8; // see frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h 38cd7d3128f41a59692e5c59a2b81969616579aae4David Gross 3918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossenum SpecialParameterKind { 4018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross SPK_INT, // 'int' or 'unsigned int' 4118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross SPK_CTXT, // rs_kernel_context 4218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross}; 4318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 4418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossstruct SpecialParameter { 4518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross const char *name; 4618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross bcinfo::MetadataSignatureBitval bitval; 4718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross SpecialParameterKind kind; 4818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross SlangTargetAPI minAPI; 4918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross}; 5018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 5118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// Table entries are in the order parameters must occur in a kernel parameter list. 5218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossconst SpecialParameter specialParameterTable[] = { 5318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross { "ctxt", bcinfo::MD_SIG_Ctxt, SPK_CTXT, SLANG_23_TARGET_API }, 5418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross { "x", bcinfo::MD_SIG_X, SPK_INT, SLANG_MINIMUM_TARGET_API }, 5518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross { "y", bcinfo::MD_SIG_Y, SPK_INT, SLANG_MINIMUM_TARGET_API }, 5618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross { "z", bcinfo::MD_SIG_Z, SPK_INT, SLANG_23_TARGET_API }, 5718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross { nullptr, bcinfo::MD_SIG_None, SPK_INT, SLANG_MINIMUM_TARGET_API }, // marks end of table 5818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross}; 5918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 6018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// If the specified name matches the name of an entry in 6118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// specialParameterTable, return the corresponding table index; 6218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// otherwise return -1. 6318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossint lookupSpecialParameter(const llvm::StringRef name) { 6418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross for (int i = 0; specialParameterTable[i].name != nullptr; ++i) 6518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (name.equals(specialParameterTable[i].name)) 6618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross return i; 6718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross return -1; 6818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross} 6918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 7018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// Return a comma-separated list of names in specialParameterTable 7118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// that are available at the specified API level. 7218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossstd::string listSpecialParameters(unsigned int api) { 7318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross std::string ret; 7418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross bool first = true; 7518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross for (int i = 0; specialParameterTable[i].name != nullptr; ++i) { 7618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (specialParameterTable[i].minAPI > api) 7718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross continue; 7818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (first) 7918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross first = false; 8018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross else 8118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross ret += ", "; 8218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross ret += "'"; 8318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross ret += specialParameterTable[i].name; 8418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross ret += "'"; 8518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 8618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross return ret; 8718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross} 8818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 897cc6876212646f91cd718a72a1845a0563838fe9David Gross} 9018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 91593a894650e81be54173106ec266f0311cebebd3Stephen Hinesnamespace slang { 92593a894650e81be54173106ec266f0311cebebd3Stephen Hines 93b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// This function takes care of additional validation and construction of 94b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// parameters related to forEach_* reflection. 95b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesbool RSExportForEach::validateAndConstructParams( 96b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSContext *Context, const clang::FunctionDecl *FD) { 97b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 98b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines bool valid = true; 99b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 100b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines numParams = FD->getNumParams(); 101b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 1027b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (Context->getTargetAPI() < SLANG_JB_TARGET_API) { 103482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet // Before JellyBean, we allowed only one kernel per file. It must be called "root". 1047b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (!isRootRSFunc(FD)) { 105d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 106d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Non-root compute kernel %0() is " 107d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "not supported in SDK levels %1-%2") 108d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 109d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << (SLANG_JB_TARGET_API - 1); 1107b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 1117b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 1127b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 1137b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 114ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray mResultType = FD->getReturnType().getCanonicalType(); 1150f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Compute kernel functions are defined differently when the 1160f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // "__attribute__((kernel))" is set. 1179ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FD->hasAttr<clang::KernelAttr>()) { 1180f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid |= validateAndConstructKernelParams(Context, FD); 1190f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } else { 1200f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid |= validateAndConstructOldStyleParams(Context, FD); 1219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 122c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 1230f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid |= setSignatureMetadata(Context, FD); 1240f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet return valid; 1250f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet} 1269ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 12742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouilletbool RSExportForEach::validateAndConstructOldStyleParams( 12842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD) { 1290f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet slangAssert(Context && FD); 1309ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // If numParams is 0, we already marked this as a graphics root(). 1319ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(numParams > 0); 1329ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1330f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet bool valid = true; 1340f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 1350f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Compute kernel functions of this style are required to return a void type. 1360f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet clang::ASTContext &C = Context->getASTContext(); 1379ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType != C.VoidTy) { 138d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 139d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() is required to return a " 140d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "void type") 141d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 142b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 143b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 144b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 145b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Validate remaining parameter types 146b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 14718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross size_t IndexOfFirstSpecialParameter = numParams; 14818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross valid |= validateSpecialParameters(Context, FD, &IndexOfFirstSpecialParameter); 1494ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 15018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // Validate the non-special parameters, which should all be found before the 15118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // first special parameter. 15218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross for (size_t i = 0; i < IndexOfFirstSpecialParameter; i++) { 15342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 15442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::QualType QT = PVD->getType().getCanonicalType(); 1554ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 15642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (!QT->isPointerType()) { 15742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 15842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() cannot have non-pointer " 15918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "parameters besides (%1). Parameter '%2' is " 16018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "of type: '%3'") 16118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << FD->getName() << listSpecialParameters(Context->getTargetAPI()) 16218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << PVD->getName() << PVD->getType().getAsString(); 16342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 16442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet continue; 16542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 1664ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 16742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // The only non-const pointer should be out. 16842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (!QT->getPointeeType().isConstQualified()) { 1695abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes if (mOut == nullptr) { 17042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mOut = PVD; 17142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 17242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 17342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() can only have one non-const " 17442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "pointer parameter. Parameters '%1' and '%2' are " 17542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "both non-const.") 17642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << FD->getName() << mOut->getName() << PVD->getName(); 17742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 17842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 17942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 1805abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes if (mIns.empty() && mOut == nullptr) { 181c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes mIns.push_back(PVD); 1825abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes } else if (mUsrData == nullptr) { 18342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mUsrData = PVD; 18442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 18542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError( 18642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet PVD->getLocation(), 18742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Unexpected parameter '%0' for compute kernel %1()") 18842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << PVD->getName() << FD->getName(); 18942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 19042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 1914ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1924ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1934ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 194c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (mIns.empty() && !mOut) { 195d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 196d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() must have at least one " 197d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameter for in or out") 198d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 1994ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 2004ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 2014ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 202b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return valid; 203b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} 204b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 20542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouilletbool RSExportForEach::validateAndConstructKernelParams( 20642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD) { 2079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(Context && FD); 2089ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines bool valid = true; 2099ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::ASTContext &C = Context->getASTContext(); 2109ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2119ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (Context->getTargetAPI() < SLANG_JB_MR1_TARGET_API) { 212d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 213d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() targeting SDK levels " 214d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%1-%2 may not use pass-by-value with " 215d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "__attribute__((kernel))") 216d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 217d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << (SLANG_JB_MR1_TARGET_API - 1); 2189ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return false; 2199ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2209ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Denote that we are indeed a pass-by-value kernel. 2220f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mIsKernelStyle = true; 223d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet mHasReturnType = (mResultType != C.VoidTy); 2249ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2259ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType->isPointerType()) { 22642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError( 22742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet FD->getTypeSpecStartLoc(), 22842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() cannot return a pointer type: '%1'") 229d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << mResultType.getAsString(); 2309ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2319ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2329ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2339ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Validate remaining parameter types 2349ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 23518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross size_t IndexOfFirstSpecialParameter = numParams; 23618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross valid |= validateSpecialParameters(Context, FD, &IndexOfFirstSpecialParameter); 2379ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 23818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // Validate the non-special parameters, which should all be found before the 23918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // first special. 24018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross for (size_t i = 0; i < IndexOfFirstSpecialParameter; i++) { 24142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 242c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 243c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes /* 244c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes * FIXME: Change this to a test against an actual API version when the 245c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes * multi-input feature is officially supported. 246c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes */ 247c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (Context->getTargetAPI() == SLANG_DEVELOPMENT_TARGET_API || i == 0) { 248cd7d3128f41a59692e5c59a2b81969616579aae4David Gross if (i >= RS_KERNEL_INPUT_LIMIT) { 249cd7d3128f41a59692e5c59a2b81969616579aae4David Gross Context->ReportError(PVD->getLocation(), 250cd7d3128f41a59692e5c59a2b81969616579aae4David Gross "Invalid parameter '%0' for compute kernel %1(). " 251cd7d3128f41a59692e5c59a2b81969616579aae4David Gross "Kernels targeting SDK levels %2-%3 may not use " 252cd7d3128f41a59692e5c59a2b81969616579aae4David Gross "more than %4 input parameters.") << PVD->getName() << 253cd7d3128f41a59692e5c59a2b81969616579aae4David Gross FD->getName() << SLANG_MINIMUM_TARGET_API << 254cd7d3128f41a59692e5c59a2b81969616579aae4David Gross SLANG_MAXIMUM_TARGET_API << int(RS_KERNEL_INPUT_LIMIT); 255cd7d3128f41a59692e5c59a2b81969616579aae4David Gross 256cd7d3128f41a59692e5c59a2b81969616579aae4David Gross } else { 257cd7d3128f41a59692e5c59a2b81969616579aae4David Gross mIns.push_back(PVD); 258cd7d3128f41a59692e5c59a2b81969616579aae4David Gross } 25942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 26042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 261c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "Invalid parameter '%0' for compute kernel %1(). " 262c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "Kernels targeting SDK levels %2-%3 may not use " 263c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "multiple input parameters.") << PVD->getName() << 264c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes FD->getName() << SLANG_MINIMUM_TARGET_API << 265c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes SLANG_MAXIMUM_TARGET_API; 26642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 26742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 26842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::QualType QT = PVD->getType().getCanonicalType(); 2699ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (QT->isPointerType()) { 270d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(PVD->getLocation(), 271d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() cannot have " 272d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameter '%1' of pointer type: '%2'") 273d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 2749ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2759ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2769ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2779ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Check that we have at least one allocation to use for dimensions. 279fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross if (valid && mIns.empty() && !mHasReturnType && Context->getTargetAPI() < SLANG_23_TARGET_API) { 280d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 281fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross "Compute kernel %0() targeting SDK levels " 282fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross "%1-%2 must have at least one " 283d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "input parameter or a non-void return " 284d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "type") 285fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross << FD->getName() << SLANG_MINIMUM_TARGET_API 286fb78d4c6604bd243578ce8071e31f68c023d82cfDavid Gross << (SLANG_23_TARGET_API - 1); 2879ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2889ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 29042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet return valid; 29142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet} 2929ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 29318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// Search for the optional special parameters. Returns true if valid. Also 29418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross// sets *IndexOfFirstSpecialParameter to the index of the first special parameter, or 29542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet// FD->getNumParams() if none are found. 29618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Grossbool RSExportForEach::validateSpecialParameters( 29742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD, 29818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross size_t *IndexOfFirstSpecialParameter) { 29918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross slangAssert(IndexOfFirstSpecialParameter != nullptr); 30018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross slangAssert(mSpecialParameterSignatureMetadata == 0); 30142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::ASTContext &C = Context->getASTContext(); 30242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet 30318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // Find all special parameters if present. 30418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross int LastSpecialParameterIdx = -1; // index into specialParameterTable 30518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross int FirstIntSpecialParameterIdx = -1; // index into specialParameterTable 30618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross clang::QualType FirstIntSpecialParameterType; 30742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet size_t NumParams = FD->getNumParams(); 30818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross *IndexOfFirstSpecialParameter = NumParams; 30942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet bool valid = true; 31042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet for (size_t i = 0; i < NumParams; i++) { 31142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 31242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet llvm::StringRef ParamName = PVD->getName(); 31318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross int SpecialParameterIdx = lookupSpecialParameter(ParamName); 31418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (SpecialParameterIdx >= 0) { 31518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross const SpecialParameter &SP = specialParameterTable[SpecialParameterIdx]; 31618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // We won't be invoked if two parameters of the same name are present. 31718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross slangAssert(!(mSpecialParameterSignatureMetadata & SP.bitval)); 31818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 31918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (Context->getTargetAPI() < SP.minAPI) { 32042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 32118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "Compute kernel %0() targeting SDK levels " 32218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "%1-%2 may not use parameter '%3'.") 32318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << FD->getName() 32418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << SLANG_MINIMUM_TARGET_API 32518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << (SP.minAPI - 1) 32618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << SP.name; 32742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 32842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 32918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 33018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSpecialParameterSignatureMetadata |= SP.bitval; 33118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (SpecialParameterIdx < LastSpecialParameterIdx) { 33218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross Context->ReportError(PVD->getLocation(), 33318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "In compute kernel %0(), parameter '%1' must " 33418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "be defined before parameter '%2'.") 33518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << FD->getName() 33618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << SP.name 33718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << specialParameterTable[LastSpecialParameterIdx].name; 33818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross valid = false; 33918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 34018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross LastSpecialParameterIdx = SpecialParameterIdx; 34118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross 34218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // Ensure that all SPK_INT special parameters have the same type. 34318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (SP.kind == SPK_INT) { 34418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross clang::QualType SpecialParameterType = PVD->getType(); 34518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (FirstIntSpecialParameterIdx >= 0) { 34618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (SpecialParameterType != FirstIntSpecialParameterType) { 34718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross Context->ReportError(PVD->getLocation(), 34818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "Parameters '%0' and '%1' must be of the same type. " 34918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "'%0' is of type '%2' while '%1' is of type '%3'.") 35018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << specialParameterTable[FirstIntSpecialParameterIdx].name 35118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << SP.name 35218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << FirstIntSpecialParameterType.getAsString() 35318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << SpecialParameterType.getAsString(); 35418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross valid = false; 35518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 35618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } else { 35718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross FirstIntSpecialParameterIdx = SpecialParameterIdx; 35818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross FirstIntSpecialParameterType = SpecialParameterType; 35918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 36018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 3619ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 36218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // It's not a special parameter. 36318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (*IndexOfFirstSpecialParameter < NumParams) { 36442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 36542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "In compute kernel %0(), parameter '%1' cannot " 36618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "appear after any of the (%2) parameters.") 36718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << FD->getName() << ParamName << listSpecialParameters(Context->getTargetAPI()); 36842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 3699ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 37042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet continue; 37142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 37218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // Validate the data type of the special parameter. 37318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross switch (specialParameterTable[SpecialParameterIdx].kind) { 37418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross case SPK_INT: { 37518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross clang::QualType QT = PVD->getType().getCanonicalType(); 37618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross clang::QualType UT = QT.getUnqualifiedType(); 37718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (UT != C.UnsignedIntTy && UT != C.IntTy) { 37818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross Context->ReportError(PVD->getLocation(), 37918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "Parameter '%0' must be of type 'int' or " 38018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "'unsigned int'. It is of type '%1'.") 38118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << ParamName << PVD->getType().getAsString(); 38218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross valid = false; 38318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 38418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross break; 38518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 38618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross case SPK_CTXT: { 38718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross static const char ExpectedTypeNameMatch[] = "const struct rs_kernel_context_t *"; 38818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross static const char ExpectedTypeNamePrint[] = "rs_kernel_context"; 38918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross clang::QualType QT = PVD->getType().getCanonicalType(); 39018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross clang::QualType UT = QT.getUnqualifiedType(); 39118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (UT.getAsString() != ExpectedTypeNameMatch) { 39218c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross Context->ReportError(PVD->getLocation(), 39318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "Parameter '%0' must be of type '%1'. " 39418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross "It is of type '%2'.") 39518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross << ParamName << ExpectedTypeNamePrint << PVD->getType().getAsString(); 39618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross valid = false; 39718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 39818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross break; 39918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross } 40018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross default: 40118c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross slangAssert(!"Unexpected special parameter type"); 4029ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 40318c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross // If this is the first time we find a special parameter, save it. 40418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (*IndexOfFirstSpecialParameter >= NumParams) { 40518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross *IndexOfFirstSpecialParameter = i; 4069ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 4079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 4080f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet return valid; 4090f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet} 4109ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 4110f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouilletbool RSExportForEach::setSignatureMetadata(RSContext *Context, 4120f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet const clang::FunctionDecl *FD) { 4139ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata = 0; 4140f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet bool valid = true; 4150f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 4160f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (mIsKernelStyle) { 4175abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes slangAssert(mOut == nullptr); 4185abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes slangAssert(mUsrData == nullptr); 4190f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } else { 4200f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet slangAssert(!mHasReturnType); 4219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 4229ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 4230f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Set up the bitwise metadata encoding for runtime argument passing. 4240f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet const bool HasOut = mOut || mHasReturnType; 42518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (hasIns() ? bcinfo::MD_SIG_In : 0); 42618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (HasOut ? bcinfo::MD_SIG_Out : 0); 42718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (mUsrData ? bcinfo::MD_SIG_Usr : 0); 42818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= (mIsKernelStyle ? bcinfo::MD_SIG_Kernel : 0); // pass-by-value 42918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata |= mSpecialParameterSignatureMetadata; 4300f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 4310f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { 4320f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // APIs before ICS cannot skip between parameters. It is ok, however, for 4330f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // them to omit further parameters (i.e. skipping X is ok if you skip Y). 43418c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross if (mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out | bcinfo::MD_SIG_Usr | 43518c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross bcinfo::MD_SIG_X | bcinfo::MD_SIG_Y) && 43618c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out | bcinfo::MD_SIG_Usr | 43718c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross bcinfo::MD_SIG_X) && 43818c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out | bcinfo::MD_SIG_Usr) && 43918c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In | bcinfo::MD_SIG_Out) && 44018c50ebf6e87a6f51de8f21dce6282d1096e50c2David Gross mSignatureMetadata != (bcinfo::MD_SIG_In)) { 441d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 442d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() targeting SDK levels " 443d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%1-%2 may not skip parameters") 4440f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 4450f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet << (SLANG_ICS_TARGET_API - 1); 4460f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid = false; 4470f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } 4480f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } 4499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return valid; 4509ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines} 4519ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 452593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context, 453593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::FunctionDecl *FD) { 454b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 455593a894650e81be54173106ec266f0311cebebd3Stephen Hines llvm::StringRef Name = FD->getName(); 456b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportForEach *FE; 457593a894650e81be54173106ec266f0311cebebd3Stephen Hines 458593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 459593a894650e81be54173106ec266f0311cebebd3Stephen Hines 460c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE = new RSExportForEach(Context, Name); 461593a894650e81be54173106ec266f0311cebebd3Stephen Hines 462b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (!FE->validateAndConstructParams(Context, FD)) { 4635abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes return nullptr; 464593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 465593a894650e81be54173106ec266f0311cebebd3Stephen Hines 466593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 467593a894650e81be54173106ec266f0311cebebd3Stephen Hines 468eca0534a31b6185d6ab758f5e97acd7a4cb21e8eJean-Luc Brouillet std::string Id = CreateDummyName("helper_foreach_param", FE->getName()); 469593a894650e81be54173106ec266f0311cebebd3Stephen Hines 470593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Extract the usrData parameter (if we have one) 471b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mUsrData) { 472b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::ParmVarDecl *PVD = FE->mUsrData; 473593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 474593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(QT->isPointerType() && 475593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType().isConstQualified()); 476593a894650e81be54173106ec266f0311cebebd3Stephen Hines 477593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = Context->getASTContext(); 478593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() == 479593a894650e81be54173106ec266f0311cebebd3Stephen Hines C.VoidTy) { 480593a894650e81be54173106ec266f0311cebebd3Stephen Hines // In the case of using const void*, we can't reflect an appopriate 481593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Java type, so we fall back to just reflecting the ain/aout parameters 4825abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes FE->mUsrData = nullptr; 483593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 484b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl *RD = 485b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 486b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Ctx.getTranslationUnitDecl(), 487b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 488b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 489b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines &Ctx.Idents.get(Id)); 490b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 491593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl *FD = 492593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl::Create(Ctx, 493593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD, 494593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 495593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 496593a894650e81be54173106ec266f0311cebebd3Stephen Hines PVD->getIdentifier(), 497593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType(), 4985abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes nullptr, 4995abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes /* BitWidth = */ nullptr, 5001688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* Mutable = */ false, 50143730fe3c839af391efe6bdf56b0479860121924Shih-wei Liao /* HasInit = */ clang::ICIS_NoInit); 502593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD->addDecl(FD); 503b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RD->completeDefinition(); 504b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 505b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Create an export type iff we have a valid usrData type 506b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 507b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(!T.isNull()); 508b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 509b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportType *ET = RSExportType::Create(Context, T.getTypePtr()); 510b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 5115abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes if (ET == nullptr) { 512b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines fprintf(stderr, "Failed to export the function %s. There's at least " 513b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "one parameter whose type is not supported by the " 514b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "reflection\n", FE->getName().c_str()); 5155abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes return nullptr; 516b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 517b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 518b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 519b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "Parameter packet must be a record"); 520b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 521b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mParamPacketType = static_cast<RSExportRecordType *>(ET); 522593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 523593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 524593a894650e81be54173106ec266f0311cebebd3Stephen Hines 525c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (FE->hasIns()) { 526c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 527c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes for (InIter BI = FE->mIns.begin(), EI = FE->mIns.end(); BI != EI; BI++) { 528c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes const clang::Type *T = (*BI)->getType().getCanonicalType().getTypePtr(); 529c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes RSExportType *InExportType = RSExportType::Create(Context, T); 530c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 531c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (FE->mIsKernelStyle) { 5325abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes slangAssert(InExportType != nullptr); 533c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes } 534c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 535c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes FE->mInTypes.push_back(InExportType); 5369ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 537b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 538593a894650e81be54173106ec266f0311cebebd3Stephen Hines 5390f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (FE->mIsKernelStyle && FE->mHasReturnType) { 5409ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines const clang::Type *T = FE->mResultType.getTypePtr(); 5419ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines FE->mOutType = RSExportType::Create(Context, T); 5429ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(FE->mOutType); 5439ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (FE->mOut) { 544b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr(); 545b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mOutType = RSExportType::Create(Context, T); 546593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 547593a894650e81be54173106ec266f0311cebebd3Stephen Hines 548b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return FE; 549593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 550593a894650e81be54173106ec266f0311cebebd3Stephen Hines 551c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen HinesRSExportForEach *RSExportForEach::CreateDummyRoot(RSContext *Context) { 552c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines slangAssert(Context); 553c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines llvm::StringRef Name = "root"; 554c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines RSExportForEach *FE = new RSExportForEach(Context, Name); 555c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE->mDummyRoot = true; 556c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines return FE; 557c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines} 558c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines 559c9454afec1649846512993d0ef65a9f868976bb4Chris Wailesbool RSExportForEach::isGraphicsRootRSFunc(unsigned int targetAPI, 5609999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 5619ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FD->hasAttr<clang::KernelAttr>()) { 5629ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return false; 5639ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 5649ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 565593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (!isRootRSFunc(FD)) { 566593a894650e81be54173106ec266f0311cebebd3Stephen Hines return false; 567593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 568593a894650e81be54173106ec266f0311cebebd3Stephen Hines 569b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FD->getNumParams() == 0) { 5709999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function 5719999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 572593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 573f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 5749999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Check for legacy graphics root function (with single parameter). 575f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 576f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 577ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray if (FD->getReturnType().getCanonicalType() == IntType) { 5789999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 579f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 580f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 581f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 5829999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 5839999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines} 5849999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 585c9454afec1649846512993d0ef65a9f868976bb4Chris Wailesbool RSExportForEach::isRSForEachFunc(unsigned int targetAPI, 586c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes slang::RSContext* Context, 587c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes const clang::FunctionDecl *FD) { 588d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet slangAssert(Context && FD); 589089cde338148fbb75825aea4539ccdae8211ffefStephen Hines bool hasKernelAttr = FD->hasAttr<clang::KernelAttr>(); 590089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 591089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (FD->getStorageClass() == clang::SC_Static) { 592089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (hasKernelAttr) { 593d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 594d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Invalid use of attribute kernel with " 595d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "static function declaration: %0") 596d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 597089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 598089cde338148fbb75825aea4539ccdae8211ffefStephen Hines return false; 599089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 600089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 6019ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Anything tagged as a kernel is definitely used with ForEach. 602089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (hasKernelAttr) { 6039ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return true; 6049ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 6059ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 6067b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 6079999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 6089999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 6099999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 6107b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Check if first parameter is a pointer (which is required for ForEach). 6117b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines unsigned int numParams = FD->getNumParams(); 6127b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 6137b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (numParams > 0) { 6147b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 6157b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 6167b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 6177b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (QT->isPointerType()) { 6187b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 6197b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 6207b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 6217b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Any non-graphics root() is automatically a ForEach candidate. 6227b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // At this point, however, we know that it is not going to be a valid 6237b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // compute root() function (due to not having a pointer parameter). We 6247b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // still want to return true here, so that we can issue appropriate 6257b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // diagnostics. 6267b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isRootRSFunc(FD)) { 6277b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 6287b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 6299999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 6309999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 6317b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 632593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 633593a894650e81be54173106ec266f0311cebebd3Stephen Hines 6349207a2e495c8363606861e4f034504ec5c153dabLogan Chienbool 635c9454afec1649846512993d0ef65a9f868976bb4Chris WailesRSExportForEach::validateSpecialFuncDecl(unsigned int targetAPI, 636d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet slang::RSContext *Context, 6379207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FunctionDecl const *FD) { 638d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet slangAssert(Context && FD); 639593a894650e81be54173106ec266f0311cebebd3Stephen Hines bool valid = true; 640593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = FD->getASTContext(); 6419999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 642593a894650e81be54173106ec266f0311cebebd3Stephen Hines 6439999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 6449999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 6459999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Legacy graphics root function 6469999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 6479999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 6489999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (QT != IntType) { 649d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(PVD->getLocation(), 650d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "invalid parameter type for legacy " 651d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "graphics root() function: %0") 652d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << PVD->getType(); 653593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 654593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 6559999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 6569999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 6579999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function, so verify that it returns an int 658ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray if (FD->getReturnType().getCanonicalType() != IntType) { 659d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 660d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "root() is required to return " 661d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "an int for graphics usage"); 6629999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines valid = false; 663593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 664688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) { 665593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getNumParams() != 0) { 666d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 667d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%0(void) is required to have no " 668d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameters") 669d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 670593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 671593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 672593a894650e81be54173106ec266f0311cebebd3Stephen Hines 673ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray if (FD->getReturnType().getCanonicalType() != C.VoidTy) { 674d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 675d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%0(void) is required to have a void " 676d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "return type") 677d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 678593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 679593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 680593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 681688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines slangAssert(false && "must be called on root, init or .rs.dtor function!"); 682593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 683593a894650e81be54173106ec266f0311cebebd3Stephen Hines 684593a894650e81be54173106ec266f0311cebebd3Stephen Hines return valid; 685593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 686593a894650e81be54173106ec266f0311cebebd3Stephen Hines 687593a894650e81be54173106ec266f0311cebebd3Stephen Hines} // namespace slang 688