slang_rs_export_foreach.cpp revision 9999ec3aa0c4d7a6befd3a300dc07f0cea91cb6c
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 if (!isRootRSFunc(FD)) { 63b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(false && "must be called on compute root function!"); 64b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 65b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 66b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines numParams = FD->getNumParams(); 67b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(numParams > 0); 68b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 69b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Compute root functions are required to return a void type for now 70b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FD->getResultType().getCanonicalType() != C.VoidTy) { 719207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 729207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()), 739207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 749207a2e495c8363606861e4f034504ec5c153dabLogan Chien "compute root() is required to return a " 759207a2e495c8363606861e4f034504ec5c153dabLogan Chien "void type")); 76b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 77b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 78b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 79b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Validate remaining parameter types 80b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // TODO(all): Add support for LOD/face when we have them 81b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 824ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines size_t i = 0; 834ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(i); 844ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 854ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 864ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for const T1 *in 874ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) { 884ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mIn = PVD; 894ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 904ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 914ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 924ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for T2 *out 934ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (i < numParams) { 944ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 954ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 964ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && !QT->getPointeeType().isConstQualified()) { 974ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mOut = PVD; 984ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 994ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1004ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1014ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1024ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (!mIn && !mOut) { 1039207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1049207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 1059207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1069207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1079207a2e495c8363606861e4f034504ec5c153dabLogan Chien "Compute root() must have at least one " 1089207a2e495c8363606861e4f034504ec5c153dabLogan Chien "parameter for in or out")); 1094ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1104ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1114ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1124ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Check for T3 *usrData 1134ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (i < numParams) { 1144ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1154ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1164ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) { 1174ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mUsrData = PVD; 1184ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; // advance parameter pointer 1194ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1204ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } 1214ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1224ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines while (i < numParams) { 1234ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines PVD = FD->getParamDecl(i); 1244ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines QT = PVD->getType().getCanonicalType(); 1254ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1264ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (QT.getUnqualifiedType() != C.UnsignedIntTy) { 1279207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1289207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(PVD->getLocation(), 1299207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1309207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1319207a2e495c8363606861e4f034504ec5c153dabLogan Chien "Unexpected root() parameter '%0' " 1329207a2e495c8363606861e4f034504ec5c153dabLogan Chien "of type '%1'")) 1339207a2e495c8363606861e4f034504ec5c153dabLogan Chien << PVD->getName() << PVD->getType().getAsString(); 1344ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 1354ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } else { 1364ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines llvm::StringRef ParamName = PVD->getName(); 137b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (ParamName.equals("x")) { 138b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (mX) { 1399207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 140b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 1414ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines } else if (mY) { 1424ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Can't go back to X after skipping Y 1439207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 1444ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines valid = false; 145b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 146b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mX = PVD; 147b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 148b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else if (ParamName.equals("y")) { 149b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (mY) { 1509207a2e495c8363606861e4f034504ec5c153dabLogan Chien ReportNameError(DiagEngine, PVD); 151b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 152b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 153b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mY = PVD; 154b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 155b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 1564ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (!mX && !mY) { 157b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mX = PVD; 158b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else if (!mY) { 159b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines mY = PVD; 160b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } else { 1619207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1629207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(PVD->getLocation(), 1639207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1649207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1659207a2e495c8363606861e4f034504ec5c153dabLogan Chien "Unexpected root() parameter '%0' " 1669207a2e495c8363606861e4f034504ec5c153dabLogan Chien "of type '%1'")) 1679207a2e495c8363606861e4f034504ec5c153dabLogan Chien << PVD->getName() << PVD->getType().getAsString(); 168b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines valid = false; 169b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 170b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 171b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 1724ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines 1734ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines i++; 174b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 175b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 1764ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mMetadataEncoding = 0; 1774ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines if (valid) { 1784ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines // Set up the bitwise metadata encoding for runtime argument passing. 1794ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mMetadataEncoding |= (mIn ? 0x01 : 0); 1804ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mMetadataEncoding |= (mOut ? 0x02 : 0); 1814ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mMetadataEncoding |= (mUsrData ? 0x04 : 0); 1824ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mMetadataEncoding |= (mX ? 0x08 : 0); 1834ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines mMetadataEncoding |= (mY ? 0x10 : 0); 184b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 185b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 18612580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) { 18712580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines // APIs before ICS cannot skip between parameters. It is ok, however, for 18812580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines // them to omit further parameters (i.e. skipping X is ok if you skip Y). 18912580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines if (mMetadataEncoding != 0x1f && // In, Out, UsrData, X, Y 19012580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines mMetadataEncoding != 0x0f && // In, Out, UsrData, X 19112580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines mMetadataEncoding != 0x07 && // In, Out, UsrData 19212580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines mMetadataEncoding != 0x03 && // In, Out 19312580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines mMetadataEncoding != 0x01) { // In 1949207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 1959207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 1969207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 1979207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 1989207a2e495c8363606861e4f034504ec5c153dabLogan Chien "Compute root() targeting SDK levels " 1999207a2e495c8363606861e4f034504ec5c153dabLogan Chien "%0-%1 may not skip parameters")) 2009207a2e495c8363606861e4f034504ec5c153dabLogan Chien << SLANG_MINIMUM_TARGET_API << (SLANG_ICS_TARGET_API-1); 20112580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines valid = false; 20212580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines } 20312580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines } 20412580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines 20512580dcd125d958bff87385ab13599ad01bd8aeaStephen Hines 206b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return valid; 207b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines} 208b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 209593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context, 210593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::FunctionDecl *FD) { 211b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(Context && FD); 212593a894650e81be54173106ec266f0311cebebd3Stephen Hines llvm::StringRef Name = FD->getName(); 213b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportForEach *FE; 214593a894650e81be54173106ec266f0311cebebd3Stephen Hines 215593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(!Name.empty() && "Function must have a name"); 216593a894650e81be54173106ec266f0311cebebd3Stephen Hines 217b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE = new RSExportForEach(Context, Name, FD); 218593a894650e81be54173106ec266f0311cebebd3Stephen Hines 219b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (!FE->validateAndConstructParams(Context, FD)) { 220b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 221593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 222593a894650e81be54173106ec266f0311cebebd3Stephen Hines 223593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::ASTContext &Ctx = Context->getASTContext(); 224593a894650e81be54173106ec266f0311cebebd3Stephen Hines 225593a894650e81be54173106ec266f0311cebebd3Stephen Hines std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_foreach_param:"); 226b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Id.append(FE->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX); 227593a894650e81be54173106ec266f0311cebebd3Stephen Hines 228593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Extract the usrData parameter (if we have one) 229b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mUsrData) { 230b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::ParmVarDecl *PVD = FE->mUsrData; 231593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 232593a894650e81be54173106ec266f0311cebebd3Stephen Hines slangAssert(QT->isPointerType() && 233593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType().isConstQualified()); 234593a894650e81be54173106ec266f0311cebebd3Stephen Hines 235593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = Context->getASTContext(); 236593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() == 237593a894650e81be54173106ec266f0311cebebd3Stephen Hines C.VoidTy) { 238593a894650e81be54173106ec266f0311cebebd3Stephen Hines // In the case of using const void*, we can't reflect an appopriate 239593a894650e81be54173106ec266f0311cebebd3Stephen Hines // Java type, so we fall back to just reflecting the ain/aout parameters 240b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mUsrData = NULL; 241593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 242b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl *RD = 243b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::RecordDecl::Create(Ctx, clang::TTK_Struct, 244b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines Ctx.getTranslationUnitDecl(), 245b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 246b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::SourceLocation(), 247b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines &Ctx.Idents.get(Id)); 248b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 249593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl *FD = 250593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::FieldDecl::Create(Ctx, 251593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD, 252593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 253593a894650e81be54173106ec266f0311cebebd3Stephen Hines clang::SourceLocation(), 254593a894650e81be54173106ec266f0311cebebd3Stephen Hines PVD->getIdentifier(), 255593a894650e81be54173106ec266f0311cebebd3Stephen Hines QT->getPointeeType(), 256593a894650e81be54173106ec266f0311cebebd3Stephen Hines NULL, 2571688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* BitWidth = */ NULL, 2581688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* Mutable = */ false, 2591688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao /* HasInit = */ false); 260593a894650e81be54173106ec266f0311cebebd3Stephen Hines RD->addDecl(FD); 261b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RD->completeDefinition(); 262b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 263b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines // Create an export type iff we have a valid usrData type 264b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines clang::QualType T = Ctx.getTagDeclType(RD); 265b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert(!T.isNull()); 266b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 267b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines RSExportType *ET = RSExportType::Create(Context, T.getTypePtr()); 268b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 269b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (ET == NULL) { 270b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines fprintf(stderr, "Failed to export the function %s. There's at least " 271b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "one parameter whose type is not supported by the " 272b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "reflection\n", FE->getName().c_str()); 273b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return NULL; 274b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 275b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 276b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && 277b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines "Parameter packet must be a record"); 278b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines 279b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mParamPacketType = static_cast<RSExportRecordType *>(ET); 280593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 281593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 282593a894650e81be54173106ec266f0311cebebd3Stephen Hines 283b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mIn) { 284b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mIn->getType().getCanonicalType().getTypePtr(); 285b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mInType = RSExportType::Create(Context, T); 286b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines } 287593a894650e81be54173106ec266f0311cebebd3Stephen Hines 288b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FE->mOut) { 289b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr(); 290b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines FE->mOutType = RSExportType::Create(Context, T); 291593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 292593a894650e81be54173106ec266f0311cebebd3Stephen Hines 293b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines return FE; 294593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 295593a894650e81be54173106ec266f0311cebebd3Stephen Hines 2969999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isGraphicsRootRSFunc(int targetAPI, 2979999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 298593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (!isRootRSFunc(FD)) { 299593a894650e81be54173106ec266f0311cebebd3Stephen Hines return false; 300593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 301593a894650e81be54173106ec266f0311cebebd3Stephen Hines 302b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines if (FD->getNumParams() == 0) { 3039999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function 3049999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 305593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 306f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 3079999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Check for legacy graphics root function (with single parameter). 308f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 309f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 3109999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (FD->getResultType().getCanonicalType() == IntType) { 3119999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return true; 312f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 313f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines } 314f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines 3159999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 3169999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines} 3179999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 3189999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isRSForEachFunc(int targetAPI, 3199999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::FunctionDecl *FD) { 3209999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // We currently support only compute root() being exported via forEach 3219999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (!isRootRSFunc(FD)) { 3229999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 3239999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 3249999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 3259999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 3269999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines return false; 3279999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 3289999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 329593a894650e81be54173106ec266f0311cebebd3Stephen Hines return true; 330593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 331593a894650e81be54173106ec266f0311cebebd3Stephen Hines 3329207a2e495c8363606861e4f034504ec5c153dabLogan Chienbool 333fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen HinesRSExportForEach::validateSpecialFuncDecl(int targetAPI, 334fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen Hines clang::DiagnosticsEngine *DiagEngine, 3359207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FunctionDecl const *FD) { 3369207a2e495c8363606861e4f034504ec5c153dabLogan Chien slangAssert(DiagEngine && FD); 337593a894650e81be54173106ec266f0311cebebd3Stephen Hines bool valid = true; 338593a894650e81be54173106ec266f0311cebebd3Stephen Hines const clang::ASTContext &C = FD->getASTContext(); 3399999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::QualType &IntType = FD->getASTContext().IntTy; 340593a894650e81be54173106ec266f0311cebebd3Stephen Hines 3419999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (isGraphicsRootRSFunc(targetAPI, FD)) { 3429999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) { 3439999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Legacy graphics root function 3449999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 3459999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 3469999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (QT != IntType) { 3479207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 3489999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::FullSourceLoc(PVD->getLocation(), 3499207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 3509207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3519999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "invalid parameter type for legacy " 3529999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "graphics root() function: %0")) 3539999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines << PVD->getType(); 354593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 355593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 3569999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines } 3579999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines 3589999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines // Graphics root function, so verify that it returns an int 3599999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines if (FD->getResultType().getCanonicalType() != IntType) { 3609999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->Report( 3619999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines clang::FullSourceLoc(FD->getLocation(), 3629999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->getSourceManager()), 3639999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3649999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "root() is required to return " 3659999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines "an int for graphics usage")); 3669999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines valid = false; 367593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 368688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) { 369593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getNumParams() != 0) { 3709207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 3719207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 3729207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 3739207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3749207a2e495c8363606861e4f034504ec5c153dabLogan Chien "%0(void) is required to have no " 3759207a2e495c8363606861e4f034504ec5c153dabLogan Chien "parameters")) << FD->getName(); 376593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 377593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 378593a894650e81be54173106ec266f0311cebebd3Stephen Hines 379593a894650e81be54173106ec266f0311cebebd3Stephen Hines if (FD->getResultType().getCanonicalType() != C.VoidTy) { 3809207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->Report( 3819207a2e495c8363606861e4f034504ec5c153dabLogan Chien clang::FullSourceLoc(FD->getLocation(), 3829207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getSourceManager()), 3839207a2e495c8363606861e4f034504ec5c153dabLogan Chien DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, 3849207a2e495c8363606861e4f034504ec5c153dabLogan Chien "%0(void) is required to have a void " 3859207a2e495c8363606861e4f034504ec5c153dabLogan Chien "return type")) << FD->getName(); 386593a894650e81be54173106ec266f0311cebebd3Stephen Hines valid = false; 387593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 388593a894650e81be54173106ec266f0311cebebd3Stephen Hines } else { 389688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines slangAssert(false && "must be called on root, init or .rs.dtor function!"); 390593a894650e81be54173106ec266f0311cebebd3Stephen Hines } 391593a894650e81be54173106ec266f0311cebebd3Stephen Hines 392593a894650e81be54173106ec266f0311cebebd3Stephen Hines return valid; 393593a894650e81be54173106ec266f0311cebebd3Stephen Hines} 394593a894650e81be54173106ec266f0311cebebd3Stephen Hines 395593a894650e81be54173106ec266f0311cebebd3Stephen Hines} // namespace slang 396