slang_rs_export_foreach.cpp revision c9454afec1649846512993d0ef65a9f868976bb4
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 28593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_assert.h" 29593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_rs_context.h" 30593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_rs_export_type.h" 3112580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines#include "slang_version.h" 32593a894650e81be54173106ec266f0311cebebd3Stephen Hines 33593a894650e81be54173106ec266f0311cebebd3Stephen Hinesnamespace slang { 34593a894650e81be54173106ec266f0311cebebd3Stephen Hines 35b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// This function takes care of additional validation and construction of 36b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// parameters related to forEach_* reflection. 37b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesbool RSExportForEach::validateAndConstructParams( 38b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSContext *Context, const clang::FunctionDecl *FD) { 39b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 40b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines bool valid = true; 41b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 42b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines numParams = FD->getNumParams(); 43b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 447b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (Context->getTargetAPI() < SLANG_JB_TARGET_API) { 45482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet // Before JellyBean, we allowed only one kernel per file. It must be called "root". 467b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (!isRootRSFunc(FD)) { 47d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 48d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Non-root compute kernel %0() is " 49d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "not supported in SDK levels %1-%2") 50d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 51d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << (SLANG_JB_TARGET_API - 1); 527b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 537b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 547b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 557b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 56ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray mResultType = FD->getReturnType().getCanonicalType(); 570f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Compute kernel functions are defined differently when the 580f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // "__attribute__((kernel))" is set. 599ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FD->hasAttr<clang::KernelAttr>()) { 600f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid |= validateAndConstructKernelParams(Context, FD); 610f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } else { 620f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid |= validateAndConstructOldStyleParams(Context, FD); 639ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 64c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 650f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid |= setSignatureMetadata(Context, FD); 660f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet return valid; 670f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet} 689ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 6942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouilletbool RSExportForEach::validateAndConstructOldStyleParams( 7042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD) { 710f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet slangAssert(Context && FD); 729ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // If numParams is 0, we already marked this as a graphics root(). 739ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(numParams > 0); 749ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 750f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet bool valid = true; 760f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 770f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Compute kernel functions of this style are required to return a void type. 780f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet clang::ASTContext &C = Context->getASTContext(); 799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType != C.VoidTy) { 80d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 81d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() is required to return a " 82d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "void type") 83d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 84b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 85b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 86b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 87b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Validate remaining parameter types 88b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // TODO(all): Add support for LOD/face when we have them 89b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 9042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet size_t IndexOfFirstIterator = numParams; 9142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid |= validateIterationParameters(Context, FD, &IndexOfFirstIterator); 924ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 9342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // Validate the non-iterator parameters, which should all be found before the 9442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // first iterator. 9542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet for (size_t i = 0; i < IndexOfFirstIterator; i++) { 9642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 9742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::QualType QT = PVD->getType().getCanonicalType(); 984ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 9942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (!QT->isPointerType()) { 10042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 10142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() cannot have non-pointer " 10242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "parameters besides 'x' and 'y'. Parameter '%1' is " 10342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "of type: '%2'") 10442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 10542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 10642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet continue; 10742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 1084ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 10942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // The only non-const pointer should be out. 11042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (!QT->getPointeeType().isConstQualified()) { 11142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (mOut == NULL) { 11242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mOut = PVD; 11342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 11442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 11542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() can only have one non-const " 11642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "pointer parameter. Parameters '%1' and '%2' are " 11742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "both non-const.") 11842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << FD->getName() << mOut->getName() << PVD->getName(); 11942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 12042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 12142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 122c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (mIns.empty() && mOut == NULL) { 123c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes mIns.push_back(PVD); 12442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else if (mUsrData == NULL) { 12542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mUsrData = PVD; 12642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 12742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError( 12842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet PVD->getLocation(), 12942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Unexpected parameter '%0' for compute kernel %1()") 13042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << PVD->getName() << FD->getName(); 13142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 13242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 1334ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1344ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1354ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 136c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (mIns.empty() && !mOut) { 137d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 138d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() must have at least one " 139d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameter for in or out") 140d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 1414ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1424ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1434ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 144b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return valid; 145b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} 146b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 14742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouilletbool RSExportForEach::validateAndConstructKernelParams( 14842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD) { 1499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(Context && FD); 1509ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines bool valid = true; 1519ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::ASTContext &C = Context->getASTContext(); 1529ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1539ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (Context->getTargetAPI() < SLANG_JB_MR1_TARGET_API) { 154d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 155d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() targeting SDK levels " 156d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%1-%2 may not use pass-by-value with " 157d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "__attribute__((kernel))") 158d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 159d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << (SLANG_JB_MR1_TARGET_API - 1); 1609ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return false; 1619ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 1629ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1639ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Denote that we are indeed a pass-by-value kernel. 1640f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mIsKernelStyle = true; 165d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet mHasReturnType = (mResultType != C.VoidTy); 1669ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1679ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType->isPointerType()) { 16842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError( 16942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet FD->getTypeSpecStartLoc(), 17042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "Compute kernel %0() cannot return a pointer type: '%1'") 171d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << mResultType.getAsString(); 1729ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 1739ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 1749ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 1759ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Validate remaining parameter types 1769ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // TODO(all): Add support for LOD/face when we have them 1779ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 17842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet size_t IndexOfFirstIterator = numParams; 17942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid |= validateIterationParameters(Context, FD, &IndexOfFirstIterator); 1809ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 18142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // Validate the non-iterator parameters, which should all be found before the 18242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // first iterator. 18342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet for (size_t i = 0; i < IndexOfFirstIterator; i++) { 18442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 185c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 186c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes /* 187c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes * FIXME: Change this to a test against an actual API version when the 188c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes * multi-input feature is officially supported. 189c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes */ 190c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (Context->getTargetAPI() == SLANG_DEVELOPMENT_TARGET_API || i == 0) { 191c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes mIns.push_back(PVD); 19242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else { 19342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 194c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "Invalid parameter '%0' for compute kernel %1(). " 195c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "Kernels targeting SDK levels %2-%3 may not use " 196c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes "multiple input parameters.") << PVD->getName() << 197c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes FD->getName() << SLANG_MINIMUM_TARGET_API << 198c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes SLANG_MAXIMUM_TARGET_API; 19942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 20042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 20142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::QualType QT = PVD->getType().getCanonicalType(); 2029ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (QT->isPointerType()) { 203d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(PVD->getLocation(), 204d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() cannot have " 205d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameter '%1' of pointer type: '%2'") 206d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 2079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2089ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2099ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2109ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2119ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Check that we have at least one allocation to use for dimensions. 212c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (valid && mIns.empty() && !mHasReturnType) { 213d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 214d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() must have at least one " 215d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "input parameter or a non-void return " 216d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "type") 217d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 2189ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2199ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2209ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 22142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet return valid; 22242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet} 2239ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 22442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet// Search for the optional x and y parameters. Returns true if valid. Also 22542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet// sets *IndexOfFirstIterator to the index of the first iterator parameter, or 22642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet// FD->getNumParams() if none are found. 22742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouilletbool RSExportForEach::validateIterationParameters( 22842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet RSContext *Context, const clang::FunctionDecl *FD, 22942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet size_t *IndexOfFirstIterator) { 23042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet slangAssert(IndexOfFirstIterator != NULL); 23142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet slangAssert(mX == NULL && mY == NULL); 23242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::ASTContext &C = Context->getASTContext(); 23342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet 23442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // Find the x and y parameters if present. 23542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet size_t NumParams = FD->getNumParams(); 23642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet *IndexOfFirstIterator = NumParams; 23742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet bool valid = true; 23842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet for (size_t i = 0; i < NumParams; i++) { 23942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 24042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet llvm::StringRef ParamName = PVD->getName(); 24142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (ParamName.equals("x")) { 24242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet slangAssert(mX == NULL); // We won't be invoked if two 'x' are present. 24342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mX = PVD; 24442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (mY != NULL) { 24542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 24642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "In compute kernel %0(), parameter 'x' should " 24742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "be defined before parameter 'y'") 24842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << FD->getName(); 24942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 25042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 25142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } else if (ParamName.equals("y")) { 25242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet slangAssert(mY == NULL); // We won't be invoked if two 'y' are present. 25342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet mY = PVD; 2549ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 25542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // It's neither x nor y. 25642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (*IndexOfFirstIterator < NumParams) { 25742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 25842f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "In compute kernel %0(), parameter '%1' cannot " 25942f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet "appear after the 'x' and 'y' parameters") 26042f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << FD->getName() << ParamName; 26142f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 2629ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 26342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet continue; 26442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 26542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // Validate the data type of x and y. 26642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet clang::QualType QT = PVD->getType().getCanonicalType(); 267482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet clang::QualType UT = QT.getUnqualifiedType(); 268482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet if (UT != C.UnsignedIntTy && UT != C.IntTy) { 269482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet Context->ReportError(PVD->getLocation(), 270482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet "Parameter '%0' must be of type 'int' or " 271482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet "'unsigned int'. It is of type '%1'") 27242f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet << ParamName << PVD->getType().getAsString(); 27342f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet valid = false; 27442f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet } 27542f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet // If this is the first time we find an iterator, save it. 27642f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet if (*IndexOfFirstIterator >= NumParams) { 27742f81b2b44205f421c6bd4727ce8c25b0effcb55Jean-Luc Brouillet *IndexOfFirstIterator = i; 2789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 280482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet // Check that x and y have the same type. 281482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet if (mX != NULL and mY != NULL) { 282482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet clang::QualType XType = mX->getType(); 283482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet clang::QualType YType = mY->getType(); 284482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet 285482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet if (XType != YType) { 286482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet Context->ReportError(mY->getLocation(), 287482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet "Parameter 'x' and 'y' must be of the same type. " 288482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet "'x' is of type '%0' while 'y' is of type '%1'") 289482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet << XType.getAsString() << YType.getAsString(); 290482caac59574f980cc78b2ac63e01a926da86a96Jean-Luc Brouillet valid = false; 2919ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2929ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2930f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet return valid; 2940f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet} 2959ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2960f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouilletbool RSExportForEach::setSignatureMetadata(RSContext *Context, 2970f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet const clang::FunctionDecl *FD) { 2989ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata = 0; 2990f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet bool valid = true; 3000f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 3010f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (mIsKernelStyle) { 3029ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(mOut == NULL); 3039ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(mUsrData == NULL); 3040f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } else { 3050f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet slangAssert(!mHasReturnType); 3069ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3080f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // Set up the bitwise metadata encoding for runtime argument passing. 3090f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // TODO: If this bit field is re-used from C++ code, define the values in a header. 3100f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet const bool HasOut = mOut || mHasReturnType; 311c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes mSignatureMetadata |= (hasIns() ? 0x01 : 0); 3120f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata |= (HasOut ? 0x02 : 0); 3130f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata |= (mUsrData ? 0x04 : 0); 3140f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata |= (mX ? 0x08 : 0); 3150f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata |= (mY ? 0x10 : 0); 3160f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata |= (mIsKernelStyle ? 0x20 : 0); // pass-by-value 3170f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet 3180f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { 3190f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // APIs before ICS cannot skip between parameters. It is ok, however, for 3200f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet // them to omit further parameters (i.e. skipping X is ok if you skip Y). 3210f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (mSignatureMetadata != 0x1f && // In, Out, UsrData, X, Y 3220f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata != 0x0f && // In, Out, UsrData, X 3230f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata != 0x07 && // In, Out, UsrData 3240f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata != 0x03 && // In, Out 3250f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet mSignatureMetadata != 0x01) { // In 326d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 327d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Compute kernel %0() targeting SDK levels " 328d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%1-%2 may not skip parameters") 3290f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet << FD->getName() << SLANG_MINIMUM_TARGET_API 3300f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet << (SLANG_ICS_TARGET_API - 1); 3310f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet valid = false; 3320f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } 3330f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet } 3349ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return valid; 3359ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines} 3369ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 337593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context, 338593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::FunctionDecl *FD) { 339b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 340593a894650e81be54173106ec266f0311cebebd3Stephen Hines llvm::StringRef Name = FD->getName(); 341b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportForEach *FE; 342593a894650e81be54173106ec266f0311cebebd3Stephen Hines 343593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 344593a894650e81be54173106ec266f0311cebebd3Stephen Hines 345c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE = new RSExportForEach(Context, Name); 346593a894650e81be54173106ec266f0311cebebd3Stephen Hines 347b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (!FE->validateAndConstructParams(Context, FD)) { 348b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 349593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 350593a894650e81be54173106ec266f0311cebebd3Stephen Hines 351593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 352593a894650e81be54173106ec266f0311cebebd3Stephen Hines 353eca0534a31b6185d6ab758f5e97acd7a4cb21e8eJean-Luc Brouillet std::string Id = CreateDummyName("helper_foreach_param", FE->getName()); 354593a894650e81be54173106ec266f0311cebebd3Stephen Hines 355593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Extract the usrData parameter (if we have one) 356b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mUsrData) { 357b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::ParmVarDecl *PVD = FE->mUsrData; 358593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 359593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(QT->isPointerType() && 360593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType().isConstQualified()); 361593a894650e81be54173106ec266f0311cebebd3Stephen Hines 362593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = Context->getASTContext(); 363593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() == 364593a894650e81be54173106ec266f0311cebebd3Stephen Hines C.VoidTy) { 365593a894650e81be54173106ec266f0311cebebd3Stephen Hines // In the case of using const void*, we can't reflect an appopriate 366593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Java type, so we fall back to just reflecting the ain/aout parameters 367b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mUsrData = NULL; 368593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 369b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl *RD = 370b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 371b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Ctx.getTranslationUnitDecl(), 372b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 373b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 374b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines &Ctx.Idents.get(Id)); 375b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 376593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl *FD = 377593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl::Create(Ctx, 378593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD, 379593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 380593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 381593a894650e81be54173106ec266f0311cebebd3Stephen Hines PVD->getIdentifier(), 382593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType(), 383593a894650e81be54173106ec266f0311cebebd3Stephen Hines NULL, 3841688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* BitWidth = */ NULL, 3851688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* Mutable = */ false, 38643730fe3c839af391efe6bdf56b0479860121924Shih-wei Liao /* HasInit = */ clang::ICIS_NoInit); 387593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD->addDecl(FD); 388b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RD->completeDefinition(); 389b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 390b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Create an export type iff we have a valid usrData type 391b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 392b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(!T.isNull()); 393b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 394b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportType *ET = RSExportType::Create(Context, T.getTypePtr()); 395b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 396b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (ET == NULL) { 397b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines fprintf(stderr, "Failed to export the function %s. There's at least " 398b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "one parameter whose type is not supported by the " 399b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "reflection\n", FE->getName().c_str()); 400b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 401b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 402b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 403b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 404b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "Parameter packet must be a record"); 405b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 406b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mParamPacketType = static_cast<RSExportRecordType *>(ET); 407593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 408593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 409593a894650e81be54173106ec266f0311cebebd3Stephen Hines 410c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (FE->hasIns()) { 411c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 412c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes for (InIter BI = FE->mIns.begin(), EI = FE->mIns.end(); BI != EI; BI++) { 413c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes const clang::Type *T = (*BI)->getType().getCanonicalType().getTypePtr(); 414c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes RSExportType *InExportType = RSExportType::Create(Context, T); 415c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 416c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes if (FE->mIsKernelStyle) { 417c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes slangAssert(InExportType != NULL); 418c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes } 419c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes 420c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes FE->mInTypes.push_back(InExportType); 4219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 422b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 423593a894650e81be54173106ec266f0311cebebd3Stephen Hines 4240f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet if (FE->mIsKernelStyle && FE->mHasReturnType) { 4259ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines const clang::Type *T = FE->mResultType.getTypePtr(); 4269ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines FE->mOutType = RSExportType::Create(Context, T); 4279ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(FE->mOutType); 4289ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (FE->mOut) { 429b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr(); 430b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mOutType = RSExportType::Create(Context, T); 431593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 432593a894650e81be54173106ec266f0311cebebd3Stephen Hines 433b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return FE; 434593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 435593a894650e81be54173106ec266f0311cebebd3Stephen Hines 436c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen HinesRSExportForEach *RSExportForEach::CreateDummyRoot(RSContext *Context) { 437c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines slangAssert(Context); 438c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines llvm::StringRef Name = "root"; 439c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines RSExportForEach *FE = new RSExportForEach(Context, Name); 440c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE->mDummyRoot = true; 441c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines return FE; 442c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines} 443c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines 444c9454afec1649846512993d0ef65a9f868976bb4Chris Wailesbool RSExportForEach::isGraphicsRootRSFunc(unsigned int targetAPI, 4459999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 4469ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FD->hasAttr<clang::KernelAttr>()) { 4479ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return false; 4489ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 4499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 450593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (!isRootRSFunc(FD)) { 451593a894650e81be54173106ec266f0311cebebd3Stephen Hines return false; 452593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 453593a894650e81be54173106ec266f0311cebebd3Stephen Hines 454b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FD->getNumParams() == 0) { 4559999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function 4569999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 457593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 458f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 4599999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Check for legacy graphics root function (with single parameter). 460f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 461f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 462ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray if (FD->getReturnType().getCanonicalType() == IntType) { 4639999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 464f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 465f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 466f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 4679999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 4689999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines} 4699999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 470c9454afec1649846512993d0ef65a9f868976bb4Chris Wailesbool RSExportForEach::isRSForEachFunc(unsigned int targetAPI, 471c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes slang::RSContext* Context, 472c9454afec1649846512993d0ef65a9f868976bb4Chris Wailes const clang::FunctionDecl *FD) { 473d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet slangAssert(Context && FD); 474089cde338148fbb75825aea4539ccdae8211ffefStephen Hines bool hasKernelAttr = FD->hasAttr<clang::KernelAttr>(); 475089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 476089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (FD->getStorageClass() == clang::SC_Static) { 477089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (hasKernelAttr) { 478d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 479d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Invalid use of attribute kernel with " 480d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "static function declaration: %0") 481d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 482089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 483089cde338148fbb75825aea4539ccdae8211ffefStephen Hines return false; 484089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 485089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 4869ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Anything tagged as a kernel is definitely used with ForEach. 487089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (hasKernelAttr) { 4889ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return true; 4899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 4909ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 4917b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 4929999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 4939999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 4949999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 4957b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Check if first parameter is a pointer (which is required for ForEach). 4967b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines unsigned int numParams = FD->getNumParams(); 4977b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 4987b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (numParams > 0) { 4997b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 5007b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 5017b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 5027b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (QT->isPointerType()) { 5037b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 5047b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 5057b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 5067b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Any non-graphics root() is automatically a ForEach candidate. 5077b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // At this point, however, we know that it is not going to be a valid 5087b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // compute root() function (due to not having a pointer parameter). We 5097b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // still want to return true here, so that we can issue appropriate 5107b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // diagnostics. 5117b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isRootRSFunc(FD)) { 5127b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 5137b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 5149999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 5159999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 5167b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 517593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 518593a894650e81be54173106ec266f0311cebebd3Stephen Hines 5199207a2e495c8363606861e4f034504ec5c153dabLogan Chienbool 520c9454afec1649846512993d0ef65a9f868976bb4Chris WailesRSExportForEach::validateSpecialFuncDecl(unsigned int targetAPI, 521d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet slang::RSContext *Context, 5229207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FunctionDecl const *FD) { 523d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet slangAssert(Context && FD); 524593a894650e81be54173106ec266f0311cebebd3Stephen Hines bool valid = true; 525593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = FD->getASTContext(); 5269999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 527593a894650e81be54173106ec266f0311cebebd3Stephen Hines 5289999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 5299999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 5309999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Legacy graphics root function 5319999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 5329999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 5339999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (QT != IntType) { 534d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(PVD->getLocation(), 535d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "invalid parameter type for legacy " 536d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "graphics root() function: %0") 537d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << PVD->getType(); 538593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 539593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 5409999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 5419999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 5429999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function, so verify that it returns an int 543ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray if (FD->getReturnType().getCanonicalType() != IntType) { 544d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 545d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "root() is required to return " 546d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "an int for graphics usage"); 5479999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines valid = false; 548593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 549688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) { 550593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getNumParams() != 0) { 551d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 552d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%0(void) is required to have no " 553d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "parameters") 554d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 555593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 556593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 557593a894650e81be54173106ec266f0311cebebd3Stephen Hines 558ee4016d1247d3fbe50822de279d3da273d8aef4cTim Murray if (FD->getReturnType().getCanonicalType() != C.VoidTy) { 559d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(FD->getLocation(), 560d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "%0(void) is required to have a void " 561d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "return type") 562d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet << FD->getName(); 563593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 564593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 565593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 566688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines slangAssert(false && "must be called on root, init or .rs.dtor function!"); 567593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 568593a894650e81be54173106ec266f0311cebebd3Stephen Hines 569593a894650e81be54173106ec266f0311cebebd3Stephen Hines return valid; 570593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 571593a894650e81be54173106ec266f0311cebebd3Stephen Hines 572593a894650e81be54173106ec266f0311cebebd3Stephen Hines} // namespace slang 573