slang_rs_foreach_lowering.cpp revision 40bac5d72af8fe32ab3d0bb38aafb5c65d8d9dfa
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