slang_rs_export_foreach.cpp revision 688e64b2d56e4218c680b9d6523c5de672f55757
1593a894650e81be54173106ec266f0311cebebd3Stephen Hines/*
2593a894650e81be54173106ec266f0311cebebd3Stephen Hines * Copyright 2011, 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"
31593a894650e81be54173106ec266f0311cebebd3Stephen Hines
32593a894650e81be54173106ec266f0311cebebd3Stephen Hinesnamespace slang {
33593a894650e81be54173106ec266f0311cebebd3Stephen Hines
34b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesnamespace {
35b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
36b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesstatic void ReportNameError(clang::Diagnostic *Diags,
37b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                            const clang::ParmVarDecl *PVD) {
38b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  slangAssert(Diags && PVD);
39b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  const clang::SourceManager &SM = Diags->getSourceManager();
40b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
41b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  Diags->Report(clang::FullSourceLoc(PVD->getLocation(), SM),
42b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                Diags->getCustomDiagID(clang::Diagnostic::Error,
43b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                "Duplicate parameter entry (by position/name): '%0'"))
44b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines       << PVD->getName();
45b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  return;
46b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines}
47b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
48b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines}  // namespace
49b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
50b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// This function takes care of additional validation and construction of
51b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines// parameters related to forEach_* reflection.
52b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hinesbool RSExportForEach::validateAndConstructParams(
53b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    RSContext *Context, const clang::FunctionDecl *FD) {
54b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  slangAssert(Context && FD);
55b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  bool valid = true;
56b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  clang::ASTContext &C = Context->getASTContext();
57b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  clang::Diagnostic *Diags = Context->getDiagnostics();
58b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
59b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (!isRootRSFunc(FD)) {
60b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    slangAssert(false && "must be called on compute root function!");
61b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
62b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
63b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  numParams = FD->getNumParams();
64b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  slangAssert(numParams > 0);
65b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
66b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  // Compute root functions are required to return a void type for now
67b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FD->getResultType().getCanonicalType() != C.VoidTy) {
68b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    Diags->Report(
69b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        clang::FullSourceLoc(FD->getLocation(), Diags->getSourceManager()),
70b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        Diags->getCustomDiagID(clang::Diagnostic::Error,
71b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                               "compute root() is required to return a "
72b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                               "void type"));
73b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    valid = false;
74b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
75b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
76b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  // Validate remaining parameter types
77b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  // TODO(all): Add support for LOD/face when we have them
78b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
794ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  size_t i = 0;
804ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
814ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  clang::QualType QT = PVD->getType().getCanonicalType();
824ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
834ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  // Check for const T1 *in
844ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) {
854ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    mIn = PVD;
864ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    i++;  // advance parameter pointer
874ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
884ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
894ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  // Check for T2 *out
904ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (i < numParams) {
914ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    PVD = FD->getParamDecl(i);
924ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    QT = PVD->getType().getCanonicalType();
934ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    if (QT->isPointerType() && !QT->getPointeeType().isConstQualified()) {
944ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      mOut = PVD;
954ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      i++;  // advance parameter pointer
964ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    }
974ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
984ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
994ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (!mIn && !mOut) {
1004ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    Diags->Report(
1014ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines        clang::FullSourceLoc(FD->getLocation(),
1024ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines                             Diags->getSourceManager()),
1034ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines        Diags->getCustomDiagID(clang::Diagnostic::Error,
1044ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines                               "Compute root() must have at least one "
1054ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines                               "parameter for in or out"));
1064ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    valid = false;
1074ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
1084ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1094ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  // Check for T3 *usrData
1104ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (i < numParams) {
1114ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    PVD = FD->getParamDecl(i);
1124ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    QT = PVD->getType().getCanonicalType();
1134ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) {
1144ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      mUsrData = PVD;
1154ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      i++;  // advance parameter pointer
1164ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    }
1174ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
1184ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1194ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  while (i < numParams) {
1204ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    PVD = FD->getParamDecl(i);
1214ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    QT = PVD->getType().getCanonicalType();
1224ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1234ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    if (QT.getUnqualifiedType() != C.UnsignedIntTy) {
1244ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      Diags->Report(
1254ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          clang::FullSourceLoc(PVD->getLocation(),
1264ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines                               Diags->getSourceManager()),
1274ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          Diags->getCustomDiagID(clang::Diagnostic::Error,
1284ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines                                 "Unexpected root() parameter '%0' "
1294ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines                                 "of type '%1'"))
1304ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          << PVD->getName() << PVD->getType().getAsString();
1314ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      valid = false;
1324ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    } else {
1334ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      llvm::StringRef ParamName = PVD->getName();
134b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      if (ParamName.equals("x")) {
135b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        if (mX) {
136b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          ReportNameError(Diags, PVD);
137b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          valid = false;
1384ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines        } else if (mY) {
1394ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          // Can't go back to X after skipping Y
1404ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          ReportNameError(Diags, PVD);
1414ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          valid = false;
142b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else {
143b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mX = PVD;
144b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        }
145b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      } else if (ParamName.equals("y")) {
146b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        if (mY) {
147b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          ReportNameError(Diags, PVD);
148b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          valid = false;
149b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else {
150b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mY = PVD;
151b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        }
152b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      } else {
1534ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines        if (!mX && !mY) {
154b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mX = PVD;
155b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else if (!mY) {
156b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mY = PVD;
157b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else {
158b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          Diags->Report(
159b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines              clang::FullSourceLoc(PVD->getLocation(),
160b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                   Diags->getSourceManager()),
161b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines              Diags->getCustomDiagID(clang::Diagnostic::Error,
162b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                     "Unexpected root() parameter '%0' "
163b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                     "of type '%1'"))
164b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines              << PVD->getName() << PVD->getType().getAsString();
165b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          valid = false;
166b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        }
167b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      }
168b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    }
1694ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1704ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    i++;
171b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
172b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
1734ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  mMetadataEncoding = 0;
1744ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (valid) {
1754ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    // Set up the bitwise metadata encoding for runtime argument passing.
1764ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    mMetadataEncoding |= (mIn ?       0x01 : 0);
1774ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    mMetadataEncoding |= (mOut ?      0x02 : 0);
1784ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    mMetadataEncoding |= (mUsrData ?  0x04 : 0);
1794ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    mMetadataEncoding |= (mX ?        0x08 : 0);
1804ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    mMetadataEncoding |= (mY ?        0x10 : 0);
181b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
182b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
183b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  return valid;
184b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines}
185b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
186593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context,
187593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                         const clang::FunctionDecl *FD) {
188b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  slangAssert(Context && FD);
189593a894650e81be54173106ec266f0311cebebd3Stephen Hines  llvm::StringRef Name = FD->getName();
190b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  RSExportForEach *FE;
191593a894650e81be54173106ec266f0311cebebd3Stephen Hines
192593a894650e81be54173106ec266f0311cebebd3Stephen Hines  slangAssert(!Name.empty() && "Function must have a name");
193593a894650e81be54173106ec266f0311cebebd3Stephen Hines
194b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  FE = new RSExportForEach(Context, Name, FD);
195593a894650e81be54173106ec266f0311cebebd3Stephen Hines
196b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (!FE->validateAndConstructParams(Context, FD)) {
197b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    return NULL;
198593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
199593a894650e81be54173106ec266f0311cebebd3Stephen Hines
200593a894650e81be54173106ec266f0311cebebd3Stephen Hines  clang::ASTContext &Ctx = Context->getASTContext();
201593a894650e81be54173106ec266f0311cebebd3Stephen Hines
202593a894650e81be54173106ec266f0311cebebd3Stephen Hines  std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_foreach_param:");
203b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  Id.append(FE->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX);
204593a894650e81be54173106ec266f0311cebebd3Stephen Hines
205593a894650e81be54173106ec266f0311cebebd3Stephen Hines  // Extract the usrData parameter (if we have one)
206b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FE->mUsrData) {
207b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    const clang::ParmVarDecl *PVD = FE->mUsrData;
208593a894650e81be54173106ec266f0311cebebd3Stephen Hines    clang::QualType QT = PVD->getType().getCanonicalType();
209593a894650e81be54173106ec266f0311cebebd3Stephen Hines    slangAssert(QT->isPointerType() &&
210593a894650e81be54173106ec266f0311cebebd3Stephen Hines                QT->getPointeeType().isConstQualified());
211593a894650e81be54173106ec266f0311cebebd3Stephen Hines
212593a894650e81be54173106ec266f0311cebebd3Stephen Hines    const clang::ASTContext &C = Context->getASTContext();
213593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() ==
214593a894650e81be54173106ec266f0311cebebd3Stephen Hines        C.VoidTy) {
215593a894650e81be54173106ec266f0311cebebd3Stephen Hines      // In the case of using const void*, we can't reflect an appopriate
216593a894650e81be54173106ec266f0311cebebd3Stephen Hines      // Java type, so we fall back to just reflecting the ain/aout parameters
217b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      FE->mUsrData = NULL;
218593a894650e81be54173106ec266f0311cebebd3Stephen Hines    } else {
219b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      clang::RecordDecl *RD =
220b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          clang::RecordDecl::Create(Ctx, clang::TTK_Struct,
221b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    Ctx.getTranslationUnitDecl(),
222b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    clang::SourceLocation(),
223b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    clang::SourceLocation(),
224b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    &Ctx.Idents.get(Id));
225b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
226593a894650e81be54173106ec266f0311cebebd3Stephen Hines      llvm::StringRef ParamName = PVD->getName();
227593a894650e81be54173106ec266f0311cebebd3Stephen Hines      clang::FieldDecl *FD =
228593a894650e81be54173106ec266f0311cebebd3Stephen Hines          clang::FieldDecl::Create(Ctx,
229593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   RD,
230593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   clang::SourceLocation(),
231593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   clang::SourceLocation(),
232593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   PVD->getIdentifier(),
233593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   QT->getPointeeType(),
234593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   NULL,
2351688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao                                   /* BitWidth = */ NULL,
2361688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao                                   /* Mutable = */ false,
2371688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao                                   /* HasInit = */ false);
238593a894650e81be54173106ec266f0311cebebd3Stephen Hines      RD->addDecl(FD);
239b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      RD->completeDefinition();
240b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
241b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      // Create an export type iff we have a valid usrData type
242b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      clang::QualType T = Ctx.getTagDeclType(RD);
243b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      slangAssert(!T.isNull());
244b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
245b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      RSExportType *ET = RSExportType::Create(Context, T.getTypePtr());
246b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
247b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      if (ET == NULL) {
248b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        fprintf(stderr, "Failed to export the function %s. There's at least "
249b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                        "one parameter whose type is not supported by the "
250b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                        "reflection\n", FE->getName().c_str());
251b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        return NULL;
252b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      }
253b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
254b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      slangAssert((ET->getClass() == RSExportType::ExportClassRecord) &&
255b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                  "Parameter packet must be a record");
256b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
257b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      FE->mParamPacketType = static_cast<RSExportRecordType *>(ET);
258593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
259593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
260593a894650e81be54173106ec266f0311cebebd3Stephen Hines
261b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FE->mIn) {
262b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    const clang::Type *T = FE->mIn->getType().getCanonicalType().getTypePtr();
263b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    FE->mInType = RSExportType::Create(Context, T);
264b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
265593a894650e81be54173106ec266f0311cebebd3Stephen Hines
266b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FE->mOut) {
267b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr();
268b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    FE->mOutType = RSExportType::Create(Context, T);
269593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
270593a894650e81be54173106ec266f0311cebebd3Stephen Hines
271b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  return FE;
272593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
273593a894650e81be54173106ec266f0311cebebd3Stephen Hines
274593a894650e81be54173106ec266f0311cebebd3Stephen Hinesbool RSExportForEach::isRSForEachFunc(const clang::FunctionDecl *FD) {
275593a894650e81be54173106ec266f0311cebebd3Stephen Hines  // We currently support only compute root() being exported via forEach
276593a894650e81be54173106ec266f0311cebebd3Stephen Hines  if (!isRootRSFunc(FD)) {
277593a894650e81be54173106ec266f0311cebebd3Stephen Hines    return false;
278593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
279593a894650e81be54173106ec266f0311cebebd3Stephen Hines
280b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FD->getNumParams() == 0) {
281593a894650e81be54173106ec266f0311cebebd3Stephen Hines    // Graphics compute function
282593a894650e81be54173106ec266f0311cebebd3Stephen Hines    return false;
283593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
284593a894650e81be54173106ec266f0311cebebd3Stephen Hines  return true;
285593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
286593a894650e81be54173106ec266f0311cebebd3Stephen Hines
287593a894650e81be54173106ec266f0311cebebd3Stephen Hinesbool RSExportForEach::validateSpecialFuncDecl(clang::Diagnostic *Diags,
288593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                              const clang::FunctionDecl *FD) {
289b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  slangAssert(Diags && FD);
290593a894650e81be54173106ec266f0311cebebd3Stephen Hines  bool valid = true;
291593a894650e81be54173106ec266f0311cebebd3Stephen Hines  const clang::ASTContext &C = FD->getASTContext();
292593a894650e81be54173106ec266f0311cebebd3Stephen Hines
293593a894650e81be54173106ec266f0311cebebd3Stephen Hines  if (isRootRSFunc(FD)) {
294593a894650e81be54173106ec266f0311cebebd3Stephen Hines    unsigned int numParams = FD->getNumParams();
295593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (numParams == 0) {
296593a894650e81be54173106ec266f0311cebebd3Stephen Hines      // Graphics root function, so verify that it returns an int
297593a894650e81be54173106ec266f0311cebebd3Stephen Hines      if (FD->getResultType().getCanonicalType() != C.IntTy) {
298593a894650e81be54173106ec266f0311cebebd3Stephen Hines        Diags->Report(
299593a894650e81be54173106ec266f0311cebebd3Stephen Hines            clang::FullSourceLoc(FD->getLocation(), Diags->getSourceManager()),
300593a894650e81be54173106ec266f0311cebebd3Stephen Hines            Diags->getCustomDiagID(clang::Diagnostic::Error,
301593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   "root(void) is required to return "
302593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   "an int for graphics usage"));
303593a894650e81be54173106ec266f0311cebebd3Stephen Hines        valid = false;
304593a894650e81be54173106ec266f0311cebebd3Stephen Hines      }
305593a894650e81be54173106ec266f0311cebebd3Stephen Hines    } else {
306b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      slangAssert(false &&
307b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          "Should not call validateSpecialFuncDecl() on compute root()");
308593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
309688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) {
310593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (FD->getNumParams() != 0) {
311593a894650e81be54173106ec266f0311cebebd3Stephen Hines      Diags->Report(
312593a894650e81be54173106ec266f0311cebebd3Stephen Hines          clang::FullSourceLoc(FD->getLocation(), Diags->getSourceManager()),
313593a894650e81be54173106ec266f0311cebebd3Stephen Hines          Diags->getCustomDiagID(clang::Diagnostic::Error,
314688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines                                 "%0(void) is required to have no "
315688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines                                 "parameters")) << FD->getName();
316593a894650e81be54173106ec266f0311cebebd3Stephen Hines      valid = false;
317593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
318593a894650e81be54173106ec266f0311cebebd3Stephen Hines
319593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (FD->getResultType().getCanonicalType() != C.VoidTy) {
320593a894650e81be54173106ec266f0311cebebd3Stephen Hines      Diags->Report(
321593a894650e81be54173106ec266f0311cebebd3Stephen Hines          clang::FullSourceLoc(FD->getLocation(), Diags->getSourceManager()),
322593a894650e81be54173106ec266f0311cebebd3Stephen Hines          Diags->getCustomDiagID(clang::Diagnostic::Error,
323688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines                                 "%0(void) is required to have a void "
324688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines                                 "return type")) << FD->getName();
325593a894650e81be54173106ec266f0311cebebd3Stephen Hines      valid = false;
326593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
327593a894650e81be54173106ec266f0311cebebd3Stephen Hines  } else {
328688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    slangAssert(false && "must be called on root, init or .rs.dtor function!");
329593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
330593a894650e81be54173106ec266f0311cebebd3Stephen Hines
331593a894650e81be54173106ec266f0311cebebd3Stephen Hines  return valid;
332593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
333593a894650e81be54173106ec266f0311cebebd3Stephen Hines
334593a894650e81be54173106ec266f0311cebebd3Stephen Hines}  // namespace slang
335