slang_rs_context.cpp revision 5e306b944425a952fe744f59d828538137a59375
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
7223c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  mDataLayout = new llvm::DataLayout(Target.getTargetDescription());
73fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
74fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  // Reserve slot 0 for the root kernel.
75fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  mExportForEach.push_back(nullptr);
76462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
77462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool RSContext::processExportVar(const clang::VarDecl *VD) {
796e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(!VD->getName().empty() && "Variable name should not be empty");
80537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!ET)
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
84462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSExportVar *EV = new RSExportVar(this, VD, ET);
865abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  if (EV == nullptr)
879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  else
899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mExportVars.push_back(EV);
90462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return true;
92462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
93462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
94fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niint RSContext::getForEachSlotNumber(const clang::FunctionDecl* FD) {
95fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::StringRef& funcName = FD->getName();
96fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return getForEachSlotNumber(funcName);
97fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
98fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
99fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niint RSContext::getForEachSlotNumber(const clang::StringRef& funcName) {
100fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  auto it = mExportForEachMap.find(funcName);
101fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (it == mExportForEachMap.end()) {
102fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return -1;
103fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
104fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return it->second;
105fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
106fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1076315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrbool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
1086e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(!FD->getName().empty() && "Function name should not be empty");
109462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1103fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines  if (!FD->isThisDeclarationADefinition()) {
1113fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines    return true;
1123fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines  }
113462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
11465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  slangAssert(FD->getStorageClass() == clang::SC_None);
115462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
116c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  // Specialized function
117eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala  if (RSSpecialFunc::isSpecialRSFunc(mTargetAPI, FD)) {
1189999ec3aa0c4d7a6befd3a300dc07f0cea91cb6cStephen Hines    // Do not reflect specialized functions like init, dtor, or graphics root.
119eae0b7ad0195360b0afc37d51553f2917f1aa365Matt Wala    return RSSpecialFunc::validateSpecialFuncDecl(mTargetAPI, this, FD);
120c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  }
121c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala
122c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  // Foreach kernel
123c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
124fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    RSExportForEach *EFE = RSExportForEach::Create(this, FD);
125fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    if (EFE == nullptr) {
126fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      return false;
127fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
128fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    const llvm::StringRef& funcName = FD->getName();
129fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    if (funcName.equals("root")) {
130fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mExportForEach[0] = EFE;
131fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    } else {
1325d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      mExportForEach.push_back(EFE);
1335d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines    }
134fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return true;
1353fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines  }
1363fbe68a4ec20fec25f8a40191437bbc02d00f591Stephen Hines
137c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  // Reduce kernel
138c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  if (RSExportReduce::isRSReduceFunc(mTargetAPI, FD)) {
139c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    if (auto *ER = RSExportReduce::Create(this, FD)) {
140c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      mExportReduce.push_back(ER);
141c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      return true;
142c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    }
1439ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
144c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  }
145c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala
146c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  // Invokable
147c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  if (auto *EF = RSExportFunc::Create(this, FD)) {
1489ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mExportFuncs.push_back(EF);
149c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    return true;
150c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  }
151462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
152c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  return false;
1539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
154462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
155fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nibool RSContext::addForEach(const clang::FunctionDecl* FD) {
156fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const llvm::StringRef& funcName = FD->getName();
157fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
158fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (funcName.equals("root")) {
159fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    // The root kernel should always be in slot 0.
160fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    mExportForEachMap.insert(std::make_pair(funcName, 0));
161fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  } else {
162fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    mExportForEachMap.insert(std::make_pair(funcName, mNextSlot++));
163fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
164fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
165fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return true;
166fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
167462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool RSContext::processExportType(const llvm::StringRef &Name) {
1699e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
170462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1715abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert(TUDecl != nullptr && "Translation unit declaration (top-level "
1725abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                   "declaration) is null object");
173f52a620440fa62257dfdcf2583f0f9df5b855c76Shih-wei Liao
1749e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines  const clang::IdentifierInfo *II = mPP.getIdentifierInfo(Name);
1755abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  if (II == nullptr)
1766315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
1776315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    //             found
1789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
179f52a620440fa62257dfdcf2583f0f9df5b855c76Shih-wei Liao
180c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines  clang::DeclContext::lookup_result R = TUDecl->lookup(II);
1815abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  RSExportType *ET = nullptr;
182f52a620440fa62257dfdcf2583f0f9df5b855c76Shih-wei Liao
183c706907a8041faaa882f9bd87f1d1c1669023a62Stephen Hines  for (clang::DeclContext::lookup_iterator I = R.begin(), E = R.end();
1849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       I != E;
1859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       I++) {
1869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    clang::NamedDecl *const ND = *I;
1875abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    const clang::Type *T = nullptr;
188462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    switch (ND->getKind()) {
1909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      case clang::Decl::Typedef: {
1919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        T = static_cast<const clang::TypedefDecl*>(
1929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
1939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      }
1959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      case clang::Decl::Record: {
1969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
1979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      }
1999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      default: {
2009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        // unsupported, skip
2019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
202ac91815eb4918b9307ec876f34f2b60adf28c78bShih-wei Liao      }
203ac91815eb4918b9307ec876f34f2b60adf28c78bShih-wei Liao    }
204537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
2055abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    if (T != nullptr)
20613fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines      ET = RSExportType::Create(this, T, NotLegacyKernelArgument);
2079ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
208462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
2095abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  return (ET != nullptr);
210462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
211462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
21288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Nivoid RSContext::setAllocationType(const clang::TypeDecl* TD) {
21388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  mAllocationType = mCtx.getTypeDeclType(TD);
21488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni}
21588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
2162615f383dfc1542a05f19aee23b03a09bd018f4eYang Nivoid RSContext::setScriptCallType(const clang::TypeDecl* TD) {
2172615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  mScriptCallType = mCtx.getTypeDeclType(TD);
2182615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni}
2192615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni
220fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nibool RSContext::processExports() {
221b6809edd6ee8b90982425fb8ad24e867708b46fcStephen Hines  bool valid = true;
222593a894650e81be54173106ec266f0311cebebd3Stephen Hines
223593a894650e81be54173106ec266f0311cebebd3Stephen Hines  if (getDiagnostics()->hasErrorOccurred()) {
224593a894650e81be54173106ec266f0311cebebd3Stephen Hines    return false;
225593a894650e81be54173106ec266f0311cebebd3Stephen Hines  }
226593a894650e81be54173106ec266f0311cebebd3Stephen Hines
2275d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
228fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  for (auto I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; I++) {
229fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    clang::Decl* D = *I;
230fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    switch (D->getKind()) {
231fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    case clang::Decl::Var: {
232fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::VarDecl* VD = llvm::dyn_cast<clang::VarDecl>(D);
233a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines      bool ShouldExportVariable = true;
2345d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      if (VD->getFormalLinkage() == clang::ExternalLinkage) {
235a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        clang::QualType QT = VD->getTypeSourceInfo()->getType();
236a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        if (QT.isConstQualified() && !VD->hasInit()) {
237a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines          if (Slang::IsLocInRSHeaderFile(VD->getLocation(),
238a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines                                         *getSourceManager())) {
239a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            // We don't export variables internal to the runtime's
240a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            // implementation.
241a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            ShouldExportVariable = false;
242a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines          } else {
243a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
244a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            DiagEngine->Report(VD->getLocation(), DiagEngine->getCustomDiagID(
245a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines                clang::DiagnosticsEngine::Error,
246a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines                "invalid declaration of uninitialized constant variable '%0'"))
247a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines              << VD->getName();
248a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines            valid = false;
249a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines          }
250a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        }
2515e306b944425a952fe744f59d828538137a59375David Gross        if (valid && ShouldExportVariable && isSyntheticName(VD->getName()))
2525e306b944425a952fe744f59d828538137a59375David Gross          ShouldExportVariable = false;
253a5d846df579f3d60457f664a284afe2cc2b9f8dbStephen Hines        if (valid && ShouldExportVariable && !processExportVar(VD)) {
2545d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines          valid = false;
2555d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines        }
2565d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      }
257fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      break;
258fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
259fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    case clang::Decl::Function: {
260fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::FunctionDecl* FD = llvm::dyn_cast<clang::FunctionDecl>(D);
2615d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      if (FD->getFormalLinkage() == clang::ExternalLinkage) {
2625d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines        if (!processExportFunc(FD)) {
2635d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines          valid = false;
2645d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines        }
2655d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines      }
266fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      break;
267fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
268fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    default:
269fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      break;
2705d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines    }
2715d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines  }
2725d9263d3a3a7457b9e5fe6e518c0d822dcdfcda6Stephen Hines
27315410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni  // Create a dummy root in slot 0 if a root kernel is not seen
27415410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni  // and there exists a non-root kernel.
275fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (valid && mExportForEach[0] == nullptr) {
27615410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    const size_t numExportedForEach = mExportForEach.size();
27715410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    if (numExportedForEach > 1) {
27815410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni      mExportForEach[0] = RSExportForEach::CreateDummyRoot(this);
27915410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    } else {
28015410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni      slangAssert(numExportedForEach == 1);
28115410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni      mExportForEach.pop_back();
28215410146cdc2a354ade80ceb3cd134f8a792d92aYang Ni    }
283c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines  }
284c17e198ffcd37bfc57e3add1f6eee952ae2a2eabStephen Hines
2859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Finally, export type forcely set to be exported by user
2869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
2879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao           EE = mNeedExportTypes.end();
2889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       EI != EE;
2899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao       EI++) {
2909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (!processExportType(EI->getKey())) {
291b6809edd6ee8b90982425fb8ad24e867708b46fcStephen Hines      valid = false;
2923f8b44dba57685b437cecc208f2a20a4ed93ed36Ying Wang    }
2939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
2949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
295b6809edd6ee8b90982425fb8ad24e867708b46fcStephen Hines  return valid;
2969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
297537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
2985e306b944425a952fe744f59d828538137a59375David Grossbool RSContext::processReducePragmas(Backend *BE) {
2995e306b944425a952fe744f59d828538137a59375David Gross  // This is needed to ensure that the dummy variable is emitted into
3005e306b944425a952fe744f59d828538137a59375David Gross  // the bitcode -- which in turn forces the function to be emitted
3015e306b944425a952fe744f59d828538137a59375David Gross  // into the bitcode.  We couldn't do this at
3025e306b944425a952fe744f59d828538137a59375David Gross  // markUsedByReducePragma() time because we had to wait until the
3035e306b944425a952fe744f59d828538137a59375David Gross  // Backend is available.
3045e306b944425a952fe744f59d828538137a59375David Gross  for (auto DummyVar : mUsedByReducePragmaDummyVars)
3055e306b944425a952fe744f59d828538137a59375David Gross    BE->HandleTopLevelDecl(clang::DeclGroupRef(DummyVar));
3065e306b944425a952fe744f59d828538137a59375David Gross
30765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  bool valid = true;
30865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  for (auto I = export_reduce_new_begin(), E = export_reduce_new_end(); I != E; ++I) {
30965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (! (*I)->analyzeTranslationUnit())
31065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      valid = false;
31165f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  }
31265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  return valid;
31365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross}
31465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
3155e306b944425a952fe744f59d828538137a59375David Grossvoid RSContext::markUsedByReducePragma(clang::FunctionDecl *FD, CheckName Check) {
3165e306b944425a952fe744f59d828538137a59375David Gross  if (mUsedByReducePragmaFns.find(FD) != mUsedByReducePragmaFns.end())
3175e306b944425a952fe744f59d828538137a59375David Gross    return;  // already marked used
3185e306b944425a952fe744f59d828538137a59375David Gross
3195e306b944425a952fe744f59d828538137a59375David Gross  if (Check == CheckNameYes) {
3205e306b944425a952fe744f59d828538137a59375David Gross    // This is an inefficient linear search.  If this turns out to be a
3215e306b944425a952fe744f59d828538137a59375David Gross    // problem in practice, then processReducePragmas() could build a
3225e306b944425a952fe744f59d828538137a59375David Gross    // set or hash table or something similar containing all function
3235e306b944425a952fe744f59d828538137a59375David Gross    // names mentioned in a reduce pragma and searchable in O(c) or
3245e306b944425a952fe744f59d828538137a59375David Gross    // O(log(n)) time rather than the currently-implemented O(n) search.
3255e306b944425a952fe744f59d828538137a59375David Gross    auto NameMatches = [this, FD]() {
3265e306b944425a952fe744f59d828538137a59375David Gross      for (auto I = export_reduce_new_begin(), E = export_reduce_new_end(); I != E; ++I) {
3275e306b944425a952fe744f59d828538137a59375David Gross        if ((*I)->matchName(FD->getName()))
3285e306b944425a952fe744f59d828538137a59375David Gross          return true;
3295e306b944425a952fe744f59d828538137a59375David Gross      }
3305e306b944425a952fe744f59d828538137a59375David Gross      return false;
3315e306b944425a952fe744f59d828538137a59375David Gross    };
3325e306b944425a952fe744f59d828538137a59375David Gross    if (!NameMatches())
3335e306b944425a952fe744f59d828538137a59375David Gross      return;
33465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  }
3355e306b944425a952fe744f59d828538137a59375David Gross
3365e306b944425a952fe744f59d828538137a59375David Gross  mUsedByReducePragmaFns.insert(FD);
3375e306b944425a952fe744f59d828538137a59375David Gross
3385e306b944425a952fe744f59d828538137a59375David Gross  // This is needed to prevent clang from warning that the function is
3395e306b944425a952fe744f59d828538137a59375David Gross  // unused (in the case where it is only referenced by #pragma rs
3405e306b944425a952fe744f59d828538137a59375David Gross  // reduce).
3415e306b944425a952fe744f59d828538137a59375David Gross  FD->setIsUsed();
3425e306b944425a952fe744f59d828538137a59375David Gross
3435e306b944425a952fe744f59d828538137a59375David Gross  // Each constituent function "f" of a reduction kernel gets a dummy variable generated for it:
3445e306b944425a952fe744f59d828538137a59375David Gross  //   void *.rs.reduce_fn.f = (void*)&f;
3455e306b944425a952fe744f59d828538137a59375David Gross  // This is a trick to ensure that clang will not delete "f" as unused.
3465e306b944425a952fe744f59d828538137a59375David Gross
3475e306b944425a952fe744f59d828538137a59375David Gross  // `-VarDecl 0x87cb558 <line:3:1, col:30> col:7 var 'void *' cinit
3485e306b944425a952fe744f59d828538137a59375David Gross  //     `-CStyleCastExpr 0x87cb630 <col:19, col:26> 'void *' <BitCast>
3495e306b944425a952fe744f59d828538137a59375David Gross  //       `-ImplicitCastExpr 0x87cb618 <col:26> 'void (*)(int *, float, double)' <FunctionToPointerDecay>
3505e306b944425a952fe744f59d828538137a59375David Gross  //         `-DeclRefExpr 0x87cb5b8 <col:26> 'void (int *, float, double)' Function 0x8784e10 'foo' 'void (int *, float, double)
3515e306b944425a952fe744f59d828538137a59375David Gross
3525e306b944425a952fe744f59d828538137a59375David Gross  const clang::QualType VoidPtrType = mCtx.getPointerType(mCtx.VoidTy);
3535e306b944425a952fe744f59d828538137a59375David Gross
3545e306b944425a952fe744f59d828538137a59375David Gross  clang::DeclContext *const DC = FD->getDeclContext();
3555e306b944425a952fe744f59d828538137a59375David Gross  const clang::SourceLocation Loc = FD->getLocation();
3565e306b944425a952fe744f59d828538137a59375David Gross
3575e306b944425a952fe744f59d828538137a59375David Gross  clang::VarDecl *const VD = clang::VarDecl::Create(
3585e306b944425a952fe744f59d828538137a59375David Gross      mCtx, DC, Loc, Loc,
3595e306b944425a952fe744f59d828538137a59375David Gross      &mCtx.Idents.get(std::string(".rs.reduce_fn.") + FD->getNameAsString()),
3605e306b944425a952fe744f59d828538137a59375David Gross      VoidPtrType,
3615e306b944425a952fe744f59d828538137a59375David Gross      mCtx.getTrivialTypeSourceInfo(VoidPtrType),
3625e306b944425a952fe744f59d828538137a59375David Gross      clang::SC_None);
3635e306b944425a952fe744f59d828538137a59375David Gross  VD->setLexicalDeclContext(DC);
3645e306b944425a952fe744f59d828538137a59375David Gross  DC->addDecl(VD);
3655e306b944425a952fe744f59d828538137a59375David Gross
3665e306b944425a952fe744f59d828538137a59375David Gross  clang::DeclRefExpr *const DRE = clang::DeclRefExpr::Create(mCtx,
3675e306b944425a952fe744f59d828538137a59375David Gross                                                             clang::NestedNameSpecifierLoc(),
3685e306b944425a952fe744f59d828538137a59375David Gross                                                             Loc,
3695e306b944425a952fe744f59d828538137a59375David Gross                                                             FD, false, Loc, FD->getType(),
3705e306b944425a952fe744f59d828538137a59375David Gross                                                             clang::VK_RValue);
3715e306b944425a952fe744f59d828538137a59375David Gross  clang::ImplicitCastExpr *const ICE = clang::ImplicitCastExpr::Create(mCtx, mCtx.getPointerType(FD->getType()),
3725e306b944425a952fe744f59d828538137a59375David Gross                                                                       clang::CK_FunctionToPointerDecay, DRE,
3735e306b944425a952fe744f59d828538137a59375David Gross                                                                       nullptr, clang::VK_RValue);
3745e306b944425a952fe744f59d828538137a59375David Gross  clang::CStyleCastExpr *const CSCE = clang::CStyleCastExpr::Create(mCtx, VoidPtrType, clang::VK_RValue, clang::CK_BitCast,
3755e306b944425a952fe744f59d828538137a59375David Gross                                                                    ICE, nullptr, nullptr,
3765e306b944425a952fe744f59d828538137a59375David Gross                                                                    Loc, Loc);
3775e306b944425a952fe744f59d828538137a59375David Gross  VD->setInit(CSCE);
3785e306b944425a952fe744f59d828538137a59375David Gross
3795e306b944425a952fe744f59d828538137a59375David Gross  mUsedByReducePragmaDummyVars.push_back(VD);
38065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross}
38165f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
3829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool RSContext::insertExportType(const llvm::StringRef &TypeName,
3839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                 RSExportType *ET) {
3849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  ExportTypeMap::value_type *NewItem =
3852eb9a3f7c48fe54eb4e813d80e3363bc79553a1eStephen Hines      ExportTypeMap::value_type::Create(TypeName,
3869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        mExportTypes.getAllocator(),
3879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        ET);
3889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
3899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (mExportTypes.insert(NewItem)) {
3909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return true;
3919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  } else {
3923f45a25c23fa0f2cca4070f4d8713dc1a83f5ff7Matt Wala    NewItem->Destroy(mExportTypes.getAllocator());
3939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
3949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
395462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
396462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
397462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei LiaoRSContext::~RSContext() {
3989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  delete mLicenseNote;
39923c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  delete mDataLayout;
400a41ce1d98094da84643995d40d71c529905123fcZonr Chang  for (ExportableList::iterator I = mExportables.begin(),
401a41ce1d98094da84643995d40d71c529905123fcZonr Chang          E = mExportables.end();
402a41ce1d98094da84643995d40d71c529905123fcZonr Chang       I != E;
403a41ce1d98094da84643995d40d71c529905123fcZonr Chang       I++) {
404641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang    if (!(*I)->isKeep())
405641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang      delete *I;
406a41ce1d98094da84643995d40d71c529905123fcZonr Chang  }
407462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
408e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
409e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
410