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