slang_rs_export_foreach.cpp revision 0f2a2397df53a1bb74609abe3c27719bc7e3c328
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"
2223c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "clang/AST/Attr.h"
23593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "clang/AST/Decl.h"
24b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines#include "clang/AST/TypeLoc.h"
25593a894650e81be54173106ec266f0311cebebd3Stephen Hines
2623c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/DerivedTypes.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;
609207a2e495c8363606861e4f034504ec5c153dabLogan Chien  clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
61b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
62b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  numParams = FD->getNumParams();
63b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
647b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  if (Context->getTargetAPI() < SLANG_JB_TARGET_API) {
657b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    if (!isRootRSFunc(FD)) {
667b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines      DiagEngine->Report(
677b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines        clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()),
687b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
697b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                    "Non-root compute kernel %0() is "
707b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                    "not supported in SDK levels %1-%2"))
717b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines        << FD->getName()
727b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines        << SLANG_MINIMUM_TARGET_API
737b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines        << (SLANG_JB_TARGET_API - 1);
747b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines      return false;
757b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    }
767b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  }
777b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines
789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  mResultType = FD->getResultType().getCanonicalType();
790f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  // Compute kernel functions are defined differently when the
800f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  // "__attribute__((kernel))" is set.
819ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (FD->hasAttr<clang::KernelAttr>()) {
820f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    valid |= validateAndConstructKernelParams(Context, FD);
830f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  } else {
840f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    valid |= validateAndConstructOldStyleParams(Context, FD);
859ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
860f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  valid |= setSignatureMetadata(Context, FD);
870f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  return valid;
880f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet}
899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
900f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouilletbool RSExportForEach::validateAndConstructOldStyleParams(RSContext *Context,
910f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    const clang::FunctionDecl *FD) {
920f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  slangAssert(Context && FD);
939ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // If numParams is 0, we already marked this as a graphics root().
949ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  slangAssert(numParams > 0);
959ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
960f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  bool valid = true;
970f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
980f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet
990f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  // Compute kernel functions of this style are required to return a void type.
1000f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  clang::ASTContext &C = Context->getASTContext();
1019ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (mResultType != C.VoidTy) {
1029207a2e495c8363606861e4f034504ec5c153dabLogan Chien    DiagEngine->Report(
1039207a2e495c8363606861e4f034504ec5c153dabLogan Chien      clang::FullSourceLoc(FD->getLocation(), DiagEngine->getSourceManager()),
1049207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1057b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                  "Compute kernel %0() is required to return a "
1067b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                  "void type")) << FD->getName();
107b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    valid = false;
108b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
109b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
110b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  // Validate remaining parameter types
111b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  // TODO(all): Add support for LOD/face when we have them
112b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
1134ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  size_t i = 0;
1144ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
1154ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  clang::QualType QT = PVD->getType().getCanonicalType();
1164ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1174ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  // Check for const T1 *in
1184ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) {
1194ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    mIn = PVD;
1204ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    i++;  // advance parameter pointer
1214ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
1224ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1234ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  // Check for T2 *out
1244ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (i < numParams) {
1254ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    PVD = FD->getParamDecl(i);
1264ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    QT = PVD->getType().getCanonicalType();
1274ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    if (QT->isPointerType() && !QT->getPointeeType().isConstQualified()) {
1284ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      mOut = PVD;
1294ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      i++;  // advance parameter pointer
1304ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    }
1314ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
1324ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1334ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (!mIn && !mOut) {
1349207a2e495c8363606861e4f034504ec5c153dabLogan Chien    DiagEngine->Report(
1359207a2e495c8363606861e4f034504ec5c153dabLogan Chien      clang::FullSourceLoc(FD->getLocation(),
1369207a2e495c8363606861e4f034504ec5c153dabLogan Chien                           DiagEngine->getSourceManager()),
1379207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1387b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                  "Compute kernel %0() must have at least one "
1397b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                  "parameter for in or out")) << FD->getName();
1404ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    valid = false;
1414ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
1424ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1434ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  // Check for T3 *usrData
1444ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  if (i < numParams) {
1454ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    PVD = FD->getParamDecl(i);
1464ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    QT = PVD->getType().getCanonicalType();
1474ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    if (QT->isPointerType() && QT->getPointeeType().isConstQualified()) {
1484ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      mUsrData = PVD;
1494ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      i++;  // advance parameter pointer
1504ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    }
1514ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  }
1524ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1534ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines  while (i < numParams) {
1544ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    PVD = FD->getParamDecl(i);
1554ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    QT = PVD->getType().getCanonicalType();
1564ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
1574ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    if (QT.getUnqualifiedType() != C.UnsignedIntTy) {
1589207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine->Report(
1599207a2e495c8363606861e4f034504ec5c153dabLogan Chien        clang::FullSourceLoc(PVD->getLocation(),
1609207a2e495c8363606861e4f034504ec5c153dabLogan Chien                             DiagEngine->getSourceManager()),
1619207a2e495c8363606861e4f034504ec5c153dabLogan Chien        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1627b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                    "Unexpected kernel %0() parameter '%1' "
1637b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                    "of type '%2'"))
1647b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines        << FD->getName() << PVD->getName() << PVD->getType().getAsString();
1654ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      valid = false;
1664ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    } else {
1674ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines      llvm::StringRef ParamName = PVD->getName();
168b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      if (ParamName.equals("x")) {
169b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        if (mX) {
1709207a2e495c8363606861e4f034504ec5c153dabLogan Chien          ReportNameError(DiagEngine, PVD);
171b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          valid = false;
1724ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines        } else if (mY) {
1734ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          // Can't go back to X after skipping Y
1749207a2e495c8363606861e4f034504ec5c153dabLogan Chien          ReportNameError(DiagEngine, PVD);
1754ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines          valid = false;
176b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else {
177b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mX = PVD;
178b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        }
179b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      } else if (ParamName.equals("y")) {
180b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        if (mY) {
1819207a2e495c8363606861e4f034504ec5c153dabLogan Chien          ReportNameError(DiagEngine, PVD);
182b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          valid = false;
183b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else {
184b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mY = PVD;
185b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        }
186b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      } else {
1874ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines        if (!mX && !mY) {
188b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mX = PVD;
189b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else if (!mY) {
190b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          mY = PVD;
191b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        } else {
1929207a2e495c8363606861e4f034504ec5c153dabLogan Chien          DiagEngine->Report(
1939207a2e495c8363606861e4f034504ec5c153dabLogan Chien            clang::FullSourceLoc(PVD->getLocation(),
1949207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                 DiagEngine->getSourceManager()),
1959207a2e495c8363606861e4f034504ec5c153dabLogan Chien            DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
1967b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                        "Unexpected kernel %0() parameter '%1' "
1977b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines                                        "of type '%2'"))
1987b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines            << FD->getName() << PVD->getName() << PVD->getType().getAsString();
199b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          valid = false;
200b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        }
201b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      }
202b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    }
2034ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines
2044ccf75e55fe460a8daa49247d7e5a797329c71a6Stephen Hines    i++;
205b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
206b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
207b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  return valid;
208b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines}
209b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
2109ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2119ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hinesbool RSExportForEach::validateAndConstructKernelParams(RSContext *Context,
2129ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    const clang::FunctionDecl *FD) {
2139ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  slangAssert(Context && FD);
2149ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  bool valid = true;
2159ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  clang::ASTContext &C = Context->getASTContext();
2169ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
2179ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2189ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (Context->getTargetAPI() < SLANG_JB_MR1_TARGET_API) {
2199ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    DiagEngine->Report(
2209ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      clang::FullSourceLoc(FD->getLocation(),
2219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                           DiagEngine->getSourceManager()),
2229ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
2239ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "Compute kernel %0() targeting SDK levels "
2249ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "%1-%2 may not use pass-by-value with "
2259ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "__attribute__((kernel))"))
2269ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      << FD->getName() << SLANG_MINIMUM_TARGET_API
2279ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      << (SLANG_JB_MR1_TARGET_API - 1);
2289ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    return false;
2299ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
2309ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2319ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // Denote that we are indeed a pass-by-value kernel.
2320f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  mIsKernelStyle = true;
2339ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2349ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (mResultType != C.VoidTy) {
2350f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    mHasReturnType = true;
2369ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
2379ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2389ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (mResultType->isPointerType()) {
2399ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    DiagEngine->Report(
2409ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      clang::FullSourceLoc(FD->getTypeSpecStartLoc(),
2419ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                           DiagEngine->getSourceManager()),
2429ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
2439ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "Compute kernel %0() cannot return a "
2449ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "pointer type: '%1'"))
2459ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      << FD->getName() << mResultType.getAsString();
2469ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    valid = false;
2479ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
2489ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // Validate remaining parameter types
2509ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // TODO(all): Add support for LOD/face when we have them
2519ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2529ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  size_t i = 0;
2539ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  const clang::ParmVarDecl *PVD = NULL;
2549ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  clang::QualType QT;
2559ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2569ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (i < numParams) {
2579ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    PVD = FD->getParamDecl(i);
2589ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    QT = PVD->getType().getCanonicalType();
2599ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2609ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    if (QT->isPointerType()) {
2619ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      DiagEngine->Report(
2629ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        clang::FullSourceLoc(PVD->getLocation(),
2639ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                             DiagEngine->getSourceManager()),
2649ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
2659ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                    "Compute kernel %0() cannot have "
2669ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                    "parameter '%1' of pointer type: '%2'"))
2679ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        << FD->getName() << PVD->getName() << PVD->getType().getAsString();
2689ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      valid = false;
2699ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    } else if (QT.getUnqualifiedType() == C.UnsignedIntTy) {
2709ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      // First parameter is either input or x, y (iff it is uint32_t).
2719ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      llvm::StringRef ParamName = PVD->getName();
2729ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      if (ParamName.equals("x")) {
2739ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        mX = PVD;
2749ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      } else if (ParamName.equals("y")) {
2759ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        mY = PVD;
2769ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      } else {
2779ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        mIn = PVD;
2789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      }
2799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    } else {
2809ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      mIn = PVD;
2819ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    }
2829ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2839ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    i++;  // advance parameter pointer
2849ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
2859ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2869ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // Check that we have at least one allocation to use for dimensions.
2870f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  if (valid && !mIn && !mHasReturnType) {
2889ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    DiagEngine->Report(
2899ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      clang::FullSourceLoc(FD->getLocation(),
2909ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                           DiagEngine->getSourceManager()),
2919ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
2929ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "Compute kernel %0() must have at least one "
2939ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "input parameter or a non-void return "
2949ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                  "type")) << FD->getName();
2959ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    valid = false;
2969ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
2979ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
2989ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // TODO: Abstract this block away, since it is duplicate code.
2999ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  while (i < numParams) {
3009ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    PVD = FD->getParamDecl(i);
3019ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    QT = PVD->getType().getCanonicalType();
3029ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
3039ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    if (QT.getUnqualifiedType() != C.UnsignedIntTy) {
3049ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      DiagEngine->Report(
3059ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        clang::FullSourceLoc(PVD->getLocation(),
3069ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                             DiagEngine->getSourceManager()),
3079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
3089ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                    "Unexpected kernel %0() parameter '%1' "
3099ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                    "of type '%2'"))
3109ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        << FD->getName() << PVD->getName() << PVD->getType().getAsString();
3119ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      valid = false;
3129ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    } else {
3139ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      llvm::StringRef ParamName = PVD->getName();
3149ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      if (ParamName.equals("x")) {
3159ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        if (mX) {
3169ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          ReportNameError(DiagEngine, PVD);
3179ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          valid = false;
3189ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        } else if (mY) {
3199ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          // Can't go back to X after skipping Y
3209ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          ReportNameError(DiagEngine, PVD);
3219ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          valid = false;
3229ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        } else {
3239ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          mX = PVD;
3249ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        }
3259ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      } else if (ParamName.equals("y")) {
3269ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        if (mY) {
3279ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          ReportNameError(DiagEngine, PVD);
3289ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          valid = false;
3299ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        } else {
3309ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          mY = PVD;
3319ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        }
3329ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      } else {
3339ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        if (!mX && !mY) {
3349ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          mX = PVD;
3359ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        } else if (!mY) {
3369ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          mY = PVD;
3379ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        } else {
3389ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          DiagEngine->Report(
3399ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines            clang::FullSourceLoc(PVD->getLocation(),
3409ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                 DiagEngine->getSourceManager()),
3419ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines            DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
3429ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                        "Unexpected kernel %0() parameter '%1' "
3439ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines                                        "of type '%2'"))
3449ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines            << FD->getName() << PVD->getName() << PVD->getType().getAsString();
3459ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines          valid = false;
3469ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines        }
3479ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      }
3489ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    }
3499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
3509ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    i++;  // advance parameter pointer
3519ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
3520f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  return valid;
3530f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet}
3549ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
3550f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouilletbool RSExportForEach::setSignatureMetadata(RSContext *Context,
3560f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet                                           const clang::FunctionDecl *FD) {
3579ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  mSignatureMetadata = 0;
3580f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  bool valid = true;
3590f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet
3600f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  if (mIsKernelStyle) {
3619ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    slangAssert(mOut == NULL);
3629ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    slangAssert(mUsrData == NULL);
3630f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  } else {
3640f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    slangAssert(!mHasReturnType);
3659ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
3669ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
3670f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  // Set up the bitwise metadata encoding for runtime argument passing.
3680f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  // TODO: If this bit field is re-used from C++ code, define the values in a header.
3690f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  const bool HasOut = mOut || mHasReturnType;
3700f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  mSignatureMetadata |= (mIn ?            0x01 : 0);
3710f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  mSignatureMetadata |= (HasOut ?         0x02 : 0);
3720f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  mSignatureMetadata |= (mUsrData ?       0x04 : 0);
3730f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  mSignatureMetadata |= (mX ?             0x08 : 0);
3740f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  mSignatureMetadata |= (mY ?             0x10 : 0);
3750f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  mSignatureMetadata |= (mIsKernelStyle ? 0x20 : 0);  // pass-by-value
3760f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet
3770f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  if (Context->getTargetAPI() < SLANG_ICS_TARGET_API) {
3780f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    // APIs before ICS cannot skip between parameters. It is ok, however, for
3790f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    // them to omit further parameters (i.e. skipping X is ok if you skip Y).
3800f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    if (mSignatureMetadata != 0x1f &&  // In, Out, UsrData, X, Y
3810f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet        mSignatureMetadata != 0x0f &&  // In, Out, UsrData, X
3820f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet        mSignatureMetadata != 0x07 &&  // In, Out, UsrData
3830f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet        mSignatureMetadata != 0x03 &&  // In, Out
3840f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet        mSignatureMetadata != 0x01) {  // In
3850f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet      clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics();
3860f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet      DiagEngine->Report(clang::FullSourceLoc(FD->getLocation(),
3870f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet                                              DiagEngine->getSourceManager()),
3880f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet                         DiagEngine->getCustomDiagID(
3890f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet                             clang::DiagnosticsEngine::Error,
3900f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet                             "Compute kernel %0() targeting SDK levels "
3910f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet                             "%1-%2 may not skip parameters"))
3920f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet          << FD->getName() << SLANG_MINIMUM_TARGET_API
3930f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet          << (SLANG_ICS_TARGET_API - 1);
3940f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet      valid = false;
3950f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    }
3960f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  }
3979ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  return valid;
3989ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines}
3999ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
400593a894650e81be54173106ec266f0311cebebd3Stephen HinesRSExportForEach *RSExportForEach::Create(RSContext *Context,
401593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                         const clang::FunctionDecl *FD) {
402b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  slangAssert(Context && FD);
403593a894650e81be54173106ec266f0311cebebd3Stephen Hines  llvm::StringRef Name = FD->getName();
404b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  RSExportForEach *FE;
405593a894650e81be54173106ec266f0311cebebd3Stephen Hines
406593a894650e81be54173106ec266f0311cebebd3Stephen Hines  slangAssert(!Name.empty() && "Function must have a name");
407593a894650e81be54173106ec266f0311cebebd3Stephen Hines
408c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  FE = new RSExportForEach(Context, Name);
409593a894650e81be54173106ec266f0311cebebd3Stephen Hines
410b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (!FE->validateAndConstructParams(Context, FD)) {
411b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    return NULL;
412593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
413593a894650e81be54173106ec266f0311cebebd3Stephen Hines
414593a894650e81be54173106ec266f0311cebebd3Stephen Hines  clang::ASTContext &Ctx = Context->getASTContext();
415593a894650e81be54173106ec266f0311cebebd3Stephen Hines
416593a894650e81be54173106ec266f0311cebebd3Stephen Hines  std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_foreach_param:");
417b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  Id.append(FE->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX);
418593a894650e81be54173106ec266f0311cebebd3Stephen Hines
419593a894650e81be54173106ec266f0311cebebd3Stephen Hines  // Extract the usrData parameter (if we have one)
420b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FE->mUsrData) {
421b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    const clang::ParmVarDecl *PVD = FE->mUsrData;
422593a894650e81be54173106ec266f0311cebebd3Stephen Hines    clang::QualType QT = PVD->getType().getCanonicalType();
423593a894650e81be54173106ec266f0311cebebd3Stephen Hines    slangAssert(QT->isPointerType() &&
424593a894650e81be54173106ec266f0311cebebd3Stephen Hines                QT->getPointeeType().isConstQualified());
425593a894650e81be54173106ec266f0311cebebd3Stephen Hines
426593a894650e81be54173106ec266f0311cebebd3Stephen Hines    const clang::ASTContext &C = Context->getASTContext();
427593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() ==
428593a894650e81be54173106ec266f0311cebebd3Stephen Hines        C.VoidTy) {
429593a894650e81be54173106ec266f0311cebebd3Stephen Hines      // In the case of using const void*, we can't reflect an appopriate
430593a894650e81be54173106ec266f0311cebebd3Stephen Hines      // Java type, so we fall back to just reflecting the ain/aout parameters
431b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      FE->mUsrData = NULL;
432593a894650e81be54173106ec266f0311cebebd3Stephen Hines    } else {
433b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      clang::RecordDecl *RD =
434b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines          clang::RecordDecl::Create(Ctx, clang::TTK_Struct,
435b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    Ctx.getTranslationUnitDecl(),
436b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    clang::SourceLocation(),
437b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    clang::SourceLocation(),
438b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                                    &Ctx.Idents.get(Id));
439b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
440593a894650e81be54173106ec266f0311cebebd3Stephen Hines      clang::FieldDecl *FD =
441593a894650e81be54173106ec266f0311cebebd3Stephen Hines          clang::FieldDecl::Create(Ctx,
442593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   RD,
443593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   clang::SourceLocation(),
444593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   clang::SourceLocation(),
445593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   PVD->getIdentifier(),
446593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   QT->getPointeeType(),
447593a894650e81be54173106ec266f0311cebebd3Stephen Hines                                   NULL,
4481688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao                                   /* BitWidth = */ NULL,
4491688a3c56851f235866d6870c89ddb20650cc030Shih-wei Liao                                   /* Mutable = */ false,
45043730fe3c839af391efe6bdf56b0479860121924Shih-wei Liao                                   /* HasInit = */ clang::ICIS_NoInit);
451593a894650e81be54173106ec266f0311cebebd3Stephen Hines      RD->addDecl(FD);
452b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      RD->completeDefinition();
453b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
454b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      // Create an export type iff we have a valid usrData type
455b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      clang::QualType T = Ctx.getTagDeclType(RD);
456b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      slangAssert(!T.isNull());
457b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
458b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      RSExportType *ET = RSExportType::Create(Context, T.getTypePtr());
459b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
460b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      if (ET == NULL) {
461b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        fprintf(stderr, "Failed to export the function %s. There's at least "
462b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                        "one parameter whose type is not supported by the "
463b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                        "reflection\n", FE->getName().c_str());
464b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines        return NULL;
465b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      }
466b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
467b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      slangAssert((ET->getClass() == RSExportType::ExportClassRecord) &&
468b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines                  "Parameter packet must be a record");
469b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines
470b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines      FE->mParamPacketType = static_cast<RSExportRecordType *>(ET);
471593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
472593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
473593a894650e81be54173106ec266f0311cebebd3Stephen Hines
474b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FE->mIn) {
475b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    const clang::Type *T = FE->mIn->getType().getCanonicalType().getTypePtr();
476b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    FE->mInType = RSExportType::Create(Context, T);
4770f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet    if (FE->mIsKernelStyle) {
4789ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines      slangAssert(FE->mInType);
4799ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    }
480b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  }
481593a894650e81be54173106ec266f0311cebebd3Stephen Hines
4820f2a2397df53a1bb74609abe3c27719bc7e3c328Jean-Luc Brouillet  if (FE->mIsKernelStyle && FE->mHasReturnType) {
4839ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    const clang::Type *T = FE->mResultType.getTypePtr();
4849ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    FE->mOutType = RSExportType::Create(Context, T);
4859ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    slangAssert(FE->mOutType);
4869ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  } else if (FE->mOut) {
487b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr();
488b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines    FE->mOutType = RSExportType::Create(Context, T);
489593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
490593a894650e81be54173106ec266f0311cebebd3Stephen Hines
491b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  return FE;
492593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
493593a894650e81be54173106ec266f0311cebebd3Stephen Hines
494c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen HinesRSExportForEach *RSExportForEach::CreateDummyRoot(RSContext *Context) {
495c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  slangAssert(Context);
496c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  llvm::StringRef Name = "root";
497c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  RSExportForEach *FE = new RSExportForEach(Context, Name);
498c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  FE->mDummyRoot = true;
499c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  return FE;
500c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines}
501c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines
5029999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isGraphicsRootRSFunc(int targetAPI,
5039999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                           const clang::FunctionDecl *FD) {
5049ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  if (FD->hasAttr<clang::KernelAttr>()) {
5059ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    return false;
5069ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
5079ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
508593a894650e81be54173106ec266f0311cebebd3Stephen Hines  if (!isRootRSFunc(FD)) {
509593a894650e81be54173106ec266f0311cebebd3Stephen Hines    return false;
510593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
511593a894650e81be54173106ec266f0311cebebd3Stephen Hines
512b5a89fbfcba6d8817c1c3700ed78bd6482cf1a5dStephen Hines  if (FD->getNumParams() == 0) {
5139999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    // Graphics root function
5149999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    return true;
515593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
516f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines
5179999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  // Check for legacy graphics root function (with single parameter).
518f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines  if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
519f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines    const clang::QualType &IntType = FD->getASTContext().IntTy;
5209999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    if (FD->getResultType().getCanonicalType() == IntType) {
5219999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      return true;
522f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines    }
523f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines  }
524f736d5a12269e7e74740b130cdca98d9839b31e6Stephen Hines
5259999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  return false;
5269999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines}
5279999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines
5289999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hinesbool RSExportForEach::isRSForEachFunc(int targetAPI,
529089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    clang::DiagnosticsEngine *DiagEngine,
5309999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    const clang::FunctionDecl *FD) {
531089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  slangAssert(DiagEngine && FD);
532089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  bool hasKernelAttr = FD->hasAttr<clang::KernelAttr>();
533089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
534089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  if (FD->getStorageClass() == clang::SC_Static) {
535089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    if (hasKernelAttr) {
536089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      DiagEngine->Report(
537089cde338148fbb75825aea4539ccdae8211ffefStephen Hines        clang::FullSourceLoc(FD->getLocation(),
538089cde338148fbb75825aea4539ccdae8211ffefStephen Hines                             DiagEngine->getSourceManager()),
539089cde338148fbb75825aea4539ccdae8211ffefStephen Hines        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
540089cde338148fbb75825aea4539ccdae8211ffefStephen Hines                                    "Invalid use of attribute kernel with "
541089cde338148fbb75825aea4539ccdae8211ffefStephen Hines                                    "static function declaration: %0"))
542089cde338148fbb75825aea4539ccdae8211ffefStephen Hines        << FD->getName();
543089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    }
544089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    return false;
545089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  }
546089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
5479ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  // Anything tagged as a kernel is definitely used with ForEach.
548089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  if (hasKernelAttr) {
5499ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines    return true;
5509ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines  }
5519ca96e70657cf5437a294213f56ba4768dc08ad2Stephen Hines
5527b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  if (isGraphicsRootRSFunc(targetAPI, FD)) {
5539999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    return false;
5549999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  }
5559999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines
5567b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  // Check if first parameter is a pointer (which is required for ForEach).
5577b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  unsigned int numParams = FD->getNumParams();
5587b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines
5597b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  if (numParams > 0) {
5607b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
5617b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    clang::QualType QT = PVD->getType().getCanonicalType();
5627b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines
5637b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    if (QT->isPointerType()) {
5647b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines      return true;
5657b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    }
5667b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines
5677b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // Any non-graphics root() is automatically a ForEach candidate.
5687b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // At this point, however, we know that it is not going to be a valid
5697b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // compute root() function (due to not having a pointer parameter). We
5707b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // still want to return true here, so that we can issue appropriate
5717b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    // diagnostics.
5727b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    if (isRootRSFunc(FD)) {
5737b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines      return true;
5747b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines    }
5759999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  }
5769999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines
5777b51b55e4467605a599e868a0dde7cb95c5ab76eStephen Hines  return false;
578593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
579593a894650e81be54173106ec266f0311cebebd3Stephen Hines
5809207a2e495c8363606861e4f034504ec5c153dabLogan Chienbool
581fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen HinesRSExportForEach::validateSpecialFuncDecl(int targetAPI,
582fbfd7f5fd97458b6b23437556025ac1d55e98fd4Stephen Hines                                         clang::DiagnosticsEngine *DiagEngine,
5839207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                         clang::FunctionDecl const *FD) {
5849207a2e495c8363606861e4f034504ec5c153dabLogan Chien  slangAssert(DiagEngine && FD);
585593a894650e81be54173106ec266f0311cebebd3Stephen Hines  bool valid = true;
586593a894650e81be54173106ec266f0311cebebd3Stephen Hines  const clang::ASTContext &C = FD->getASTContext();
5879999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  const clang::QualType &IntType = FD->getASTContext().IntTy;
588593a894650e81be54173106ec266f0311cebebd3Stephen Hines
5899999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines  if (isGraphicsRootRSFunc(targetAPI, FD)) {
5909999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
5919999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      // Legacy graphics root function
5929999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
5939999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      clang::QualType QT = PVD->getType().getCanonicalType();
5949999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      if (QT != IntType) {
5959207a2e495c8363606861e4f034504ec5c153dabLogan Chien        DiagEngine->Report(
5969999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines          clang::FullSourceLoc(PVD->getLocation(),
5979207a2e495c8363606861e4f034504ec5c153dabLogan Chien                               DiagEngine->getSourceManager()),
5989207a2e495c8363606861e4f034504ec5c153dabLogan Chien          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
5999999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                      "invalid parameter type for legacy "
6009999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                      "graphics root() function: %0"))
6019999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines          << PVD->getType();
602593a894650e81be54173106ec266f0311cebebd3Stephen Hines        valid = false;
603593a894650e81be54173106ec266f0311cebebd3Stephen Hines      }
6049999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    }
6059999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines
6069999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    // Graphics root function, so verify that it returns an int
6079999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    if (FD->getResultType().getCanonicalType() != IntType) {
6089999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      DiagEngine->Report(
6099999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines        clang::FullSourceLoc(FD->getLocation(),
6109999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                             DiagEngine->getSourceManager()),
6119999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
6129999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                    "root() is required to return "
6139999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines                                    "an int for graphics usage"));
6149999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines      valid = false;
615593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
616688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) {
617593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (FD->getNumParams() != 0) {
6189207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine->Report(
6199207a2e495c8363606861e4f034504ec5c153dabLogan Chien          clang::FullSourceLoc(FD->getLocation(),
6209207a2e495c8363606861e4f034504ec5c153dabLogan Chien                               DiagEngine->getSourceManager()),
6219207a2e495c8363606861e4f034504ec5c153dabLogan Chien          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
6229207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "%0(void) is required to have no "
6239207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "parameters")) << FD->getName();
624593a894650e81be54173106ec266f0311cebebd3Stephen Hines      valid = false;
625593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
626593a894650e81be54173106ec266f0311cebebd3Stephen Hines
627593a894650e81be54173106ec266f0311cebebd3Stephen Hines    if (FD->getResultType().getCanonicalType() != C.VoidTy) {
6289207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine->Report(
6299207a2e495c8363606861e4f034504ec5c153dabLogan Chien          clang::FullSourceLoc(FD->getLocation(),
6309207a2e495c8363606861e4f034504ec5c153dabLogan Chien                               DiagEngine->getSourceManager()),
6319207a2e495c8363606861e4f034504ec5c153dabLogan Chien          DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
6329207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "%0(void) is required to have a void "
6339207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                      "return type")) << FD->getName();
634593a894650e81be54173106ec266f0311cebebd3Stephen Hines      valid = false;
635593a894650e81be54173106ec266f0311cebebd3Stephen Hines    }
636593a894650e81be54173106ec266f0311cebebd3Stephen Hines  } else {
637688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    slangAssert(false && "must be called on root, init or .rs.dtor function!");
638593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
639593a894650e81be54173106ec266f0311cebebd3Stephen Hines
640593a894650e81be54173106ec266f0311cebebd3Stephen Hines  return valid;
641593a894650e81be54173106ec266f0311cebebd3Stephen Hines}
642593a894650e81be54173106ec266f0311cebebd3Stephen Hines
643593a894650e81be54173106ec266f0311cebebd3Stephen Hines}  // namespace slang
644