1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
29999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines * Copyright 2010-2012, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_context.h"
186315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <string>
2041ebf534161bb67f6207a070c1f6a895dc853408Zonr Chang
21e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/AST/ASTContext.h"
22fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "clang/AST/Attr.h"
239ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/AST/Decl.h"
249ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/AST/DeclBase.h"
25be27482cdeaf08576bc39b72a15d35d13014a636Logan#include "clang/AST/Mangle.h"
26e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/AST/Type.h"
27e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
28e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/Basic/Linkage.h"
29e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/Basic/TargetInfo.h"
3041ebf534161bb67f6207a070c1f6a895dc853408Zonr Chang
3123c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/LLVMContext.h"
3223c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines#include "llvm/IR/DataLayout.h"
33e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
346315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang.h"
356e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
365e306b944425a952fe744f59d828538137a59375David Gross#include "slang_backend.h"
37593a894650e81be54173106ec266f0311cebebd3Stephen Hines#include "slang_rs_export_foreach.h"
386315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_export_func.h"
39c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala#include "slang_rs_export_reduce.h"
406315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_export_type.h"
41e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "slang_rs_export_var.h"
42e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "slang_rs_exportable.h"
436315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_pragma_handler.h"
44e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "slang_rs_reflection.h"
45eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala#include "slang_rs_special_func.h"
469ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
47e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
489ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
499e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen HinesRSContext::RSContext(clang::Preprocessor &PP,
509e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines                     clang::ASTContext &Ctx,
513fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines                     const clang::TargetInfo &Target,
524cc67fce91f43215d61b2695746eab102a3db516Stephen Hines                     PragmaList *Pragmas,
53fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines                     unsigned int TargetAPI,
54fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines                     bool Verbose)
556315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    : mPP(PP),
566315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      mCtx(Ctx),
573fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines      mPragmas(Pragmas),
584a4bf92a8add68629a7e6e59ef81c3c3fe603a75Stephen Hines      mTargetAPI(TargetAPI),
59fc4f78b9c7941132fb048a83f0e4ba528c3b4fd0Stephen Hines      mVerbose(Verbose),
605abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      mDataLayout(nullptr),
616315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      mLLVMContext(llvm::getGlobalContext()),
625abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      mLicenseNote(nullptr),
630a813a3ef2a82f19d7eab9e23ae8493197143803Stephen Hines      mRSPackageName("android.renderscript"),
643fa286b4c2f110c6be2bbfac9c715bb1ec880338Shih-wei Liao      version(0),
659ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      mMangleCtx(Ctx.createMangleContext()),
66fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mIs64Bit(Target.getPointerWidth(0) == 64),
67fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mNextSlot(1) {
684cc67fce91f43215d61b2695746eab102a3db516Stephen Hines
69109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  AddPragmaHandlers(PP, this);
7096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
719ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Prepare target data
728f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar  mDataLayout = new llvm::DataLayout(Target.getDataLayoutString());
73fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
74fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  // Reserve slot 0 for the root kernel.
75fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  mExportForEach.push_back(nullptr);
7640bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni  mFirstOldStyleKernel = mExportForEach.end();
77462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
78462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
799ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool RSContext::processExportVar(const clang::VarDecl *VD) {
806e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(!VD->getName().empty() && "Variable name should not be empty");
81537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!ET)
849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
85462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSExportVar *EV = new RSExportVar(this, VD, ET);
875abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  if (EV == nullptr)
889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  else
909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mExportVars.push_back(EV);
91462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return true;
93462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
94462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
95fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niint RSContext::getForEachSlotNumber(const clang::FunctionDecl* FD) {
96fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::StringRef& funcName = FD->getName();
97fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return getForEachSlotNumber(funcName);
98fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
99fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
100fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niint RSContext::getForEachSlotNumber(const clang::StringRef& funcName) {
101fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  auto it = mExportForEachMap.find(funcName);
102fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (it == mExportForEachMap.end()) {
103fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return -1;
104fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
105fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return it->second;
106fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
107fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1086315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrbool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
1096e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(!FD->getName().empty() && "Function name should not be empty");
110462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1113fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines  if (!FD->isThisDeclarationADefinition()) {
1123fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines    return true;
1133fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines  }
114462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
11565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  slangAssert(FD->getStorageClass() == clang::SC_None);
116462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
117c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  // Specialized function
118eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala  if (RSSpecialFunc::isSpecialRSFunc(mTargetAPI, FD)) {
1199999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    // Do not reflect specialized functions like init, dtor, or graphics root.
120eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala    return RSSpecialFunc::validateSpecialFuncDecl(mTargetAPI, this, FD);
121c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  }
122c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala
123c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  // Foreach kernel
124c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
125fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    RSExportForEach *EFE = RSExportForEach::Create(this, FD);
126fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    if (EFE == nullptr) {
127fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      return false;
128fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
12940bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni
13040bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    // The root function should be at index 0 in the list
13140bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    if (FD->getName().equals("root")) {
132fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mExportForEach[0] = EFE;
13340bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni      return true;
13440bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    }
13540bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni
13640bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    // New-style kernels with attribute "kernel" should come first in the list
13740bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    if (FD->hasAttr<clang::KernelAttr>()) {
13840bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni      mFirstOldStyleKernel = mExportForEach.insert(mFirstOldStyleKernel, EFE) + 1;
13940bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni      slangAssert((mTargetAPI < SLANG_FEATURE_SINGLE_SOURCE_API ||
14040bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni                   getForEachSlotNumber(FD->getName()) ==
14140bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni                   mFirstOldStyleKernel - mExportForEach.begin() - 1) &&
14240bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni                  "Inconsistent slot number assignment");
14340bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni      return true;
1445d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines    }
14540bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni
14640bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    // Old-style kernels should appear in the end of the list
14740bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    mFirstOldStyleKernel = mExportForEach.insert(mFirstOldStyleKernel, EFE);
148fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return true;
1493fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines  }
1503fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines
151c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  // Invokable
152c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  if (auto *EF = RSExportFunc::Create(this, FD)) {
1539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mExportFuncs.push_back(EF);
154c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    return true;
155c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  }
156462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
157c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  return false;
1589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
159462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
160fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nibool RSContext::addForEach(const clang::FunctionDecl* FD) {
161fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const llvm::StringRef& funcName = FD->getName();
162fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
163fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (funcName.equals("root")) {
164fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    // The root kernel should always be in slot 0.
165fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    mExportForEachMap.insert(std::make_pair(funcName, 0));
166fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  } else {
167fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    mExportForEachMap.insert(std::make_pair(funcName, mNextSlot++));
168fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
169fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
170fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return true;
171fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
172462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool RSContext::processExportType(const llvm::StringRef &Name) {
1749e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
175462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1765abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert(TUDecl != nullptr && "Translation unit declaration (top-level "
1775abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                   "declaration) is null object");
178f52a620440fa62257dfdcf2583f0f9df5b855c76Shih-wei Liao
1799e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines  const clang::IdentifierInfo *II = mPP.getIdentifierInfo(Name);
1805abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  if (II == nullptr)
1816315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
1826315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    //             found
1839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
184f52a620440fa62257dfdcf2583f0f9df5b855c76Shih-wei Liao
185c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines  clang::DeclContext::lookup_result R = TUDecl->lookup(II);
1865abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  RSExportType *ET = nullptr;
187f52a620440fa62257dfdcf2583f0f9df5b855c76Shih-wei Liao
188c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines  for (clang::DeclContext::lookup_iterator I = R.begin(), E = R.end();
1899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       I != E;
1909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       I++) {
1919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    clang::NamedDecl *const ND = *I;
1925abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    const clang::Type *T = nullptr;
193462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    switch (ND->getKind()) {
1959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      case clang::Decl::Typedef: {
1969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        T = static_cast<const clang::TypedefDecl*>(
1979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
1989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      }
2009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      case clang::Decl::Record: {
2019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
2029ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
2039ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      }
2049ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      default: {
2059ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        // unsupported, skip
2069ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
207ac91815eb4918b9307ec876f34f2b60adf28c78bShih-wei Liao      }
208ac91815eb4918b9307ec876f34f2b60adf28c78bShih-wei Liao    }
209537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
2105abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    if (T != nullptr)
21113fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines      ET = RSExportType::Create(this, T, NotLegacyKernelArgument);
2129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
213462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2145abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  return (ET != nullptr);
215462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
216462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
21788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Nivoid RSContext::setAllocationType(const clang::TypeDecl* TD) {
21888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  mAllocationType = mCtx.getTypeDeclType(TD);
21988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni}
22088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
2212615f383dfc1542a05f19aee23b03a09bd018f4eYang Nivoid RSContext::setScriptCallType(const clang::TypeDecl* TD) {
2222615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  mScriptCallType = mCtx.getTypeDeclType(TD);
2232615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni}
2242615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni
225fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nibool RSContext::processExports() {
226b6809edd6ee8b90982425fb8ad24e867708b46fcStephen Hines  bool valid = true;
227593a894650e81be54173106ec266f0311cebebd3Stephen Hines
228593a894650e81be54173106ec266f0311cebebd3Stephen Hines  if (getDiagnostics()->hasErrorOccurred()) {
229593a894650e81be54173106ec266f0311cebebd3Stephen Hines    return false;
230593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
231593a894650e81be54173106ec266f0311cebebd3Stephen Hines
2325d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
233fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  for (auto I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; I++) {
234fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    clang::Decl* D = *I;
235fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    switch (D->getKind()) {
236fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    case clang::Decl::Var: {
237fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::VarDecl* VD = llvm::dyn_cast<clang::VarDecl>(D);
238a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines      bool ShouldExportVariable = true;
2395d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      if (VD->getFormalLinkage() == clang::ExternalLinkage) {
240a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        clang::QualType QT = VD->getTypeSourceInfo()->getType();
241a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        if (QT.isConstQualified() && !VD->hasInit()) {
242a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines          if (Slang::IsLocInRSHeaderFile(VD->getLocation(),
243a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines                                         *getSourceManager())) {
244a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            // We don't export variables internal to the runtime's
245a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            // implementation.
246a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            ShouldExportVariable = false;
247a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines          } else {
248a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
249a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            DiagEngine->Report(VD->getLocation(), DiagEngine->getCustomDiagID(
250a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines                clang::DiagnosticsEngine::Error,
251a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines                "invalid declaration of uninitialized constant variable '%0'"))
252a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines              << VD->getName();
253a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            valid = false;
254a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines          }
255a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        }
2565e306b944425a952fe744f59d828538137a59375David Gross        if (valid && ShouldExportVariable && isSyntheticName(VD->getName()))
2575e306b944425a952fe744f59d828538137a59375David Gross          ShouldExportVariable = false;
258a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        if (valid && ShouldExportVariable && !processExportVar(VD)) {
2595d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines          valid = false;
2605d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines        }
2615d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      }
262fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      break;
263fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
264fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    case clang::Decl::Function: {
265fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::FunctionDecl* FD = llvm::dyn_cast<clang::FunctionDecl>(D);
2665d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      if (FD->getFormalLinkage() == clang::ExternalLinkage) {
2675d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines        if (!processExportFunc(FD)) {
2685d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines          valid = false;
2695d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines        }
2705d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      }
271fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      break;
272fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
273fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    default:
274fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      break;
2755d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines    }
2765d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines  }
2775d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines
27815410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni  // Create a dummy root in slot 0 if a root kernel is not seen
27915410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni  // and there exists a non-root kernel.
280fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (valid && mExportForEach[0] == nullptr) {
28115410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    const size_t numExportedForEach = mExportForEach.size();
28215410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    if (numExportedForEach > 1) {
28315410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni      mExportForEach[0] = RSExportForEach::CreateDummyRoot(this);
28415410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    } else {
28515410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni      slangAssert(numExportedForEach == 1);
28615410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni      mExportForEach.pop_back();
28715410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    }
288c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  }
289c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines
2909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Finally, export type forcely set to be exported by user
2919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
2929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao           EE = mNeedExportTypes.end();
2939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       EI != EE;
2949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       EI++) {
2959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (!processExportType(EI->getKey())) {
296b6809edd6ee8b90982425fb8ad24e867708b46fcStephen Hines      valid = false;
2973f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang    }
2989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
2999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
300b6809edd6ee8b90982425fb8ad24e867708b46fcStephen Hines  return valid;
3019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
302537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
3035e306b944425a952fe744f59d828538137a59375David Grossbool RSContext::processReducePragmas(Backend *BE) {
3045e306b944425a952fe744f59d828538137a59375David Gross  // This is needed to ensure that the dummy variable is emitted into
3055e306b944425a952fe744f59d828538137a59375David Gross  // the bitcode -- which in turn forces the function to be emitted
3065e306b944425a952fe744f59d828538137a59375David Gross  // into the bitcode.  We couldn't do this at
3075e306b944425a952fe744f59d828538137a59375David Gross  // markUsedByReducePragma() time because we had to wait until the
3085e306b944425a952fe744f59d828538137a59375David Gross  // Backend is available.
3095e306b944425a952fe744f59d828538137a59375David Gross  for (auto DummyVar : mUsedByReducePragmaDummyVars)
3105e306b944425a952fe744f59d828538137a59375David Gross    BE->HandleTopLevelDecl(clang::DeclGroupRef(DummyVar));
3115e306b944425a952fe744f59d828538137a59375David Gross
31265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  bool valid = true;
3138ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  for (auto I = export_reduce_begin(), E = export_reduce_end(); I != E; ++I) {
31465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (! (*I)->analyzeTranslationUnit())
31565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      valid = false;
31665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  }
31765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  return valid;
31865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross}
31965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
3205e306b944425a952fe744f59d828538137a59375David Grossvoid RSContext::markUsedByReducePragma(clang::FunctionDecl *FD, CheckName Check) {
3215e306b944425a952fe744f59d828538137a59375David Gross  if (mUsedByReducePragmaFns.find(FD) != mUsedByReducePragmaFns.end())
3225e306b944425a952fe744f59d828538137a59375David Gross    return;  // already marked used
3235e306b944425a952fe744f59d828538137a59375David Gross
3245e306b944425a952fe744f59d828538137a59375David Gross  if (Check == CheckNameYes) {
3255e306b944425a952fe744f59d828538137a59375David Gross    // This is an inefficient linear search.  If this turns out to be a
3265e306b944425a952fe744f59d828538137a59375David Gross    // problem in practice, then processReducePragmas() could build a
3275e306b944425a952fe744f59d828538137a59375David Gross    // set or hash table or something similar containing all function
3285e306b944425a952fe744f59d828538137a59375David Gross    // names mentioned in a reduce pragma and searchable in O(c) or
3295e306b944425a952fe744f59d828538137a59375David Gross    // O(log(n)) time rather than the currently-implemented O(n) search.
3305e306b944425a952fe744f59d828538137a59375David Gross    auto NameMatches = [this, FD]() {
3318ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      for (auto I = export_reduce_begin(), E = export_reduce_end(); I != E; ++I) {
3325e306b944425a952fe744f59d828538137a59375David Gross        if ((*I)->matchName(FD->getName()))
3335e306b944425a952fe744f59d828538137a59375David Gross          return true;
3345e306b944425a952fe744f59d828538137a59375David Gross      }
3355e306b944425a952fe744f59d828538137a59375David Gross      return false;
3365e306b944425a952fe744f59d828538137a59375David Gross    };
3375e306b944425a952fe744f59d828538137a59375David Gross    if (!NameMatches())
3385e306b944425a952fe744f59d828538137a59375David Gross      return;
33965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  }
3405e306b944425a952fe744f59d828538137a59375David Gross
3415e306b944425a952fe744f59d828538137a59375David Gross  mUsedByReducePragmaFns.insert(FD);
3425e306b944425a952fe744f59d828538137a59375David Gross
3435e306b944425a952fe744f59d828538137a59375David Gross  // This is needed to prevent clang from warning that the function is
3445e306b944425a952fe744f59d828538137a59375David Gross  // unused (in the case where it is only referenced by #pragma rs
3455e306b944425a952fe744f59d828538137a59375David Gross  // reduce).
3465e306b944425a952fe744f59d828538137a59375David Gross  FD->setIsUsed();
3475e306b944425a952fe744f59d828538137a59375David Gross
3485e306b944425a952fe744f59d828538137a59375David Gross  // Each constituent function "f" of a reduction kernel gets a dummy variable generated for it:
3495e306b944425a952fe744f59d828538137a59375David Gross  //   void *.rs.reduce_fn.f = (void*)&f;
3505e306b944425a952fe744f59d828538137a59375David Gross  // This is a trick to ensure that clang will not delete "f" as unused.
3515e306b944425a952fe744f59d828538137a59375David Gross
3525e306b944425a952fe744f59d828538137a59375David Gross  // `-VarDecl 0x87cb558 <line:3:1, col:30> col:7 var 'void *' cinit
3535e306b944425a952fe744f59d828538137a59375David Gross  //     `-CStyleCastExpr 0x87cb630 <col:19, col:26> 'void *' <BitCast>
3545e306b944425a952fe744f59d828538137a59375David Gross  //       `-ImplicitCastExpr 0x87cb618 <col:26> 'void (*)(int *, float, double)' <FunctionToPointerDecay>
3555e306b944425a952fe744f59d828538137a59375David Gross  //         `-DeclRefExpr 0x87cb5b8 <col:26> 'void (int *, float, double)' Function 0x8784e10 'foo' 'void (int *, float, double)
3565e306b944425a952fe744f59d828538137a59375David Gross
3575e306b944425a952fe744f59d828538137a59375David Gross  const clang::QualType VoidPtrType = mCtx.getPointerType(mCtx.VoidTy);
3585e306b944425a952fe744f59d828538137a59375David Gross
3595e306b944425a952fe744f59d828538137a59375David Gross  clang::DeclContext *const DC = FD->getDeclContext();
3605e306b944425a952fe744f59d828538137a59375David Gross  const clang::SourceLocation Loc = FD->getLocation();
3615e306b944425a952fe744f59d828538137a59375David Gross
3625e306b944425a952fe744f59d828538137a59375David Gross  clang::VarDecl *const VD = clang::VarDecl::Create(
3635e306b944425a952fe744f59d828538137a59375David Gross      mCtx, DC, Loc, Loc,
3645e306b944425a952fe744f59d828538137a59375David Gross      &mCtx.Idents.get(std::string(".rs.reduce_fn.") + FD->getNameAsString()),
3655e306b944425a952fe744f59d828538137a59375David Gross      VoidPtrType,
3665e306b944425a952fe744f59d828538137a59375David Gross      mCtx.getTrivialTypeSourceInfo(VoidPtrType),
3675e306b944425a952fe744f59d828538137a59375David Gross      clang::SC_None);
3685e306b944425a952fe744f59d828538137a59375David Gross  VD->setLexicalDeclContext(DC);
3695e306b944425a952fe744f59d828538137a59375David Gross  DC->addDecl(VD);
3705e306b944425a952fe744f59d828538137a59375David Gross
3715e306b944425a952fe744f59d828538137a59375David Gross  clang::DeclRefExpr *const DRE = clang::DeclRefExpr::Create(mCtx,
3725e306b944425a952fe744f59d828538137a59375David Gross                                                             clang::NestedNameSpecifierLoc(),
3735e306b944425a952fe744f59d828538137a59375David Gross                                                             Loc,
3745e306b944425a952fe744f59d828538137a59375David Gross                                                             FD, false, Loc, FD->getType(),
3755e306b944425a952fe744f59d828538137a59375David Gross                                                             clang::VK_RValue);
3765e306b944425a952fe744f59d828538137a59375David Gross  clang::ImplicitCastExpr *const ICE = clang::ImplicitCastExpr::Create(mCtx, mCtx.getPointerType(FD->getType()),
3775e306b944425a952fe744f59d828538137a59375David Gross                                                                       clang::CK_FunctionToPointerDecay, DRE,
3785e306b944425a952fe744f59d828538137a59375David Gross                                                                       nullptr, clang::VK_RValue);
3795e306b944425a952fe744f59d828538137a59375David Gross  clang::CStyleCastExpr *const CSCE = clang::CStyleCastExpr::Create(mCtx, VoidPtrType, clang::VK_RValue, clang::CK_BitCast,
3805e306b944425a952fe744f59d828538137a59375David Gross                                                                    ICE, nullptr, nullptr,
3815e306b944425a952fe744f59d828538137a59375David Gross                                                                    Loc, Loc);
3825e306b944425a952fe744f59d828538137a59375David Gross  VD->setInit(CSCE);
3835e306b944425a952fe744f59d828538137a59375David Gross
3845e306b944425a952fe744f59d828538137a59375David Gross  mUsedByReducePragmaDummyVars.push_back(VD);
38565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross}
38665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
3879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool RSContext::insertExportType(const llvm::StringRef &TypeName,
3889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                 RSExportType *ET) {
3899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  ExportTypeMap::value_type *NewItem =
3902eb9a3f7c48fe54eb4e813d80e3363bc79553a1eStephen Hines      ExportTypeMap::value_type::Create(TypeName,
3919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        mExportTypes.getAllocator(),
3929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        ET);
3939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
3949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (mExportTypes.insert(NewItem)) {
3959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return true;
3969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  } else {
3973f45a25c23fa0f2cca4070f4d8713dc1a83f5ff7Matt Wala    NewItem->Destroy(mExportTypes.getAllocator());
3989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
3999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
400462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
401462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
402462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei LiaoRSContext::~RSContext() {
4039ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  delete mLicenseNote;
40423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  delete mDataLayout;
405a41ce1d98094da84643995d40d71c529905123fcZonr Chang  for (ExportableList::iterator I = mExportables.begin(),
406a41ce1d98094da84643995d40d71c529905123fcZonr Chang          E = mExportables.end();
407a41ce1d98094da84643995d40d71c529905123fcZonr Chang       I != E;
408a41ce1d98094da84643995d40d71c529905123fcZonr Chang       I++) {
409641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang    if (!(*I)->isKeep())
410641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang      delete *I;
411a41ce1d98094da84643995d40d71c529905123fcZonr Chang  }
412462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
413e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
414e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
415