slang_rs_export_foreach.cpp revision c17e198ffcd37bfc57e3add1f6eee952ae2a2eab
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" 22593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "clang/AST/Decl.h" 23b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines#include "clang/AST/TypeLoc.h" 24593a894650e81be54173106ec266f0311cebebd3Stephen Hines 25593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "llvm/DerivedTypes.h" 26593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "llvm/Target/TargetData.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 53b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// This function takes care of additional validation and construction of 54b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// parameters related to forEach_* reflection. 55b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesbool RSExportForEach::validateAndConstructParams( 56b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSContext *Context, const clang::FunctionDecl *FD) { 57b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 58b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines bool valid = true; 59b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::ASTContext &C = Context->getASTContext(); 609207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); 61b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 62b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines numParams = FD->getNumParams(); 63b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(numParams > 0); 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 797b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Compute kernel functions are required to return a void type for now 80b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FD->getResultType().getCanonicalType() != C.VoidTy) { 819207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 829207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()), 839207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 847b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Compute kernel %0() is required to return a " 857b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "void type")) << FD->getName(); 86b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 87b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 88b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 89b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Validate remaining parameter types 90b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // TODO(all): Add support for LOD/face when we have them 91b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 924ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines size_t i = 0; 934ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 944ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 954ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 964ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for const T1 *in 974ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) { 984ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mIn = PVD; 994ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 1004ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1014ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1024ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for T2 *out 1034ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (i < numParams) { 1044ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1054ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1064ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && !QT->getPointeeType().isConstQualified()) { 1074ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mOut = PVD; 1084ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 1094ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1104ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1114ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1124ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (!mIn && !mOut) { 1139207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1149207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 1159207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1169207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1177b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Compute kernel %0() must have at least one " 1187b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "parameter for in or out")) << FD->getName(); 1194ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1204ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1214ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1224ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for T3 *usrData 1234ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (i < numParams) { 1244ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1254ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1264ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) { 1274ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mUsrData = PVD; 1284ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 1294ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1304ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1314ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1324ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines while (i < numParams) { 1334ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1344ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1354ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1364ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT.getUnqualifiedType() != C.UnsignedIntTy) { 1379207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1389207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(PVD->getLocation(), 1399207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1409207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1417b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Unexpected kernel %0() parameter '%1' " 1427b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "of type '%2'")) 1437b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 1444ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1454ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } else { 1464ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines llvm::StringRef ParamName = PVD->getName(); 147b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (ParamName.equals("x")) { 148b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (mX) { 1499207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 150b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 1514ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } else if (mY) { 1524ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Can't go back to X after skipping Y 1539207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 1544ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 155b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 156b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mX = PVD; 157b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 158b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else if (ParamName.equals("y")) { 159b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (mY) { 1609207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 161b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 162b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 163b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mY = PVD; 164b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 165b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 1664ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (!mX && !mY) { 167b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mX = PVD; 168b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else if (!mY) { 169b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mY = PVD; 170b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 1719207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1729207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(PVD->getLocation(), 1739207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1749207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1757b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Unexpected kernel %0() parameter '%1' " 1767b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "of type '%2'")) 1777b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << FD->getName() << PVD->getName() << PVD->getType().getAsString(); 178b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 179b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 180b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 181b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 1824ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1834ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; 184b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 185b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 1867b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata = 0; 1874ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (valid) { 1884ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Set up the bitwise metadata encoding for runtime argument passing. 1897b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mIn ? 0x01 : 0); 1907b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mOut ? 0x02 : 0); 1917b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mUsrData ? 0x04 : 0); 1927b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mX ? 0x08 : 0); 1937b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata |= (mY ? 0x10 : 0); 194b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 195b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 19612580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { 19712580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines // APIs before ICS cannot skip between parameters. It is ok, however, for 19812580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines // them to omit further parameters (i.e. skipping X is ok if you skip Y). 1997b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (mSignatureMetadata != 0x1f && // In, Out, UsrData, X, Y 2007b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x0f && // In, Out, UsrData, X 2017b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x07 && // In, Out, UsrData 2027b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x03 && // In, Out 2037b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines mSignatureMetadata != 0x01) { // In 2049207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 2059207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 2069207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 2079207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 2087b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "Compute kernel %0() targeting SDK levels " 2097b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines "%1-%2 may not skip parameters")) 2107b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << FD->getName() << SLANG_MINIMUM_TARGET_API 2117b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines << (SLANG_ICS_TARGET_API - 1); 21212580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines valid = false; 21312580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines } 21412580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines } 21512580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines 216b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return valid; 217b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} 218b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 219593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context, 220593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::FunctionDecl *FD) { 221b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 222593a894650e81be54173106ec266f0311cebebd3Stephen Hines llvm::StringRef Name = FD->getName(); 223b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportForEach *FE; 224593a894650e81be54173106ec266f0311cebebd3Stephen Hines 225593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 226593a894650e81be54173106ec266f0311cebebd3Stephen Hines 227c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE = new RSExportForEach(Context, Name); 228593a894650e81be54173106ec266f0311cebebd3Stephen Hines 229b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (!FE->validateAndConstructParams(Context, FD)) { 230b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 231593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 232593a894650e81be54173106ec266f0311cebebd3Stephen Hines 233593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 234593a894650e81be54173106ec266f0311cebebd3Stephen Hines 235593a894650e81be54173106ec266f0311cebebd3Stephen Hines std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_foreach_param:"); 236b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Id.append(FE->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX); 237593a894650e81be54173106ec266f0311cebebd3Stephen Hines 238593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Extract the usrData parameter (if we have one) 239b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mUsrData) { 240b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::ParmVarDecl *PVD = FE->mUsrData; 241593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 242593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(QT->isPointerType() && 243593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType().isConstQualified()); 244593a894650e81be54173106ec266f0311cebebd3Stephen Hines 245593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = Context->getASTContext(); 246593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() == 247593a894650e81be54173106ec266f0311cebebd3Stephen Hines C.VoidTy) { 248593a894650e81be54173106ec266f0311cebebd3Stephen Hines // In the case of using const void*, we can't reflect an appopriate 249593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Java type, so we fall back to just reflecting the ain/aout parameters 250b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mUsrData = NULL; 251593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 252b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl *RD = 253b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 254b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Ctx.getTranslationUnitDecl(), 255b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 256b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 257b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines &Ctx.Idents.get(Id)); 258b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 259593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl *FD = 260593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl::Create(Ctx, 261593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD, 262593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 263593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 264593a894650e81be54173106ec266f0311cebebd3Stephen Hines PVD->getIdentifier(), 265593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType(), 266593a894650e81be54173106ec266f0311cebebd3Stephen Hines NULL, 2671688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* BitWidth = */ NULL, 2681688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* Mutable = */ false, 2691688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* HasInit = */ false); 270593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD->addDecl(FD); 271b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RD->completeDefinition(); 272b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 273b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Create an export type iff we have a valid usrData type 274b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 275b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(!T.isNull()); 276b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 277b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportType *ET = RSExportType::Create(Context, T.getTypePtr()); 278b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 279b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (ET == NULL) { 280b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines fprintf(stderr, "Failed to export the function %s. There's at least " 281b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "one parameter whose type is not supported by the " 282b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "reflection\n", FE->getName().c_str()); 283b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 284b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 285b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 286b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 287b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "Parameter packet must be a record"); 288b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 289b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mParamPacketType = static_cast<RSExportRecordType *>(ET); 290593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 291593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 292593a894650e81be54173106ec266f0311cebebd3Stephen Hines 293b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mIn) { 294b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mIn->getType().getCanonicalType().getTypePtr(); 295b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mInType = RSExportType::Create(Context, T); 296b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 297593a894650e81be54173106ec266f0311cebebd3Stephen Hines 298b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mOut) { 299b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr(); 300b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mOutType = RSExportType::Create(Context, T); 301593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 302593a894650e81be54173106ec266f0311cebebd3Stephen Hines 303b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return FE; 304593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 305593a894650e81be54173106ec266f0311cebebd3Stephen Hines 306c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen HinesRSExportForEach *RSExportForEach::CreateDummyRoot(RSContext *Context) { 307c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines slangAssert(Context); 308c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines llvm::StringRef Name = "root"; 309c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines RSExportForEach *FE = new RSExportForEach(Context, Name); 310c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines FE->mDummyRoot = true; 311c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines return FE; 312c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines} 313c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines 3149999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isGraphicsRootRSFunc(int targetAPI, 3159999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 316593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (!isRootRSFunc(FD)) { 317593a894650e81be54173106ec266f0311cebebd3Stephen Hines return false; 318593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 319593a894650e81be54173106ec266f0311cebebd3Stephen Hines 320b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FD->getNumParams() == 0) { 3219999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function 3229999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 323593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 324f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 3259999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Check for legacy graphics root function (with single parameter). 326f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 327f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 3289999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (FD->getResultType().getCanonicalType() == IntType) { 3299999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 330f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 331f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 332f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 3339999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 3349999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines} 3359999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 3369999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isRSForEachFunc(int targetAPI, 3379999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 3387b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 3399999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 3409999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 3419999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 3427b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Check if first parameter is a pointer (which is required for ForEach). 3437b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines unsigned int numParams = FD->getNumParams(); 3447b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 3457b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (numParams > 0) { 3467b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 3477b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 3487b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 3497b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (QT->isPointerType()) { 3507b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 3517b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 3527b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines 3537b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // Any non-graphics root() is automatically a ForEach candidate. 3547b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // At this point, however, we know that it is not going to be a valid 3557b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // compute root() function (due to not having a pointer parameter). We 3567b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // still want to return true here, so that we can issue appropriate 3577b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines // diagnostics. 3587b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines if (isRootRSFunc(FD)) { 3597b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return true; 3607b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines } 3619999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 3629999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 3637b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines return false; 364593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 365593a894650e81be54173106ec266f0311cebebd3Stephen Hines 3669207a2e495c8363606861e4f034504ec5c153dabLogan Chienbool 367fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen HinesRSExportForEach::validateSpecialFuncDecl(int targetAPI, 368fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen Hines clang::DiagnosticsEngine *DiagEngine, 3699207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FunctionDecl const *FD) { 3709207a2e495c8363606861e4f034504ec5c153dabLogan Chien slangAssert(DiagEngine && FD); 371593a894650e81be54173106ec266f0311cebebd3Stephen Hines bool valid = true; 372593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = FD->getASTContext(); 3739999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 374593a894650e81be54173106ec266f0311cebebd3Stephen Hines 3759999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 3769999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 3779999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Legacy graphics root function 3789999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 3799999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 3809999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (QT != IntType) { 3819207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 3829999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::FullSourceLoc(PVD->getLocation(), 3839207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 3849207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3859999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "invalid parameter type for legacy " 3869999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "graphics root() function: %0")) 3879999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines << PVD->getType(); 388593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 389593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 3909999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 3919999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 3929999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function, so verify that it returns an int 3939999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (FD->getResultType().getCanonicalType() != IntType) { 3949999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->Report( 3959999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::FullSourceLoc(FD->getLocation(), 3969999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->getSourceManager()), 3979999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3989999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "root() is required to return " 3999999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "an int for graphics usage")); 4009999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines valid = false; 401593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 402688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) { 403593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getNumParams() != 0) { 4049207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 4059207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 4069207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 4079207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 4089207a2e495c8363606861e4f034504ec5c153dabLogan Chien "%0(void) is required to have no " 4099207a2e495c8363606861e4f034504ec5c153dabLogan Chien "parameters")) << FD->getName(); 410593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 411593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 412593a894650e81be54173106ec266f0311cebebd3Stephen Hines 413593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getResultType().getCanonicalType() != C.VoidTy) { 4149207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 4159207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 4169207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 4179207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 4189207a2e495c8363606861e4f034504ec5c153dabLogan Chien "%0(void) is required to have a void " 4199207a2e495c8363606861e4f034504ec5c153dabLogan Chien "return type")) << FD->getName(); 420593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 421593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 422593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 423688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines slangAssert(false && "must be called on root, init or .rs.dtor function!"); 424593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 425593a894650e81be54173106ec266f0311cebebd3Stephen Hines 426593a894650e81be54173106ec266f0311cebebd3Stephen Hines return valid; 427593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 428593a894650e81be54173106ec266f0311cebebd3Stephen Hines 429593a894650e81be54173106ec266f0311cebebd3Stephen Hines} // namespace slang 430