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
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,
5199999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    const clang::FunctionDecl *FD) {
5209ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // Anything tagged as a kernel is definitely used with ForEach.
5219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (FD->hasAttr<clang::KernelAttr>()) {
5229ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    return true;
5239ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
5249ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
5257b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  if (isGraphicsRootRSFunc(targetAPI, FD)) {
5269999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    return false;
5279999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  }
5289999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines
5297b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  // Check if first parameter is a pointer (which is required for ForEach).
5307b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  unsigned int numParams = FD->getNumParams();
5317b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines
5327b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  if (numParams > 0) {
5337b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
5347b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    clang::QualType QT = PVD->getType().getCanonicalType();
5357b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines
5367b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    if (QT->isPointerType()) {
5377b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines      return true;
5387b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    }
5397b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines
5407b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // Any non-graphics root() is automatically a ForEach candidate.
5417b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // At this point, however, we know that it is not going to be a valid
5427b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // compute root() function (due to not having a pointer parameter). We
5437b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // still want to return true here, so that we can issue appropriate
5447b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // diagnostics.
5457b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    if (isRootRSFunc(FD)) {
5467b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines      return true;
5477b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    }
5489999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  }
5499999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines
5507b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  return false;
551593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
552593a894650e81be54173106ec266f0311cebebd3Stephen Hines
5539207a2e495c8363606861e4f034504ec5c153dabLogan Chienbool
554fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen HinesRSExportForEach::validateSpecialFuncDecl(int targetAPI,
555fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen Hines                                         clang::DiagnosticsEngine *DiagEngine,
5569207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                         clang::FunctionDecl const *FD) {
5579207a2e495c8363606861e4f034504ec5c153dabLogan Chien  slangAssert(DiagEngine && FD);
558593a894650e81be54173106ec266f0311cebebd3Stephen Hines  bool valid = true;
559593a894650e81be54173106ec266f0311cebebd3Stephen Hines  const clang::ASTContext &C = FD->getASTContext();
5609999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  const clang::QualType &IntType = FD->getASTContext().IntTy;
561593a894650e81be54173106ec266f0311cebebd3Stephen Hines
5629999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  if (isGraphicsRootRSFunc(targetAPI, FD)) {
5639999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
5649999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      // Legacy graphics root function
5659999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
5669999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      clang::QualType QT = PVD->getType().getCanonicalType();
5679999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      if (QT != IntType) {
5689207a2e495c8363606861e4f034504ec5c153dabLogan Chien        DiagEngine->Report(
5699999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines          clang::FullSourceLoc(PVD->getLocation(),
5709207a2e495c8363606861e4f034504ec5c153dabLogan Chien                               DiagEngine->getSourceManager()),
5719207a2e495c8363606861e4f034504ec5c153dabLogan Chien          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
5729999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                      "invalid parameter type for legacy "
5739999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                      "graphics root() function: %0"))
5749999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines          << PVD->getType();
575593a894650e81be54173106ec266f0311cebebd3Stephen Hines        valid = false;
576593a894650e81be54173106ec266f0311cebebd3Stephen Hines      }
5779999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    }
5789999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines
5799999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    // Graphics root function, so verify that it returns an int
5809999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    if (FD->getResultType().getCanonicalType() != IntType) {
5819999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      DiagEngine->Report(
5829999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines        clang::FullSourceLoc(FD->getLocation(),
5839999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                             DiagEngine->getSourceManager()),
5849999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
5859999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                    "root() is required to return "
5869999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                    "an int for graphics usage"));
5879999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      valid = false;
588593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
589688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) {
590593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (FD->getNumParams() != 0) {
5919207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine->Report(
5929207a2e495c8363606861e4f034504ec5c153dabLogan Chien          clang::FullSourceLoc(FD->getLocation(),
5939207a2e495c8363606861e4f034504ec5c153dabLogan Chien                               DiagEngine->getSourceManager()),
5949207a2e495c8363606861e4f034504ec5c153dabLogan Chien          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
5959207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "%0(void) is required to have no "
5969207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "parameters")) << FD->getName();
597593a894650e81be54173106ec266f0311cebebd3Stephen Hines      valid = false;
598593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
599593a894650e81be54173106ec266f0311cebebd3Stephen Hines
600593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (FD->getResultType().getCanonicalType() != C.VoidTy) {
6019207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine->Report(
6029207a2e495c8363606861e4f034504ec5c153dabLogan Chien          clang::FullSourceLoc(FD->getLocation(),
6039207a2e495c8363606861e4f034504ec5c153dabLogan Chien                               DiagEngine->getSourceManager()),
6049207a2e495c8363606861e4f034504ec5c153dabLogan Chien          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
6059207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "%0(void) is required to have a void "
6069207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "return type")) << FD->getName();
607593a894650e81be54173106ec266f0311cebebd3Stephen Hines      valid = false;
608593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
609593a894650e81be54173106ec266f0311cebebd3Stephen Hines  } else {
610688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    slangAssert(false && "must be called on root, init or .rs.dtor function!");
611593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
612593a894650e81be54173106ec266f0311cebebd3Stephen Hines
613593a894650e81be54173106ec266f0311cebebd3Stephen Hines  return valid;
614593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
615593a894650e81be54173106ec266f0311cebebd3Stephen Hines
616593a894650e81be54173106ec266f0311cebebd3Stephen Hines}  // namespace slang
617