1fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni/*
2fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * Copyright 2015, The Android Open Source Project
3fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni *
4fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * Licensed under the Apache License, Version 2.0 (the "License");
5fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * you may not use this file except in compliance with the License.
6fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * You may obtain a copy of the License at
7fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni *
8fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni *     http://www.apache.org/licenses/LICENSE-2.0
9fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni *
10fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * Unless required by applicable law or agreed to in writing, software
11fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * distributed under the License is distributed on an "AS IS" BASIS,
12fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * See the License for the specific language governing permissions and
14fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni * limitations under the License.
15fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni */
16fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
17fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "slang_rs_foreach_lowering.h"
18fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
19fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "clang/AST/ASTContext.h"
2040bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni#include "clang/AST/Attr.h"
21fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "llvm/Support/raw_ostream.h"
22fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "slang_rs_context.h"
23fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "slang_rs_export_foreach.h"
24fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
25fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ninamespace slang {
26fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
27fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ninamespace {
28fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
291946749cebf4a64341d8210890688fef7d958c22Yang Niconst char KERNEL_LAUNCH_FUNCTION_NAME[] = "rsForEach";
301946749cebf4a64341d8210890688fef7d958c22Yang Niconst char KERNEL_LAUNCH_FUNCTION_NAME_WITH_OPTIONS[] = "rsForEachWithOptions";
31fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niconst char INTERNAL_LAUNCH_FUNCTION_NAME[] =
3288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    "_Z17rsForEachInternaliP14rs_script_calliiP13rs_allocation";
33fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
34fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}  // anonymous namespace
35fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
36fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang NiRSForEachLowering::RSForEachLowering(RSContext* ctxt)
37fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    : mCtxt(ctxt), mASTCtxt(ctxt->getASTContext()) {}
38fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
39fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// Check if the passed-in expr references a kernel function in the following
40fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// pattern in the AST.
41fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
42fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// ImplicitCastExpr 'void *' <BitCast>
43fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//  `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
44fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//    `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
45fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niconst clang::FunctionDecl* RSForEachLowering::matchFunctionDesignator(
46fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    clang::Expr* expr) {
47fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::ImplicitCastExpr* ToVoidPtr =
48fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::ImplicitCastExpr>(expr);
49fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (ToVoidPtr == nullptr) {
50fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
51fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
52fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
53fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::ImplicitCastExpr* Decay =
54fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::ImplicitCastExpr>(ToVoidPtr->getSubExpr());
55fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
56fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (Decay == nullptr) {
57fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
58fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
59fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
60fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclRefExpr* DRE =
61fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::DeclRefExpr>(Decay->getSubExpr());
62fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
63fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (DRE == nullptr) {
64fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
65fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
66fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
67fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::FunctionDecl* FD =
68fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::FunctionDecl>(DRE->getDecl());
69fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
70fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (FD == nullptr) {
71fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
72fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
73fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
74fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return FD;
75fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
76fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
771946749cebf4a64341d8210890688fef7d958c22Yang Ni// Checks if the call expression is a legal rsForEach call by looking for the
78fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// following pattern in the AST. On success, returns the first argument that is
79fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// a FunctionDecl of a kernel function.
80fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
81fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// CallExpr 'void'
82fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
83fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |-ImplicitCastExpr 'void (*)(void *, ...)' <FunctionToPointerDecay>
841946749cebf4a64341d8210890688fef7d958c22Yang Ni// | `-DeclRefExpr  'void (void *, ...)'  'rsForEach' 'void (void *, ...)'
85fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
86fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |-ImplicitCastExpr 'void *' <BitCast>
87fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// | `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
88fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |   `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
89fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
90fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
91fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// | `-DeclRefExpr 'rs_allocation':'rs_allocation' lvalue ParmVar 'in' 'rs_allocation':'rs_allocation'
92fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
93fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// `-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
94fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//   `-DeclRefExpr  'rs_allocation':'rs_allocation' lvalue ParmVar 'out' 'rs_allocation':'rs_allocation'
95fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niconst clang::FunctionDecl* RSForEachLowering::matchKernelLaunchCall(
961946749cebf4a64341d8210890688fef7d958c22Yang Ni    clang::CallExpr* CE, int* slot, bool* hasOptions) {
97fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::Decl* D = CE->getCalleeDecl();
98fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(D);
99fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
100fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (FD == nullptr) {
101fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
102fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
103fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
104fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::StringRef& funcName = FD->getName();
105fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1061946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (funcName.equals(KERNEL_LAUNCH_FUNCTION_NAME)) {
1071946749cebf4a64341d8210890688fef7d958c22Yang Ni    *hasOptions = false;
1081946749cebf4a64341d8210890688fef7d958c22Yang Ni  } else if (funcName.equals(KERNEL_LAUNCH_FUNCTION_NAME_WITH_OPTIONS)) {
1091946749cebf4a64341d8210890688fef7d958c22Yang Ni    *hasOptions = true;
1101946749cebf4a64341d8210890688fef7d958c22Yang Ni  } else {
111fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
112fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
113fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1149319dfc974a82794d46e9f474f316590f480b976Yang Ni  if (mInsideKernel) {
1159319dfc974a82794d46e9f474f316590f480b976Yang Ni    mCtxt->ReportError(CE->getExprLoc(),
1169319dfc974a82794d46e9f474f316590f480b976Yang Ni        "Invalid kernel launch call made from inside another kernel.");
1179319dfc974a82794d46e9f474f316590f480b976Yang Ni    return nullptr;
1189319dfc974a82794d46e9f474f316590f480b976Yang Ni  }
1199319dfc974a82794d46e9f474f316590f480b976Yang Ni
1201946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::Expr* arg0 = CE->getArg(0);
1211946749cebf4a64341d8210890688fef7d958c22Yang Ni  const clang::FunctionDecl* kernel = matchFunctionDesignator(arg0);
1221946749cebf4a64341d8210890688fef7d958c22Yang Ni
1231946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (kernel == nullptr) {
1241946749cebf4a64341d8210890688fef7d958c22Yang Ni    mCtxt->ReportError(arg0->getExprLoc(),
1251946749cebf4a64341d8210890688fef7d958c22Yang Ni                       "Invalid kernel launch call. "
1261946749cebf4a64341d8210890688fef7d958c22Yang Ni                       "Expects a function designator for the first argument.");
1271946749cebf4a64341d8210890688fef7d958c22Yang Ni    return nullptr;
1281946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
129fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1301946749cebf4a64341d8210890688fef7d958c22Yang Ni  // Verifies that kernel is indeed a "kernel" function.
1311946749cebf4a64341d8210890688fef7d958c22Yang Ni  *slot = mCtxt->getForEachSlotNumber(kernel);
1321946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (*slot == -1) {
13340bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni    mCtxt->ReportError(CE->getExprLoc(),
13440bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni         "%0 applied to function %1 defined without \"kernel\" attribute")
13540bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni         << funcName << kernel->getName();
1361946749cebf4a64341d8210890688fef7d958c22Yang Ni    return nullptr;
137fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
138fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
139fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return kernel;
140fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
141fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
142fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// Create an AST node for the declaration of rsForEachInternal
143fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niclang::FunctionDecl* RSForEachLowering::CreateForEachInternalFunctionDecl() {
144fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclContext* DC = mASTCtxt.getTranslationUnitDecl();
145fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::SourceLocation Loc;
146fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
147fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  llvm::StringRef SR(INTERNAL_LAUNCH_FUNCTION_NAME);
148fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::IdentifierInfo& II = mASTCtxt.Idents.get(SR);
149fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclarationName N(&II);
150fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
151fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::FunctionProtoType::ExtProtoInfo EPI;
15288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
15388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const clang::QualType& AllocTy = mCtxt->getAllocationType();
15488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::QualType AllocPtrTy = mASTCtxt.getPointerType(AllocTy);
155fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1562615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  clang::QualType ScriptCallTy = mCtxt->getScriptCallType();
1572615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  const clang::QualType ScriptCallPtrTy = mASTCtxt.getPointerType(ScriptCallTy);
1582615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni
1592e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  clang::QualType ParamTypes[] = {
1602e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    mASTCtxt.IntTy,   // int slot
1612e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    ScriptCallPtrTy,  // rs_script_call_t* launch_options
1622e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    mASTCtxt.IntTy,   // int numOutput
1632e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    mASTCtxt.IntTy,   // int numInputs
1642e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    AllocPtrTy        // rs_allocation* allocs
1652e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  };
1662e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines
167fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::QualType T = mASTCtxt.getFunctionType(
1682e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines      mASTCtxt.VoidTy,  // Return type
1692e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines      ParamTypes,       // Parameter types
170fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      EPI);
171fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
172fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::FunctionDecl* FD = clang::FunctionDecl::Create(
173fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mASTCtxt, DC, Loc, Loc, N, T, nullptr, clang::SC_Extern);
1741946749cebf4a64341d8210890688fef7d958c22Yang Ni
1752e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  static constexpr unsigned kNumParams = sizeof(ParamTypes) / sizeof(ParamTypes[0]);
1762e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  clang::ParmVarDecl *ParamDecls[kNumParams];
1772e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  for (unsigned I = 0; I != kNumParams; ++I) {
1782e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    ParamDecls[I] = clang::ParmVarDecl::Create(mASTCtxt, FD, Loc,
1792e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines        Loc, nullptr, ParamTypes[I], nullptr, clang::SC_None, nullptr);
1802e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    // Implicit means that this declaration was created by the compiler, and
1812e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    // not part of the actual source code.
1822e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines    ParamDecls[I]->setImplicit();
1832e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  }
1842e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  FD->setParams(llvm::makeArrayRef(ParamDecls, kNumParams));
1852e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines
1862e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  // Implicit means that this declaration was created by the compiler, and
1872e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  // not part of the actual source code.
1882e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines  FD->setImplicit();
1892e9b1699b06a85cb15c95efe358cc665ad92ce3fStephen Hines
190fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return FD;
191fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
192fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
193fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// Create an expression like the following that references the rsForEachInternal to
1941946749cebf4a64341d8210890688fef7d958c22Yang Ni// replace the callee in the original call expression that references rsForEach.
195fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
1962615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni// ImplicitCastExpr 'void (*)(int, rs_script_call_t*, int, int, rs_allocation*)' <FunctionToPointerDecay>
1972615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni// `-DeclRefExpr 'void' Function '_Z17rsForEachInternaliP14rs_script_calliiP13rs_allocation' 'void (int, rs_script_call_t*, int, int, rs_allocation*)'
198fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niclang::Expr* RSForEachLowering::CreateCalleeExprForInternalForEach() {
199fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::FunctionDecl* FDNew = CreateForEachInternalFunctionDecl();
200fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
2012615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  const clang::QualType FDNewType = FDNew->getType();
2022615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni
203fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclRefExpr* refExpr = clang::DeclRefExpr::Create(
204fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mASTCtxt, clang::NestedNameSpecifierLoc(), clang::SourceLocation(), FDNew,
2052615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni      false, clang::SourceLocation(), FDNewType, clang::VK_RValue);
206fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
207fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::Expr* calleeNew = clang::ImplicitCastExpr::Create(
208fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mASTCtxt, mASTCtxt.getPointerType(FDNewType),
209fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::CK_FunctionToPointerDecay, refExpr, nullptr, clang::VK_RValue);
210fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
211fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return calleeNew;
212fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
213fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
214fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// This visit method checks (via pattern matching) if the call expression is to
2151946749cebf4a64341d8210890688fef7d958c22Yang Ni// rsForEach, and the arguments satisfy the restrictions on the
2161946749cebf4a64341d8210890688fef7d958c22Yang Ni// rsForEach API. If so, replace the call with a rsForEachInternal call
217fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// with the first argument replaced by the slot number of the kernel function
218fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// referenced in the original first argument.
219fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
220fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// See comments to the helper methods defined above for details.
221fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nivoid RSForEachLowering::VisitCallExpr(clang::CallExpr* CE) {
2221946749cebf4a64341d8210890688fef7d958c22Yang Ni  int slot;
2231946749cebf4a64341d8210890688fef7d958c22Yang Ni  bool hasOptions;
2241946749cebf4a64341d8210890688fef7d958c22Yang Ni  const clang::FunctionDecl* kernel = matchKernelLaunchCall(CE, &slot, &hasOptions);
225fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (kernel == nullptr) {
226fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return;
227fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
228fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
2291946749cebf4a64341d8210890688fef7d958c22Yang Ni  slangAssert(slot >= 0);
2301946749cebf4a64341d8210890688fef7d958c22Yang Ni
2311946749cebf4a64341d8210890688fef7d958c22Yang Ni  const unsigned numArgsOrig = CE->getNumArgs();
2321946749cebf4a64341d8210890688fef7d958c22Yang Ni
2331946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::QualType resultType = kernel->getReturnType().getCanonicalType();
23488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const unsigned numOutputsExpected = resultType->isVoidType() ? 0 : 1;
2351946749cebf4a64341d8210890688fef7d958c22Yang Ni
23688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const unsigned numInputsExpected = RSExportForEach::getNumInputs(mCtxt->getTargetAPI(), kernel);
2371946749cebf4a64341d8210890688fef7d958c22Yang Ni
2381946749cebf4a64341d8210890688fef7d958c22Yang Ni  // Verifies that rsForEach takes the right number of input and output allocations.
2391946749cebf4a64341d8210890688fef7d958c22Yang Ni  // TODO: Check input/output allocation types match kernel function expectation.
24088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const unsigned numAllocations = numArgsOrig - (hasOptions ? 2 : 1);
24188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  if (numInputsExpected + numOutputsExpected != numAllocations) {
2421946749cebf4a64341d8210890688fef7d958c22Yang Ni    mCtxt->ReportError(
2431946749cebf4a64341d8210890688fef7d958c22Yang Ni      CE->getExprLoc(),
2441946749cebf4a64341d8210890688fef7d958c22Yang Ni      "Number of input and output allocations unexpected for kernel function %0")
2451946749cebf4a64341d8210890688fef7d958c22Yang Ni    << kernel->getName();
2461946749cebf4a64341d8210890688fef7d958c22Yang Ni    return;
2471946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
2481946749cebf4a64341d8210890688fef7d958c22Yang Ni
249fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::Expr* calleeNew = CreateCalleeExprForInternalForEach();
250fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  CE->setCallee(calleeNew);
251fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
2521946749cebf4a64341d8210890688fef7d958c22Yang Ni  const clang::CanQualType IntTy = mASTCtxt.IntTy;
2531946749cebf4a64341d8210890688fef7d958c22Yang Ni  const unsigned IntTySize = mASTCtxt.getTypeSize(IntTy);
2541946749cebf4a64341d8210890688fef7d958c22Yang Ni  const llvm::APInt APIntSlot(IntTySize, slot);
255fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::Expr* arg0 = CE->getArg(0);
256fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::SourceLocation Loc(arg0->getLocStart());
257fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::Expr* IntSlotNum =
2581946749cebf4a64341d8210890688fef7d958c22Yang Ni      clang::IntegerLiteral::Create(mASTCtxt, APIntSlot, IntTy, Loc);
259fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  CE->setArg(0, IntSlotNum);
2601946749cebf4a64341d8210890688fef7d958c22Yang Ni
26188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  /*
26288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    The last few arguments to rsForEach or rsForEachWithOptions are allocations.
26388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    Creates a new compound literal of an array initialized with those values, and
26488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    passes it to rsForEachInternal as the last (the 5th) argument.
26588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
26688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    For example, rsForEach(foo, ain1, ain2, aout) would be translated into
26788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    rsForEachInternal(
26888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        1,                                   // Slot number for kernel
26988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        NULL,                                // Launch options
27088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        2,                                   // Number of input allocations
27188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        1,                                   // Number of output allocations
27288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        (rs_allocation[]){ain1, ain2, aout)  // Input and output allocations
27388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    );
27488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
27588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    The AST for the rs_allocation array looks like following:
27688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
27788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    ImplicitCastExpr 0x99575670 'struct rs_allocation *' <ArrayToPointerDecay>
27888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    `-CompoundLiteralExpr 0x99575648 'struct rs_allocation [3]' lvalue
27988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      `-InitListExpr 0x99575590 'struct rs_allocation [3]'
28088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      |-ImplicitCastExpr 0x99574b38 'rs_allocation':'struct rs_allocation' <LValueToRValue>
28188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      | `-DeclRefExpr 0x99574a08 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c408 'ain1' 'rs_allocation':'struct rs_allocation'
28288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      |-ImplicitCastExpr 0x99574b50 'rs_allocation':'struct rs_allocation' <LValueToRValue>
28388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      | `-DeclRefExpr 0x99574a30 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c478 'ain2' 'rs_allocation':'struct rs_allocation'
28488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      `-ImplicitCastExpr 0x99574b68 'rs_allocation':'struct rs_allocation' <LValueToRValue>
28588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        `-DeclRefExpr 0x99574a58 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c478 'aout' 'rs_allocation':'struct rs_allocation'
28688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  */
28788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
28888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const clang::QualType& AllocTy = mCtxt->getAllocationType();
28988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const llvm::APInt APIntNumAllocs(IntTySize, numAllocations);
29088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::QualType AllocArrayTy = mASTCtxt.getConstantArrayType(
29188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      AllocTy,
29288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      APIntNumAllocs,
29388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::ArrayType::ArraySizeModifier::Normal,
29488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      0  // index type qualifiers
29588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  );
29688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
29788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const int allocArgIndexEnd = numArgsOrig - 1;
29888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  int allocArgIndexStart = allocArgIndexEnd;
29988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
30088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::Expr** args = CE->getArgs();
30188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
30288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::SourceLocation lparenloc;
30388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::SourceLocation rparenloc;
30488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
30588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  if (numAllocations > 0) {
30688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    allocArgIndexStart = hasOptions ? 2 : 1;
30788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    lparenloc = args[allocArgIndexStart]->getExprLoc();
30888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    rparenloc = args[allocArgIndexEnd]->getExprLoc();
3091946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
3101946749cebf4a64341d8210890688fef7d958c22Yang Ni
31188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::InitListExpr* init = new (mASTCtxt) clang::InitListExpr(
31288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      mASTCtxt,
31388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      lparenloc,
31488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      llvm::ArrayRef<clang::Expr*>(args + allocArgIndexStart, numAllocations),
31588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      rparenloc);
31688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  init->setType(AllocArrayTy);
31788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
31888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::TypeSourceInfo* ti = mASTCtxt.getTrivialTypeSourceInfo(AllocArrayTy);
31988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::CompoundLiteralExpr* CLE = new (mASTCtxt) clang::CompoundLiteralExpr(
32088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      lparenloc,
32188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      ti,
32288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      AllocArrayTy,
32388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::VK_LValue,  // A compound literal is an l-value in C.
32488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      init,
32588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      false  // Not file scope
32688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  );
32788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
32888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const clang::QualType AllocPtrTy = mASTCtxt.getPointerType(AllocTy);
32988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
33088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::ImplicitCastExpr* Decay = clang::ImplicitCastExpr::Create(
33188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      mASTCtxt,
33288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      AllocPtrTy,
33388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::CK_ArrayToPointerDecay,
33488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      CLE,
33588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      nullptr,  // C++ cast path
33688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::VK_RValue
33788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  );
33888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
33988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  CE->setNumArgs(mASTCtxt, 5);
34088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
34188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  CE->setArg(4, Decay);
34288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
3431946749cebf4a64341d8210890688fef7d958c22Yang Ni  // Sets the new arguments for NULL launch option (if the user does not set one),
3441946749cebf4a64341d8210890688fef7d958c22Yang Ni  // the number of outputs, and the number of inputs.
3451946749cebf4a64341d8210890688fef7d958c22Yang Ni
3461946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (!hasOptions) {
3471946749cebf4a64341d8210890688fef7d958c22Yang Ni    const llvm::APInt APIntZero(IntTySize, 0);
3481946749cebf4a64341d8210890688fef7d958c22Yang Ni    clang::Expr* IntNull =
3491946749cebf4a64341d8210890688fef7d958c22Yang Ni        clang::IntegerLiteral::Create(mASTCtxt, APIntZero, IntTy, Loc);
3502615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    clang::QualType ScriptCallTy = mCtxt->getScriptCallType();
3512615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    const clang::QualType ScriptCallPtrTy = mASTCtxt.getPointerType(ScriptCallTy);
3522615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    clang::CStyleCastExpr* Cast =
3532615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        clang::CStyleCastExpr::Create(mASTCtxt,
3542615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      ScriptCallPtrTy,
3552615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::VK_RValue,
3562615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::CK_NullToPointer,
3572615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      IntNull,
3582615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      nullptr,
3592615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      mASTCtxt.getTrivialTypeSourceInfo(ScriptCallPtrTy),
3602615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::SourceLocation(),
3612615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::SourceLocation());
3622615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    CE->setArg(1, Cast);
3631946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
3641946749cebf4a64341d8210890688fef7d958c22Yang Ni
36588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const llvm::APInt APIntNumOutput(IntTySize, numOutputsExpected);
3661946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::Expr* IntNumOutput =
3671946749cebf4a64341d8210890688fef7d958c22Yang Ni      clang::IntegerLiteral::Create(mASTCtxt, APIntNumOutput, IntTy, Loc);
3681946749cebf4a64341d8210890688fef7d958c22Yang Ni  CE->setArg(2, IntNumOutput);
3691946749cebf4a64341d8210890688fef7d958c22Yang Ni
37088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const llvm::APInt APIntNumInputs(IntTySize, numInputsExpected);
3711946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::Expr* IntNumInputs =
3721946749cebf4a64341d8210890688fef7d958c22Yang Ni      clang::IntegerLiteral::Create(mASTCtxt, APIntNumInputs, IntTy, Loc);
3731946749cebf4a64341d8210890688fef7d958c22Yang Ni  CE->setArg(3, IntNumInputs);
374fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
375fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
376fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nivoid RSForEachLowering::VisitStmt(clang::Stmt* S) {
377fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  for (clang::Stmt* Child : S->children()) {
378fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    if (Child) {
379fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      Visit(Child);
380fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
381fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
382fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
383fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
3849319dfc974a82794d46e9f474f316590f480b976Yang Nivoid RSForEachLowering::handleForEachCalls(clang::FunctionDecl* FD,
3859319dfc974a82794d46e9f474f316590f480b976Yang Ni                                           unsigned int targetAPI) {
3869319dfc974a82794d46e9f474f316590f480b976Yang Ni  slangAssert(FD && FD->hasBody());
3879319dfc974a82794d46e9f474f316590f480b976Yang Ni
38840bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfaYang Ni  mInsideKernel = FD->hasAttr<clang::KernelAttr>();
3899319dfc974a82794d46e9f474f316590f480b976Yang Ni  VisitStmt(FD->getBody());
3909319dfc974a82794d46e9f474f316590f480b976Yang Ni}
3919319dfc974a82794d46e9f474f316590f480b976Yang Ni
392fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}  // namespace slang
393