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 Hinesnamespace { 36b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 379207a2e495c8363606861e4f034504ec5c153dabLogan Chienstatic void ReportNameError(clang::DiagnosticsEngine *DiagEngine, 389207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::ParmVarDecl const *PVD) { 399207a2e495c8363606861e4f034504ec5c153dabLogan Chien slangAssert(DiagEngine && PVD); 409207a2e495c8363606861e4f034504ec5c153dabLogan Chien const clang::SourceManager &SM = DiagEngine->getSourceManager(); 419207a2e495c8363606861e4f034504ec5c153dabLogan Chien 429207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 439207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(PVD->getLocation(), SM), 449207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 459207a2e495c8363606861e4f034504ec5c153dabLogan Chien "Duplicate parameter entry " 469207a2e495c8363606861e4f034504ec5c153dabLogan Chien "(by position/name): '%0'")) 479207a2e495c8363606861e4f034504ec5c153dabLogan Chien << PVD->getName(); 48b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return; 49b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} 50b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 51b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} // namespace 52b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 539ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 54b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// This function takes care of additional validation and construction of 55b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// parameters related to forEach_* reflection. 56b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesbool RSExportForEach::validateAndConstructParams( 57b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSContext *Context, const clang::FunctionDecl *FD) { 58b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 59b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines bool valid = true; 60b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::ASTContext &C = Context->getASTContext(); 619207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 62b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 63b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines numParams = FD->getNumParams(); 64b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 657b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (Context->getTargetAPI() < SLANG_JB_TARGET_API) { 667b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (!isRootRSFunc(FD)) { 677b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines DiagEngine->Report( 687b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()), 697b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 707b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Non-root compute kernel %0() is " 717b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "not supported in SDK levels %1-%2")) 727b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << FD->getName() 737b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << SLANG_MINIMUM_TARGET_API 747b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << (SLANG_JB_TARGET_API - 1); 757b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 767b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 777b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 787b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mResultType = FD->getResultType().getCanonicalType(); 809ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Compute kernel functions are required to return a void type or 819ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // be marked explicitly as a kernel. In the case of 829ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // "__attribute__((kernel))", we handle validation differently. 839ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FD->hasAttr<clang::KernelAttr>()) { 849ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return validateAndConstructKernelParams(Context, FD); 859ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 869ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 879ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // If numParams is 0, we already marked this as a graphics root(). 889ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(numParams > 0); 899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 909ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Compute kernel functions of this type are required to return a void type. 919ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType != C.VoidTy) { 929207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 939207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()), 949207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 957b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Compute kernel %0() is required to return a " 967b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "void type")) << FD->getName(); 97b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 98b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 99b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 100b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Validate remaining parameter types 101b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // TODO(all): Add support for LOD/face when we have them 102b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 1034ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines size_t i = 0; 1044ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 1054ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 1064ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1074ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for const T1 *in 1084ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) { 1094ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mIn = PVD; 1104ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 1114ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1124ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1134ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for T2 *out 1144ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (i < numParams) { 1154ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1164ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1174ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && !QT->getPointeeType().isConstQualified()) { 1184ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mOut = PVD; 1194ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 1204ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1214ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1224ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1234ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (!mIn && !mOut) { 1249207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1259207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 1269207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1279207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1287b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Compute kernel %0() must have at least one " 1297b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "parameter for in or out")) << FD->getName(); 1304ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1314ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1324ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1334ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for T3 *usrData 1344ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (i < numParams) { 1354ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1364ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1374ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) { 1384ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mUsrData = PVD; 1394ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 1404ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1414ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1424ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1434ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines while (i < numParams) { 1444ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1454ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1464ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1474ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT.getUnqualifiedType() != C.UnsignedIntTy) { 1489207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1499207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(PVD->getLocation(), 1509207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1519207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1527b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Unexpected kernel %0() parameter '%1' " 1537b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "of type '%2'")) 1547b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 1554ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1564ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } else { 1574ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines llvm::StringRef ParamName = PVD->getName(); 158b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (ParamName.equals("x")) { 159b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (mX) { 1609207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 161b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 1624ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } else if (mY) { 1634ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Can't go back to X after skipping Y 1649207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 1654ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 166b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 167b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mX = PVD; 168b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 169b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else if (ParamName.equals("y")) { 170b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (mY) { 1719207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 172b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 173b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 174b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mY = PVD; 175b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 176b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 1774ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (!mX && !mY) { 178b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mX = PVD; 179b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else if (!mY) { 180b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mY = PVD; 181b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 1829207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1839207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(PVD->getLocation(), 1849207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1859207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1867b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Unexpected kernel %0() parameter '%1' " 1877b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "of type '%2'")) 1887b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 189b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 190b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 191b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 192b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 1934ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1944ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; 195b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 196b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 1977b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata = 0; 1984ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (valid) { 1994ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Set up the bitwise metadata encoding for runtime argument passing. 2007b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mIn ? 0x01 : 0); 2017b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mOut ? 0x02 : 0); 2027b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mUsrData ? 0x04 : 0); 2037b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mX ? 0x08 : 0); 2047b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mY ? 0x10 : 0); 205b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 206b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 20712580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { 20812580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines // APIs before ICS cannot skip between parameters. It is ok, however, for 20912580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines // them to omit further parameters (i.e. skipping X is ok if you skip Y). 2107b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (mSignatureMetadata != 0x1f && // In, Out, UsrData, X, Y 2117b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x0f && // In, Out, UsrData, X 2127b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x07 && // In, Out, UsrData 2137b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x03 && // In, Out 2147b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x01) { // In 2159207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 2169207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 2179207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 2189207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 2197b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Compute kernel %0() targeting SDK levels " 2207b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "%1-%2 may not skip parameters")) 2217b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << FD->getName() << SLANG_MINIMUM_TARGET_API 2227b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << (SLANG_ICS_TARGET_API - 1); 22312580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines valid = false; 22412580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines } 22512580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines } 22612580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines 227b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return valid; 228b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} 229b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 2309ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2319ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hinesbool RSExportForEach::validateAndConstructKernelParams(RSContext *Context, 2329ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines const clang::FunctionDecl *FD) { 2339ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(Context && FD); 2349ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines bool valid = true; 2359ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::ASTContext &C = Context->getASTContext(); 2369ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 2379ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2389ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (Context->getTargetAPI() < SLANG_JB_MR1_TARGET_API) { 2399ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->Report( 2409ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::FullSourceLoc(FD->getLocation(), 2419ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getSourceManager()), 2429ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 2439ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "Compute kernel %0() targeting SDK levels " 2449ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "%1-%2 may not use pass-by-value with " 2459ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "__attribute__((kernel))")) 2469ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines << FD->getName() << SLANG_MINIMUM_TARGET_API 2479ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines << (SLANG_JB_MR1_TARGET_API - 1); 2489ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return false; 2499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2509ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2519ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Denote that we are indeed a pass-by-value kernel. 2529ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mKernel = true; 2539ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2549ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType != C.VoidTy) { 2559ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mReturn = true; 2569ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2579ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2589ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mResultType->isPointerType()) { 2599ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->Report( 2609ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::FullSourceLoc(FD->getTypeSpecStartLoc(), 2619ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getSourceManager()), 2629ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 2639ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "Compute kernel %0() cannot return a " 2649ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "pointer type: '%1'")) 2659ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines << FD->getName() << mResultType.getAsString(); 2669ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2679ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2689ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2699ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Validate remaining parameter types 2709ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // TODO(all): Add support for LOD/face when we have them 2719ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2729ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines size_t i = 0; 2739ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines const clang::ParmVarDecl *PVD = NULL; 2749ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::QualType QT; 2759ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2769ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (i < numParams) { 2779ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines PVD = FD->getParamDecl(i); 2789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines QT = PVD->getType().getCanonicalType(); 2799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 2809ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (QT->isPointerType()) { 2819ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->Report( 2829ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::FullSourceLoc(PVD->getLocation(), 2839ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getSourceManager()), 2849ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 2859ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "Compute kernel %0() cannot have " 2869ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "parameter '%1' of pointer type: '%2'")) 2879ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 2889ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 2899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (QT.getUnqualifiedType() == C.UnsignedIntTy) { 2909ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // First parameter is either input or x, y (iff it is uint32_t). 2919ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines llvm::StringRef ParamName = PVD->getName(); 2929ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (ParamName.equals("x")) { 2939ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mX = PVD; 2949ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (ParamName.equals("y")) { 2959ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mY = PVD; 2969ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 2979ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mIn = PVD; 2989ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 2999ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 3009ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mIn = PVD; 3019ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3029ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3039ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines i++; // advance parameter pointer 3049ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3059ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3069ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Check that we have at least one allocation to use for dimensions. 3079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (valid && !mIn && !mReturn) { 3089ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->Report( 3099ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::FullSourceLoc(FD->getLocation(), 3109ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getSourceManager()), 3119ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3129ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "Compute kernel %0() must have at least one " 3139ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "input parameter or a non-void return " 3149ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "type")) << FD->getName(); 3159ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 3169ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3179ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3189ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // TODO: Abstract this block away, since it is duplicate code. 3199ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines while (i < numParams) { 3209ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines PVD = FD->getParamDecl(i); 3219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines QT = PVD->getType().getCanonicalType(); 3229ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3239ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (QT.getUnqualifiedType() != C.UnsignedIntTy) { 3249ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->Report( 3259ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::FullSourceLoc(PVD->getLocation(), 3269ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getSourceManager()), 3279ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3289ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "Unexpected kernel %0() parameter '%1' " 3299ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "of type '%2'")) 3309ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 3319ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 3329ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 3339ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines llvm::StringRef ParamName = PVD->getName(); 3349ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (ParamName.equals("x")) { 3359ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mX) { 3369ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines ReportNameError(DiagEngine, PVD); 3379ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 3389ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (mY) { 3399ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Can't go back to X after skipping Y 3409ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines ReportNameError(DiagEngine, PVD); 3419ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 3429ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 3439ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mX = PVD; 3449ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3459ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (ParamName.equals("y")) { 3469ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (mY) { 3479ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines ReportNameError(DiagEngine, PVD); 3489ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 3499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 3509ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mY = PVD; 3519ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3529ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 3539ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (!mX && !mY) { 3549ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mX = PVD; 3559ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (!mY) { 3569ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mY = PVD; 3579ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else { 3589ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->Report( 3599ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines clang::FullSourceLoc(PVD->getLocation(), 3609ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getSourceManager()), 3619ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3629ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "Unexpected kernel %0() parameter '%1' " 3639ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines "of type '%2'")) 3649ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 3659ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines valid = false; 3669ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3679ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3689ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3699ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3709ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines i++; // advance parameter pointer 3719ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3729ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3739ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata = 0; 3749ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (valid) { 3759ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Set up the bitwise metadata encoding for runtime argument passing. 3769ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata |= (mIn ? 0x01 : 0); 3779ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(mOut == NULL); 3789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata |= (mReturn ? 0x02 : 0); 3799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(mUsrData == NULL); 3809ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata |= (mUsrData ? 0x04 : 0); 3819ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata |= (mX ? 0x08 : 0); 3829ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata |= (mY ? 0x10 : 0); 3839ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines mSignatureMetadata |= (mKernel ? 0x20 : 0); // pass-by-value 3849ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 3859ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3869ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return valid; 3879ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines} 3889ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 3899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 390593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context, 391593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::FunctionDecl *FD) { 392b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 393593a894650e81be54173106ec266f0311cebebd3Stephen Hines llvm::StringRef Name = FD->getName(); 394b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportForEach *FE; 395593a894650e81be54173106ec266f0311cebebd3Stephen Hines 396593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 397593a894650e81be54173106ec266f0311cebebd3Stephen Hines 398c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE = new RSExportForEach(Context, Name); 399593a894650e81be54173106ec266f0311cebebd3Stephen Hines 400b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (!FE->validateAndConstructParams(Context, FD)) { 401b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 402593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 403593a894650e81be54173106ec266f0311cebebd3Stephen Hines 404593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 405593a894650e81be54173106ec266f0311cebebd3Stephen Hines 406593a894650e81be54173106ec266f0311cebebd3Stephen Hines std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_foreach_param:"); 407b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Id.append(FE->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX); 408593a894650e81be54173106ec266f0311cebebd3Stephen Hines 409593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Extract the usrData parameter (if we have one) 410b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mUsrData) { 411b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::ParmVarDecl *PVD = FE->mUsrData; 412593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 413593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(QT->isPointerType() && 414593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType().isConstQualified()); 415593a894650e81be54173106ec266f0311cebebd3Stephen Hines 416593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = Context->getASTContext(); 417593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() == 418593a894650e81be54173106ec266f0311cebebd3Stephen Hines C.VoidTy) { 419593a894650e81be54173106ec266f0311cebebd3Stephen Hines // In the case of using const void*, we can't reflect an appopriate 420593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Java type, so we fall back to just reflecting the ain/aout parameters 421b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mUsrData = NULL; 422593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 423b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl *RD = 424b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 425b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Ctx.getTranslationUnitDecl(), 426b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 427b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 428b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines &Ctx.Idents.get(Id)); 429b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 430593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl *FD = 431593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl::Create(Ctx, 432593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD, 433593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 434593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 435593a894650e81be54173106ec266f0311cebebd3Stephen Hines PVD->getIdentifier(), 436593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType(), 437593a894650e81be54173106ec266f0311cebebd3Stephen Hines NULL, 4381688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* BitWidth = */ NULL, 4391688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* Mutable = */ false, 44043730fe3c839af391efe6bdf56b0479860121924Shih-wei Liao /* HasInit = */ clang::ICIS_NoInit); 441593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD->addDecl(FD); 442b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RD->completeDefinition(); 443b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 444b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Create an export type iff we have a valid usrData type 445b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 446b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(!T.isNull()); 447b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 448b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportType *ET = RSExportType::Create(Context, T.getTypePtr()); 449b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 450b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (ET == NULL) { 451b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines fprintf(stderr, "Failed to export the function %s. There's at least " 452b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "one parameter whose type is not supported by the " 453b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "reflection\n", FE->getName().c_str()); 454b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 455b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 456b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 457b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 458b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "Parameter packet must be a record"); 459b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 460b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mParamPacketType = static_cast<RSExportRecordType *>(ET); 461593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 462593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 463593a894650e81be54173106ec266f0311cebebd3Stephen Hines 464b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mIn) { 465b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mIn->getType().getCanonicalType().getTypePtr(); 466b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mInType = RSExportType::Create(Context, T); 4679ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FE->mKernel) { 4689ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(FE->mInType); 4699ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 470b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 471593a894650e81be54173106ec266f0311cebebd3Stephen Hines 4729ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FE->mKernel && FE->mReturn) { 4739ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines const clang::Type *T = FE->mResultType.getTypePtr(); 4749ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines FE->mOutType = RSExportType::Create(Context, T); 4759ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines slangAssert(FE->mOutType); 4769ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } else if (FE->mOut) { 477b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr(); 478b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mOutType = RSExportType::Create(Context, T); 479593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 480593a894650e81be54173106ec266f0311cebebd3Stephen Hines 481b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return FE; 482593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 483593a894650e81be54173106ec266f0311cebebd3Stephen Hines 484c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen HinesRSExportForEach *RSExportForEach::CreateDummyRoot(RSContext *Context) { 485c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines slangAssert(Context); 486c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines llvm::StringRef Name = "root"; 487c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines RSExportForEach *FE = new RSExportForEach(Context, Name); 488c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE->mDummyRoot = true; 489c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines return FE; 490c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines} 491c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines 4929999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isGraphicsRootRSFunc(int targetAPI, 4939999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 4949ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines if (FD->hasAttr<clang::KernelAttr>()) { 4959ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return false; 4969ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 4979ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 498593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (!isRootRSFunc(FD)) { 499593a894650e81be54173106ec266f0311cebebd3Stephen Hines return false; 500593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 501593a894650e81be54173106ec266f0311cebebd3Stephen Hines 502b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FD->getNumParams() == 0) { 5039999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function 5049999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 505593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 506f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 5079999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Check for legacy graphics root function (with single parameter). 508f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 509f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 5109999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (FD->getResultType().getCanonicalType() == IntType) { 5119999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 512f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 513f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 514f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 5159999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 5169999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines} 5179999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 5189999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isRSForEachFunc(int targetAPI, 519089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::DiagnosticsEngine *DiagEngine, 5209999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 521089cde338148fbb75825aea4539ccdae8211ffefStephen Hines slangAssert(DiagEngine && FD); 522089cde338148fbb75825aea4539ccdae8211ffefStephen Hines bool hasKernelAttr = FD->hasAttr<clang::KernelAttr>(); 523089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 524089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (FD->getStorageClass() == clang::SC_Static) { 525089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (hasKernelAttr) { 526089cde338148fbb75825aea4539ccdae8211ffefStephen Hines DiagEngine->Report( 527089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::FullSourceLoc(FD->getLocation(), 528089cde338148fbb75825aea4539ccdae8211ffefStephen Hines DiagEngine->getSourceManager()), 529089cde338148fbb75825aea4539ccdae8211ffefStephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 530089cde338148fbb75825aea4539ccdae8211ffefStephen Hines "Invalid use of attribute kernel with " 531089cde338148fbb75825aea4539ccdae8211ffefStephen Hines "static function declaration: %0")) 532089cde338148fbb75825aea4539ccdae8211ffefStephen Hines << FD->getName(); 533089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 534089cde338148fbb75825aea4539ccdae8211ffefStephen Hines return false; 535089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 536089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 5379ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines // Anything tagged as a kernel is definitely used with ForEach. 538089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (hasKernelAttr) { 5399ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines return true; 5409ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines } 5419ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines 5427b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 5439999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 5449999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 5459999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 5467b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Check if first parameter is a pointer (which is required for ForEach). 5477b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines unsigned int numParams = FD->getNumParams(); 5487b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 5497b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (numParams > 0) { 5507b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 5517b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 5527b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 5537b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (QT->isPointerType()) { 5547b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 5557b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 5567b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 5577b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Any non-graphics root() is automatically a ForEach candidate. 5587b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // At this point, however, we know that it is not going to be a valid 5597b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // compute root() function (due to not having a pointer parameter). We 5607b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // still want to return true here, so that we can issue appropriate 5617b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // diagnostics. 5627b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isRootRSFunc(FD)) { 5637b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 5647b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 5659999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 5669999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 5677b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 568593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 569593a894650e81be54173106ec266f0311cebebd3Stephen Hines 5709207a2e495c8363606861e4f034504ec5c153dabLogan Chienbool 571fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen HinesRSExportForEach::validateSpecialFuncDecl(int targetAPI, 572fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen Hines clang::DiagnosticsEngine *DiagEngine, 5739207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FunctionDecl const *FD) { 5749207a2e495c8363606861e4f034504ec5c153dabLogan Chien slangAssert(DiagEngine && FD); 575593a894650e81be54173106ec266f0311cebebd3Stephen Hines bool valid = true; 576593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = FD->getASTContext(); 5779999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 578593a894650e81be54173106ec266f0311cebebd3Stephen Hines 5799999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 5809999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 5819999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Legacy graphics root function 5829999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 5839999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 5849999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (QT != IntType) { 5859207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 5869999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::FullSourceLoc(PVD->getLocation(), 5879207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 5889207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 5899999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "invalid parameter type for legacy " 5909999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "graphics root() function: %0")) 5919999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines << PVD->getType(); 592593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 593593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 5949999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 5959999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 5969999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function, so verify that it returns an int 5979999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (FD->getResultType().getCanonicalType() != IntType) { 5989999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->Report( 5999999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::FullSourceLoc(FD->getLocation(), 6009999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->getSourceManager()), 6019999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 6029999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "root() is required to return " 6039999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "an int for graphics usage")); 6049999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines valid = false; 605593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 606688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) { 607593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getNumParams() != 0) { 6089207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 6099207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 6109207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 6119207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 6129207a2e495c8363606861e4f034504ec5c153dabLogan Chien "%0(void) is required to have no " 6139207a2e495c8363606861e4f034504ec5c153dabLogan Chien "parameters")) << FD->getName(); 614593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 615593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 616593a894650e81be54173106ec266f0311cebebd3Stephen Hines 617593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getResultType().getCanonicalType() != C.VoidTy) { 6189207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 6199207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 6209207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 6219207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 6229207a2e495c8363606861e4f034504ec5c153dabLogan Chien "%0(void) is required to have a void " 6239207a2e495c8363606861e4f034504ec5c153dabLogan Chien "return type")) << FD->getName(); 624593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 625593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 626593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 627688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines slangAssert(false && "must be called on root, init or .rs.dtor function!"); 628593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 629593a894650e81be54173106ec266f0311cebebd3Stephen Hines 630593a894650e81be54173106ec266f0311cebebd3Stephen Hines return valid; 631593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 632593a894650e81be54173106ec266f0311cebebd3Stephen Hines 633593a894650e81be54173106ec266f0311cebebd3Stephen Hines} // namespace slang 634