slang_rs_foreach_lowering.cpp revision 9319dfc974a82794d46e9f474f316590f480b976
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"
20fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "llvm/Support/raw_ostream.h"
21fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "slang_rs_context.h"
22fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni#include "slang_rs_export_foreach.h"
23fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
24fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ninamespace slang {
25fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
26fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ninamespace {
27fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
281946749cebf4a64341d8210890688fef7d958c22Yang Niconst char KERNEL_LAUNCH_FUNCTION_NAME[] = "rsForEach";
291946749cebf4a64341d8210890688fef7d958c22Yang Niconst char KERNEL_LAUNCH_FUNCTION_NAME_WITH_OPTIONS[] = "rsForEachWithOptions";
30fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niconst char INTERNAL_LAUNCH_FUNCTION_NAME[] =
3188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    "_Z17rsForEachInternaliP14rs_script_calliiP13rs_allocation";
32fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
33fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}  // anonymous namespace
34fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
35fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang NiRSForEachLowering::RSForEachLowering(RSContext* ctxt)
36fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    : mCtxt(ctxt), mASTCtxt(ctxt->getASTContext()) {}
37fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
38fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// Check if the passed-in expr references a kernel function in the following
39fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// pattern in the AST.
40fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
41fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// ImplicitCastExpr 'void *' <BitCast>
42fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//  `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
43fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//    `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
44fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niconst clang::FunctionDecl* RSForEachLowering::matchFunctionDesignator(
45fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    clang::Expr* expr) {
46fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::ImplicitCastExpr* ToVoidPtr =
47fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::ImplicitCastExpr>(expr);
48fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (ToVoidPtr == nullptr) {
49fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
50fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
51fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
52fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::ImplicitCastExpr* Decay =
53fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::ImplicitCastExpr>(ToVoidPtr->getSubExpr());
54fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
55fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (Decay == nullptr) {
56fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
57fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
58fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
59fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclRefExpr* DRE =
60fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::DeclRefExpr>(Decay->getSubExpr());
61fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
62fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (DRE == nullptr) {
63fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
64fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
65fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
66fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::FunctionDecl* FD =
67fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::dyn_cast<clang::FunctionDecl>(DRE->getDecl());
68fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
69fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (FD == nullptr) {
70fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
71fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
72fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
73fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return FD;
74fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
75fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
761946749cebf4a64341d8210890688fef7d958c22Yang Ni// Checks if the call expression is a legal rsForEach call by looking for the
77fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// following pattern in the AST. On success, returns the first argument that is
78fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// a FunctionDecl of a kernel function.
79fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
80fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// CallExpr 'void'
81fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
82fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |-ImplicitCastExpr 'void (*)(void *, ...)' <FunctionToPointerDecay>
831946749cebf4a64341d8210890688fef7d958c22Yang Ni// | `-DeclRefExpr  'void (void *, ...)'  'rsForEach' 'void (void *, ...)'
84fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
85fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |-ImplicitCastExpr 'void *' <BitCast>
86fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// | `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
87fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |   `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
88fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
89fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
90fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// | `-DeclRefExpr 'rs_allocation':'rs_allocation' lvalue ParmVar 'in' 'rs_allocation':'rs_allocation'
91fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// |
92fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// `-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
93fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//   `-DeclRefExpr  'rs_allocation':'rs_allocation' lvalue ParmVar 'out' 'rs_allocation':'rs_allocation'
94fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niconst clang::FunctionDecl* RSForEachLowering::matchKernelLaunchCall(
951946749cebf4a64341d8210890688fef7d958c22Yang Ni    clang::CallExpr* CE, int* slot, bool* hasOptions) {
96fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::Decl* D = CE->getCalleeDecl();
97fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(D);
98fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
99fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (FD == nullptr) {
100fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
101fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
102fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
103fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::StringRef& funcName = FD->getName();
104fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1051946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (funcName.equals(KERNEL_LAUNCH_FUNCTION_NAME)) {
1061946749cebf4a64341d8210890688fef7d958c22Yang Ni    *hasOptions = false;
1071946749cebf4a64341d8210890688fef7d958c22Yang Ni  } else if (funcName.equals(KERNEL_LAUNCH_FUNCTION_NAME_WITH_OPTIONS)) {
1081946749cebf4a64341d8210890688fef7d958c22Yang Ni    *hasOptions = true;
1091946749cebf4a64341d8210890688fef7d958c22Yang Ni  } else {
110fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return nullptr;
111fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
112fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1139319dfc974a82794d46e9f474f316590f480b976Yang Ni  if (mInsideKernel) {
1149319dfc974a82794d46e9f474f316590f480b976Yang Ni    mCtxt->ReportError(CE->getExprLoc(),
1159319dfc974a82794d46e9f474f316590f480b976Yang Ni        "Invalid kernel launch call made from inside another kernel.");
1169319dfc974a82794d46e9f474f316590f480b976Yang Ni    return nullptr;
1179319dfc974a82794d46e9f474f316590f480b976Yang Ni  }
1189319dfc974a82794d46e9f474f316590f480b976Yang Ni
1191946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::Expr* arg0 = CE->getArg(0);
1201946749cebf4a64341d8210890688fef7d958c22Yang Ni  const clang::FunctionDecl* kernel = matchFunctionDesignator(arg0);
1211946749cebf4a64341d8210890688fef7d958c22Yang Ni
1221946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (kernel == nullptr) {
1231946749cebf4a64341d8210890688fef7d958c22Yang Ni    mCtxt->ReportError(arg0->getExprLoc(),
1241946749cebf4a64341d8210890688fef7d958c22Yang Ni                       "Invalid kernel launch call. "
1251946749cebf4a64341d8210890688fef7d958c22Yang Ni                       "Expects a function designator for the first argument.");
1261946749cebf4a64341d8210890688fef7d958c22Yang Ni    return nullptr;
1271946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
128fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1291946749cebf4a64341d8210890688fef7d958c22Yang Ni  // Verifies that kernel is indeed a "kernel" function.
1301946749cebf4a64341d8210890688fef7d958c22Yang Ni  *slot = mCtxt->getForEachSlotNumber(kernel);
1311946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (*slot == -1) {
1321946749cebf4a64341d8210890688fef7d958c22Yang Ni    mCtxt->ReportError(CE->getExprLoc(), "%0 applied to non kernel function %1")
1331946749cebf4a64341d8210890688fef7d958c22Yang Ni            << funcName << kernel->getName();
1341946749cebf4a64341d8210890688fef7d958c22Yang Ni    return nullptr;
135fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
136fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
137fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return kernel;
138fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
139fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
140fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// Create an AST node for the declaration of rsForEachInternal
141fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niclang::FunctionDecl* RSForEachLowering::CreateForEachInternalFunctionDecl() {
142fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclContext* DC = mASTCtxt.getTranslationUnitDecl();
143fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::SourceLocation Loc;
144fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
145fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  llvm::StringRef SR(INTERNAL_LAUNCH_FUNCTION_NAME);
146fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::IdentifierInfo& II = mASTCtxt.Idents.get(SR);
147fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclarationName N(&II);
148fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
149fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::FunctionProtoType::ExtProtoInfo EPI;
15088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
15188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const clang::QualType& AllocTy = mCtxt->getAllocationType();
15288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::QualType AllocPtrTy = mASTCtxt.getPointerType(AllocTy);
153fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1542615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  clang::QualType ScriptCallTy = mCtxt->getScriptCallType();
1552615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  const clang::QualType ScriptCallPtrTy = mASTCtxt.getPointerType(ScriptCallTy);
1562615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni
157fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::QualType T = mASTCtxt.getFunctionType(
1582615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni      mASTCtxt.VoidTy,    // Return type
1592615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                          // Argument types:
1602615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni      { mASTCtxt.IntTy,   // int slot
1612615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        ScriptCallPtrTy,  // rs_script_call_t* launch_options
1622615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        mASTCtxt.IntTy,   // int numOutput
1632615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        mASTCtxt.IntTy,   // int numInputs
1642615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        AllocPtrTy        // rs_allocation* allocs
1651946749cebf4a64341d8210890688fef7d958c22Yang Ni      },
166fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      EPI);
167fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
168fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::FunctionDecl* FD = clang::FunctionDecl::Create(
169fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mASTCtxt, DC, Loc, Loc, N, T, nullptr, clang::SC_Extern);
1701946749cebf4a64341d8210890688fef7d958c22Yang Ni
171fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return FD;
172fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
173fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
174fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// Create an expression like the following that references the rsForEachInternal to
1751946749cebf4a64341d8210890688fef7d958c22Yang Ni// replace the callee in the original call expression that references rsForEach.
176fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
1772615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni// ImplicitCastExpr 'void (*)(int, rs_script_call_t*, int, int, rs_allocation*)' <FunctionToPointerDecay>
1782615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni// `-DeclRefExpr 'void' Function '_Z17rsForEachInternaliP14rs_script_calliiP13rs_allocation' 'void (int, rs_script_call_t*, int, int, rs_allocation*)'
179fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Niclang::Expr* RSForEachLowering::CreateCalleeExprForInternalForEach() {
180fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::FunctionDecl* FDNew = CreateForEachInternalFunctionDecl();
181fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
1822615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni  const clang::QualType FDNewType = FDNew->getType();
1832615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni
184fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::DeclRefExpr* refExpr = clang::DeclRefExpr::Create(
185fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mASTCtxt, clang::NestedNameSpecifierLoc(), clang::SourceLocation(), FDNew,
1862615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni      false, clang::SourceLocation(), FDNewType, clang::VK_RValue);
187fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
188fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::Expr* calleeNew = clang::ImplicitCastExpr::Create(
189fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      mASTCtxt, mASTCtxt.getPointerType(FDNewType),
190fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      clang::CK_FunctionToPointerDecay, refExpr, nullptr, clang::VK_RValue);
191fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
192fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  return calleeNew;
193fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
194fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
195fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// This visit method checks (via pattern matching) if the call expression is to
1961946749cebf4a64341d8210890688fef7d958c22Yang Ni// rsForEach, and the arguments satisfy the restrictions on the
1971946749cebf4a64341d8210890688fef7d958c22Yang Ni// rsForEach API. If so, replace the call with a rsForEachInternal call
198fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// with the first argument replaced by the slot number of the kernel function
199fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// referenced in the original first argument.
200fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni//
201fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni// See comments to the helper methods defined above for details.
202fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nivoid RSForEachLowering::VisitCallExpr(clang::CallExpr* CE) {
2031946749cebf4a64341d8210890688fef7d958c22Yang Ni  int slot;
2041946749cebf4a64341d8210890688fef7d958c22Yang Ni  bool hasOptions;
2051946749cebf4a64341d8210890688fef7d958c22Yang Ni  const clang::FunctionDecl* kernel = matchKernelLaunchCall(CE, &slot, &hasOptions);
206fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  if (kernel == nullptr) {
207fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    return;
208fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
209fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
2101946749cebf4a64341d8210890688fef7d958c22Yang Ni  slangAssert(slot >= 0);
2111946749cebf4a64341d8210890688fef7d958c22Yang Ni
2121946749cebf4a64341d8210890688fef7d958c22Yang Ni  const unsigned numArgsOrig = CE->getNumArgs();
2131946749cebf4a64341d8210890688fef7d958c22Yang Ni
2141946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::QualType resultType = kernel->getReturnType().getCanonicalType();
21588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const unsigned numOutputsExpected = resultType->isVoidType() ? 0 : 1;
2161946749cebf4a64341d8210890688fef7d958c22Yang Ni
21788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const unsigned numInputsExpected = RSExportForEach::getNumInputs(mCtxt->getTargetAPI(), kernel);
2181946749cebf4a64341d8210890688fef7d958c22Yang Ni
2191946749cebf4a64341d8210890688fef7d958c22Yang Ni  // Verifies that rsForEach takes the right number of input and output allocations.
2201946749cebf4a64341d8210890688fef7d958c22Yang Ni  // TODO: Check input/output allocation types match kernel function expectation.
22188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const unsigned numAllocations = numArgsOrig - (hasOptions ? 2 : 1);
22288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  if (numInputsExpected + numOutputsExpected != numAllocations) {
2231946749cebf4a64341d8210890688fef7d958c22Yang Ni    mCtxt->ReportError(
2241946749cebf4a64341d8210890688fef7d958c22Yang Ni      CE->getExprLoc(),
2251946749cebf4a64341d8210890688fef7d958c22Yang Ni      "Number of input and output allocations unexpected for kernel function %0")
2261946749cebf4a64341d8210890688fef7d958c22Yang Ni    << kernel->getName();
2271946749cebf4a64341d8210890688fef7d958c22Yang Ni    return;
2281946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
2291946749cebf4a64341d8210890688fef7d958c22Yang Ni
230fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::Expr* calleeNew = CreateCalleeExprForInternalForEach();
231fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  CE->setCallee(calleeNew);
232fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
2331946749cebf4a64341d8210890688fef7d958c22Yang Ni  const clang::CanQualType IntTy = mASTCtxt.IntTy;
2341946749cebf4a64341d8210890688fef7d958c22Yang Ni  const unsigned IntTySize = mASTCtxt.getTypeSize(IntTy);
2351946749cebf4a64341d8210890688fef7d958c22Yang Ni  const llvm::APInt APIntSlot(IntTySize, slot);
236fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::Expr* arg0 = CE->getArg(0);
237fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  const clang::SourceLocation Loc(arg0->getLocStart());
238fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  clang::Expr* IntSlotNum =
2391946749cebf4a64341d8210890688fef7d958c22Yang Ni      clang::IntegerLiteral::Create(mASTCtxt, APIntSlot, IntTy, Loc);
240fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  CE->setArg(0, IntSlotNum);
2411946749cebf4a64341d8210890688fef7d958c22Yang Ni
24288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  /*
24388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    The last few arguments to rsForEach or rsForEachWithOptions are allocations.
24488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    Creates a new compound literal of an array initialized with those values, and
24588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    passes it to rsForEachInternal as the last (the 5th) argument.
24688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
24788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    For example, rsForEach(foo, ain1, ain2, aout) would be translated into
24888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    rsForEachInternal(
24988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        1,                                   // Slot number for kernel
25088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        NULL,                                // Launch options
25188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        2,                                   // Number of input allocations
25288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        1,                                   // Number of output allocations
25388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        (rs_allocation[]){ain1, ain2, aout)  // Input and output allocations
25488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    );
25588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
25688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    The AST for the rs_allocation array looks like following:
25788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
25888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    ImplicitCastExpr 0x99575670 'struct rs_allocation *' <ArrayToPointerDecay>
25988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    `-CompoundLiteralExpr 0x99575648 'struct rs_allocation [3]' lvalue
26088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      `-InitListExpr 0x99575590 'struct rs_allocation [3]'
26188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      |-ImplicitCastExpr 0x99574b38 'rs_allocation':'struct rs_allocation' <LValueToRValue>
26288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      | `-DeclRefExpr 0x99574a08 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c408 'ain1' 'rs_allocation':'struct rs_allocation'
26388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      |-ImplicitCastExpr 0x99574b50 'rs_allocation':'struct rs_allocation' <LValueToRValue>
26488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      | `-DeclRefExpr 0x99574a30 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c478 'ain2' 'rs_allocation':'struct rs_allocation'
26588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      `-ImplicitCastExpr 0x99574b68 'rs_allocation':'struct rs_allocation' <LValueToRValue>
26688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni        `-DeclRefExpr 0x99574a58 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c478 'aout' 'rs_allocation':'struct rs_allocation'
26788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  */
26888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
26988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const clang::QualType& AllocTy = mCtxt->getAllocationType();
27088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const llvm::APInt APIntNumAllocs(IntTySize, numAllocations);
27188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::QualType AllocArrayTy = mASTCtxt.getConstantArrayType(
27288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      AllocTy,
27388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      APIntNumAllocs,
27488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::ArrayType::ArraySizeModifier::Normal,
27588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      0  // index type qualifiers
27688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  );
27788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
27888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const int allocArgIndexEnd = numArgsOrig - 1;
27988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  int allocArgIndexStart = allocArgIndexEnd;
28088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
28188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::Expr** args = CE->getArgs();
28288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
28388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::SourceLocation lparenloc;
28488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::SourceLocation rparenloc;
28588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
28688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  if (numAllocations > 0) {
28788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    allocArgIndexStart = hasOptions ? 2 : 1;
28888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    lparenloc = args[allocArgIndexStart]->getExprLoc();
28988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni    rparenloc = args[allocArgIndexEnd]->getExprLoc();
2901946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
2911946749cebf4a64341d8210890688fef7d958c22Yang Ni
29288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::InitListExpr* init = new (mASTCtxt) clang::InitListExpr(
29388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      mASTCtxt,
29488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      lparenloc,
29588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      llvm::ArrayRef<clang::Expr*>(args + allocArgIndexStart, numAllocations),
29688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      rparenloc);
29788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  init->setType(AllocArrayTy);
29888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
29988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::TypeSourceInfo* ti = mASTCtxt.getTrivialTypeSourceInfo(AllocArrayTy);
30088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::CompoundLiteralExpr* CLE = new (mASTCtxt) clang::CompoundLiteralExpr(
30188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      lparenloc,
30288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      ti,
30388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      AllocArrayTy,
30488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::VK_LValue,  // A compound literal is an l-value in C.
30588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      init,
30688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      false  // Not file scope
30788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  );
30888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
30988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const clang::QualType AllocPtrTy = mASTCtxt.getPointerType(AllocTy);
31088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
31188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  clang::ImplicitCastExpr* Decay = clang::ImplicitCastExpr::Create(
31288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      mASTCtxt,
31388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      AllocPtrTy,
31488f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::CK_ArrayToPointerDecay,
31588f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      CLE,
31688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      nullptr,  // C++ cast path
31788f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni      clang::VK_RValue
31888f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  );
31988f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
32088f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  CE->setNumArgs(mASTCtxt, 5);
32188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
32288f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  CE->setArg(4, Decay);
32388f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni
3241946749cebf4a64341d8210890688fef7d958c22Yang Ni  // Sets the new arguments for NULL launch option (if the user does not set one),
3251946749cebf4a64341d8210890688fef7d958c22Yang Ni  // the number of outputs, and the number of inputs.
3261946749cebf4a64341d8210890688fef7d958c22Yang Ni
3271946749cebf4a64341d8210890688fef7d958c22Yang Ni  if (!hasOptions) {
3281946749cebf4a64341d8210890688fef7d958c22Yang Ni    const llvm::APInt APIntZero(IntTySize, 0);
3291946749cebf4a64341d8210890688fef7d958c22Yang Ni    clang::Expr* IntNull =
3301946749cebf4a64341d8210890688fef7d958c22Yang Ni        clang::IntegerLiteral::Create(mASTCtxt, APIntZero, IntTy, Loc);
3312615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    clang::QualType ScriptCallTy = mCtxt->getScriptCallType();
3322615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    const clang::QualType ScriptCallPtrTy = mASTCtxt.getPointerType(ScriptCallTy);
3332615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    clang::CStyleCastExpr* Cast =
3342615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni        clang::CStyleCastExpr::Create(mASTCtxt,
3352615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      ScriptCallPtrTy,
3362615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::VK_RValue,
3372615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::CK_NullToPointer,
3382615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      IntNull,
3392615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      nullptr,
3402615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      mASTCtxt.getTrivialTypeSourceInfo(ScriptCallPtrTy),
3412615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::SourceLocation(),
3422615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni                                      clang::SourceLocation());
3432615f383dfc1542a05f19aee23b03a09bd018f4eYang Ni    CE->setArg(1, Cast);
3441946749cebf4a64341d8210890688fef7d958c22Yang Ni  }
3451946749cebf4a64341d8210890688fef7d958c22Yang Ni
34688f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const llvm::APInt APIntNumOutput(IntTySize, numOutputsExpected);
3471946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::Expr* IntNumOutput =
3481946749cebf4a64341d8210890688fef7d958c22Yang Ni      clang::IntegerLiteral::Create(mASTCtxt, APIntNumOutput, IntTy, Loc);
3491946749cebf4a64341d8210890688fef7d958c22Yang Ni  CE->setArg(2, IntNumOutput);
3501946749cebf4a64341d8210890688fef7d958c22Yang Ni
35188f21e16250d2e52a75607b7f0c396e1c2a34201Yang Ni  const llvm::APInt APIntNumInputs(IntTySize, numInputsExpected);
3521946749cebf4a64341d8210890688fef7d958c22Yang Ni  clang::Expr* IntNumInputs =
3531946749cebf4a64341d8210890688fef7d958c22Yang Ni      clang::IntegerLiteral::Create(mASTCtxt, APIntNumInputs, IntTy, Loc);
3541946749cebf4a64341d8210890688fef7d958c22Yang Ni  CE->setArg(3, IntNumInputs);
355fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
356fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
357fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Nivoid RSForEachLowering::VisitStmt(clang::Stmt* S) {
358fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  for (clang::Stmt* Child : S->children()) {
359fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    if (Child) {
360fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni      Visit(Child);
361fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni    }
362fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni  }
363fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}
364fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni
3659319dfc974a82794d46e9f474f316590f480b976Yang Nivoid RSForEachLowering::handleForEachCalls(clang::FunctionDecl* FD,
3669319dfc974a82794d46e9f474f316590f480b976Yang Ni                                           unsigned int targetAPI) {
3679319dfc974a82794d46e9f474f316590f480b976Yang Ni  slangAssert(FD && FD->hasBody());
3689319dfc974a82794d46e9f474f316590f480b976Yang Ni
3699319dfc974a82794d46e9f474f316590f480b976Yang Ni  mInsideKernel = RSExportForEach::isRSForEachFunc(targetAPI, FD);
3709319dfc974a82794d46e9f474f316590f480b976Yang Ni  VisitStmt(FD->getBody());
3719319dfc974a82794d46e9f474f316590f480b976Yang Ni}
3729319dfc974a82794d46e9f474f316590f480b976Yang Ni
373fb40ee2a90f37967bf4a40a18dec7f60e5c580d8Yang Ni}  // namespace slang
374