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