Merge "Revert "Handle kernel launch calls""
diff --git a/Android.mk b/Android.mk
index 3f56193..e2b991d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -148,7 +148,6 @@
LOCAL_SRC_FILES := \
llvm-rs-cc.cpp \
rs_cc_options.cpp \
- slang_rs_foreach_lowering.cpp \
slang_rs_ast_replace.cpp \
slang_rs_check_ast.cpp \
slang_rs_context.cpp \
diff --git a/slang_backend.cpp b/slang_backend.cpp
index 5ef86de..83c157f 100644
--- a/slang_backend.cpp
+++ b/slang_backend.cpp
@@ -223,7 +223,6 @@
mExportTypeMetadata(nullptr), mRSObjectSlotsMetadata(nullptr),
mRefCount(mContext->getASTContext()),
mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
- mForEachHandler(Context),
mLLVMContext(llvm::getGlobalContext()), mDiagEngine(*DiagEngine),
mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts, mLLVMContext);
@@ -368,32 +367,7 @@
}
}
-void Backend::LowerRSForEachCall(clang::FunctionDecl *FD) {
- // Skip this AST walking for lower API levels.
- if (getTargetAPI() < SLANG_DEVELOPMENT_TARGET_API) {
- return;
- }
-
- if (!FD || !FD->hasBody() ||
- Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
- return;
- }
-
- mForEachHandler.VisitStmt(FD->getBody());
-}
-
bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
- // Find and remember the TypeDecl for rs_allocation so we can use it
- // later during the compilation
- for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
- I != E; I++) {
- clang::TypeDecl* TD = llvm::dyn_cast<clang::TypeDecl>(*I);
- if (TD && TD->getName().equals("rs_allocation")) {
- mContext->addAllocationType(TD);
- break;
- }
- }
-
// Disallow user-defined functions with prefix "rs"
if (!mAllowRSPrefix) {
// Iterate all function declarations in the program.
@@ -412,8 +386,6 @@
}
}
- mContext->processExportDecl(D);
-
// Process any non-static function declarations
for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
@@ -433,10 +405,7 @@
}
AnnotateFunction(FD);
}
-
- LowerRSForEachCall(FD);
}
-
return mGen->HandleTopLevelDecl(D);
}
@@ -701,11 +670,10 @@
CI->setCallingConv(F->getCallingConv());
- if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext)) {
+ if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
IB->CreateRetVoid();
- } else {
+ else
IB->CreateRet(CI);
- }
delete IB;
}
diff --git a/slang_backend.h b/slang_backend.h
index 2c3b9b9..83912fd 100644
--- a/slang_backend.h
+++ b/slang_backend.h
@@ -26,7 +26,6 @@
#include "slang.h"
#include "slang_pragma_recorder.h"
#include "slang_rs_check_ast.h"
-#include "slang_rs_foreach_lowering.h"
#include "slang_rs_object_ref_count.h"
#include "slang_version.h"
@@ -104,8 +103,6 @@
RSCheckAST mASTChecker;
- RSForEachLowering mForEachHandler;
-
void AnnotateFunction(clang::FunctionDecl *FD);
void dumpExportVarInfo(llvm::Module *M);
@@ -114,8 +111,6 @@
void dumpExportReduceInfo(llvm::Module *M);
void dumpExportTypeInfo(llvm::Module *M);
- void LowerRSForEachCall(clang::FunctionDecl* FD);
-
protected:
llvm::LLVMContext &mLLVMContext;
clang::DiagnosticsEngine &mDiagEngine;
diff --git a/slang_rs_context.cpp b/slang_rs_context.cpp
index e840876..94eb6be 100644
--- a/slang_rs_context.cpp
+++ b/slang_rs_context.cpp
@@ -19,7 +19,6 @@
#include <string>
#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Mangle.h"
@@ -68,9 +67,6 @@
// Prepare target data
mDataLayout = new llvm::DataLayout(Target.getTargetDescription());
-
- // Reserve slot 0 for the root kernel.
- mExportForEach.push_back(nullptr);
}
bool RSContext::processExportVar(const clang::VarDecl *VD) {
@@ -91,19 +87,6 @@
return true;
}
-int RSContext::getForEachSlotNumber(const clang::FunctionDecl* FD) {
- const clang::StringRef& funcName = FD->getName();
- return getForEachSlotNumber(funcName);
-}
-
-int RSContext::getForEachSlotNumber(const clang::StringRef& funcName) {
- auto it = mExportForEachMap.find(funcName);
- if (it == mExportForEachMap.end()) {
- return -1;
- }
- return it->second;
-}
-
bool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
slangAssert(!FD->getName().empty() && "Function name should not be empty");
@@ -125,7 +108,11 @@
// Foreach kernel
if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
- return addForEach(FD);
+ if (auto *EFE = RSExportForEach::Create(this, FD)) {
+ mExportForEach.push_back(EFE);
+ return true;
+ }
+ return false;
}
// Reduce kernel
@@ -146,25 +133,6 @@
return false;
}
-bool RSContext::addForEach(const clang::FunctionDecl* FD) {
- RSExportForEach *EFE = RSExportForEach::Create(this, FD);
- if (EFE == nullptr) {
- return false;
- }
-
- const llvm::StringRef& funcName = FD->getName();
-
- if (funcName.equals("root")) {
- // The root kernel should always be in slot 0.
- mExportForEachMap.insert(std::make_pair(funcName, 0));
- mExportForEach[0] = EFE;
- } else {
- mExportForEachMap.insert(std::make_pair(funcName, mExportForEach.size()));
- mExportForEach.push_back(EFE);
- }
-
- return true;
-}
bool RSContext::processExportType(const llvm::StringRef &Name) {
clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
@@ -210,35 +178,42 @@
return (ET != nullptr);
}
-void RSContext::addAllocationType(const clang::TypeDecl* TD) {
- mAllocationType = mCtx.getTypeDeclType(TD);
-}
-bool RSContext::processExportDecl(const clang::DeclGroupRef& DGR) {
- bool valid = true;
- for (auto I = DGR.begin(), E = DGR.end(); valid && I != E; I++) {
- clang::Decl* D = *I;
- switch (D->getKind()) {
- case clang::Decl::Var: {
- clang::VarDecl* VD = llvm::dyn_cast<clang::VarDecl>(D);
- if (VD->getFormalLinkage() == clang::ExternalLinkage) {
- valid = processExportVar(VD);
+// Possibly re-order ForEach exports (maybe generating a dummy "root" function).
+// We require "root" to be listed as slot 0 of our exported compute kernels,
+// so this only needs to be created if we have other non-root kernels.
+void RSContext::cleanupForEach() {
+ bool foundNonRoot = false;
+ ExportForEachList::iterator begin = mExportForEach.begin();
+
+ for (ExportForEachList::iterator I = begin, E = mExportForEach.end();
+ I != E;
+ I++) {
+ RSExportForEach *EFE = *I;
+ if (!EFE->getName().compare("root")) {
+ if (I == begin) {
+ // Nothing to do, since it is the first function
+ return;
}
- break;
- }
- case clang::Decl::Function: {
- clang::FunctionDecl* FD = llvm::dyn_cast<clang::FunctionDecl>(D);
- if (FD->getFormalLinkage() == clang::ExternalLinkage) {
- valid = processExportFunc(FD);
- }
- break;
- }
- default: break;
+
+ mExportForEach.erase(I);
+ mExportForEach.push_front(EFE);
+ return;
+ } else {
+ foundNonRoot = true;
}
}
- return valid;
+
+ // If we found a non-root kernel, but no root() function, we need to add a
+ // dummy version (so that script->script calls of rsForEach don't behave
+ // erratically).
+ if (foundNonRoot) {
+ RSExportForEach *DummyRoot = RSExportForEach::CreateDummyRoot(this);
+ mExportForEach.push_front(DummyRoot);
+ }
}
+
bool RSContext::processExport() {
bool valid = true;
@@ -246,9 +221,32 @@
return false;
}
- // Create a dummy root in slot 0 if a root kernel is not seen.
- if (mExportForEach[0] == nullptr) {
- mExportForEach[0] = RSExportForEach::CreateDummyRoot(this);
+ // Export variable
+ clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
+ for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
+ DE = TUDecl->decls_end();
+ DI != DE;
+ DI++) {
+ if (DI->getKind() == clang::Decl::Var) {
+ clang::VarDecl *VD = (clang::VarDecl*) (*DI);
+ if (VD->getFormalLinkage() == clang::ExternalLinkage) {
+ if (!processExportVar(VD)) {
+ valid = false;
+ }
+ }
+ } else if (DI->getKind() == clang::Decl::Function) {
+ // Export functions
+ clang::FunctionDecl *FD = (clang::FunctionDecl*) (*DI);
+ if (FD->getFormalLinkage() == clang::ExternalLinkage) {
+ if (!processExportFunc(FD)) {
+ valid = false;
+ }
+ }
+ }
+ }
+
+ if (valid) {
+ cleanupForEach();
}
// Finally, export type forcely set to be exported by user
diff --git a/slang_rs_context.h b/slang_rs_context.h
index 78d3cb8..8cced4d 100644
--- a/slang_rs_context.h
+++ b/slang_rs_context.h
@@ -21,7 +21,6 @@
#include <list>
#include <map>
#include <string>
-#include <vector>
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/Mangle.h"
@@ -40,11 +39,8 @@
class VarDecl;
class ASTContext;
class TargetInfo;
- class DeclGroupRef;
class FunctionDecl;
- class QualType;
class SourceManager;
- class TypeDecl;
} // namespace clang
namespace slang {
@@ -64,7 +60,7 @@
typedef std::list<RSExportable*> ExportableList;
typedef std::list<RSExportVar*> ExportVarList;
typedef std::list<RSExportFunc*> ExportFuncList;
- typedef std::vector<RSExportForEach*> ExportForEachVector;
+ typedef std::list<RSExportForEach*> ExportForEachList;
typedef std::list<RSExportReduce*> ExportReduceList;
typedef llvm::StringMap<RSExportType*> ExportTypeMap;
@@ -101,18 +97,14 @@
bool processExportFunc(const clang::FunctionDecl *FD);
bool processExportType(const llvm::StringRef &Name);
- bool addForEach(const clang::FunctionDecl* FD);
- int getForEachSlotNumber(const clang::StringRef& funcName);
+ void cleanupForEach();
ExportVarList mExportVars;
ExportFuncList mExportFuncs;
- std::map<llvm::StringRef, unsigned> mExportForEachMap;
- ExportForEachVector mExportForEach;
+ ExportForEachList mExportForEach;
ExportReduceList mExportReduce;
ExportTypeMap mExportTypes;
- clang::QualType mAllocationType;
-
public:
RSContext(clang::Preprocessor &PP,
clang::ASTContext &Ctx,
@@ -167,12 +159,6 @@
inline const std::string &getRSPackageName() const { return mRSPackageName; }
- void addAllocationType(const clang::TypeDecl* TD);
- inline const clang::QualType& getAllocationType() const {
- return mAllocationType;
- }
-
- bool processExportDecl(const clang::DeclGroupRef& DGR);
bool processExport();
inline void newExportable(RSExportable *E) {
if (E != nullptr)
@@ -206,7 +192,7 @@
}
inline bool hasExportFunc() const { return !mExportFuncs.empty(); }
- typedef ExportForEachVector::const_iterator const_export_foreach_iterator;
+ typedef ExportForEachList::const_iterator const_export_foreach_iterator;
const_export_foreach_iterator export_foreach_begin() const {
return mExportForEach.begin();
}
@@ -214,7 +200,6 @@
return mExportForEach.end();
}
inline bool hasExportForEach() const { return !mExportForEach.empty(); }
- int getForEachSlotNumber(const clang::FunctionDecl* FD);
typedef ExportReduceList::const_iterator const_export_reduce_iterator;
const_export_reduce_iterator export_reduce_begin() const {
diff --git a/slang_rs_foreach_lowering.cpp b/slang_rs_foreach_lowering.cpp
deleted file mode 100644
index ab32c43..0000000
--- a/slang_rs_foreach_lowering.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "slang_rs_foreach_lowering.h"
-
-#include "clang/AST/ASTContext.h"
-#include "llvm/Support/raw_ostream.h"
-#include "slang_rs_context.h"
-#include "slang_rs_export_foreach.h"
-
-namespace slang {
-
-namespace {
-
-const char KERNEL_LAUNCH_FUNCTION_NAME[] = "rsParallelFor";
-const char INTERNAL_LAUNCH_FUNCTION_NAME[] =
- "_Z17rsForEachInternali13rs_allocationS_";
-
-} // anonymous namespace
-
-RSForEachLowering::RSForEachLowering(RSContext* ctxt)
- : mCtxt(ctxt), mASTCtxt(ctxt->getASTContext()) {}
-
-// Check if the passed-in expr references a kernel function in the following
-// pattern in the AST.
-//
-// ImplicitCastExpr 'void *' <BitCast>
-// `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
-// `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
-const clang::FunctionDecl* RSForEachLowering::matchFunctionDesignator(
- clang::Expr* expr) {
- clang::ImplicitCastExpr* ToVoidPtr =
- clang::dyn_cast<clang::ImplicitCastExpr>(expr);
- if (ToVoidPtr == nullptr) {
- return nullptr;
- }
-
- clang::ImplicitCastExpr* Decay =
- clang::dyn_cast<clang::ImplicitCastExpr>(ToVoidPtr->getSubExpr());
-
- if (Decay == nullptr) {
- return nullptr;
- }
-
- clang::DeclRefExpr* DRE =
- clang::dyn_cast<clang::DeclRefExpr>(Decay->getSubExpr());
-
- if (DRE == nullptr) {
- return nullptr;
- }
-
- const clang::FunctionDecl* FD =
- clang::dyn_cast<clang::FunctionDecl>(DRE->getDecl());
-
- if (FD == nullptr) {
- return nullptr;
- }
-
- // TODO: Verify the launch has the expected number of input allocations
-
- return FD;
-}
-
-// Checks if the call expression is a legal rsParallelFor call by looking for the
-// following pattern in the AST. On success, returns the first argument that is
-// a FunctionDecl of a kernel function.
-//
-// CallExpr 'void'
-// |
-// |-ImplicitCastExpr 'void (*)(void *, ...)' <FunctionToPointerDecay>
-// | `-DeclRefExpr 'void (void *, ...)' 'rsParallelFor' 'void (void *, ...)'
-// |
-// |-ImplicitCastExpr 'void *' <BitCast>
-// | `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
-// | `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
-// |
-// |-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
-// | `-DeclRefExpr 'rs_allocation':'rs_allocation' lvalue ParmVar 'in' 'rs_allocation':'rs_allocation'
-// |
-// `-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
-// `-DeclRefExpr 'rs_allocation':'rs_allocation' lvalue ParmVar 'out' 'rs_allocation':'rs_allocation'
-const clang::FunctionDecl* RSForEachLowering::matchKernelLaunchCall(
- clang::CallExpr* CE) {
- const clang::Decl* D = CE->getCalleeDecl();
- const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(D);
-
- if (FD == nullptr) {
- return nullptr;
- }
-
- const clang::StringRef& funcName = FD->getName();
-
- if (!funcName.equals(KERNEL_LAUNCH_FUNCTION_NAME)) {
- return nullptr;
- }
-
- const clang::FunctionDecl* kernel = matchFunctionDesignator(CE->getArg(0));
-
- if (kernel == nullptr ||
- CE->getNumArgs() < 3) { // TODO: Make argument check more accurate
- mCtxt->ReportError(CE->getExprLoc(), "Invalid kernel launch call.");
- }
-
- return kernel;
-}
-
-// Create an AST node for the declaration of rsForEachInternal
-clang::FunctionDecl* RSForEachLowering::CreateForEachInternalFunctionDecl() {
- const clang::QualType& AllocTy = mCtxt->getAllocationType();
- clang::DeclContext* DC = mASTCtxt.getTranslationUnitDecl();
- clang::SourceLocation Loc;
-
- llvm::StringRef SR(INTERNAL_LAUNCH_FUNCTION_NAME);
- clang::IdentifierInfo& II = mASTCtxt.Idents.get(SR);
- clang::DeclarationName N(&II);
-
- clang::FunctionProtoType::ExtProtoInfo EPI;
-
- clang::QualType T = mASTCtxt.getFunctionType(
- mASTCtxt.VoidTy, // Return type
- {mASTCtxt.IntTy, AllocTy, AllocTy}, // Argument types
- EPI);
-
- clang::FunctionDecl* FD = clang::FunctionDecl::Create(
- mASTCtxt, DC, Loc, Loc, N, T, nullptr, clang::SC_Extern);
- return FD;
-}
-
-// Create an expression like the following that references the rsForEachInternal to
-// replace the callee in the original call expression that references rsParallelFor.
-//
-// ImplicitCastExpr 'void (*)(int, rs_allocation, rs_allocation)' <FunctionToPointerDecay>
-// `-DeclRefExpr 'void' Function '_Z17rsForEachInternali13rs_allocationS_' 'void (int, rs_allocation, rs_allocation)'
-clang::Expr* RSForEachLowering::CreateCalleeExprForInternalForEach() {
- clang::FunctionDecl* FDNew = CreateForEachInternalFunctionDecl();
-
- clang::DeclRefExpr* refExpr = clang::DeclRefExpr::Create(
- mASTCtxt, clang::NestedNameSpecifierLoc(), clang::SourceLocation(), FDNew,
- false, clang::SourceLocation(), mASTCtxt.VoidTy, clang::VK_RValue);
-
- const clang::QualType FDNewType = FDNew->getType();
-
- clang::Expr* calleeNew = clang::ImplicitCastExpr::Create(
- mASTCtxt, mASTCtxt.getPointerType(FDNewType),
- clang::CK_FunctionToPointerDecay, refExpr, nullptr, clang::VK_RValue);
-
- return calleeNew;
-}
-
-// This visit method checks (via pattern matching) if the call expression is to
-// rsParallelFor, and the arguments satisfy the restrictions on the
-// rsParallelFor API. If so, replace the call with a rsForEachInternal call
-// with the first argument replaced by the slot number of the kernel function
-// referenced in the original first argument.
-//
-// See comments to the helper methods defined above for details.
-void RSForEachLowering::VisitCallExpr(clang::CallExpr* CE) {
- const clang::FunctionDecl* kernel = matchKernelLaunchCall(CE);
- if (kernel == nullptr) {
- return;
- }
-
- clang::Expr* calleeNew = CreateCalleeExprForInternalForEach();
- CE->setCallee(calleeNew);
-
- const int slot = mCtxt->getForEachSlotNumber(kernel);
- const llvm::APInt APIntSlot(mASTCtxt.getTypeSize(mASTCtxt.IntTy), slot);
- const clang::Expr* arg0 = CE->getArg(0);
- const clang::SourceLocation Loc(arg0->getLocStart());
- clang::Expr* IntSlotNum =
- clang::IntegerLiteral::Create(mASTCtxt, APIntSlot, mASTCtxt.IntTy, Loc);
- CE->setArg(0, IntSlotNum);
-}
-
-void RSForEachLowering::VisitStmt(clang::Stmt* S) {
- for (clang::Stmt* Child : S->children()) {
- if (Child) {
- Visit(Child);
- }
- }
-}
-
-} // namespace slang
diff --git a/slang_rs_foreach_lowering.h b/slang_rs_foreach_lowering.h
deleted file mode 100644
index 6cb0e62..0000000
--- a/slang_rs_foreach_lowering.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _FRAMEWORKS_COMPILE_SLANG_RS_FOREACH_LOWERING_H
-#define _FRAMEWORKS_COMPILE_SLANG_RS_FOREACH_LOWERING_H
-
-#include "clang/AST/StmtVisitor.h"
-
-namespace clang {
- class ASTContext;
- class CallExpr;
- class Expr;
- class FunctionDecl;
-}
-
-namespace slang {
-
-class RSContext;
-
-class RSForEachLowering : public clang::StmtVisitor<RSForEachLowering> {
- public:
- RSForEachLowering(RSContext* ctxt);
-
- void VisitCallExpr(clang::CallExpr *CE);
- void VisitStmt(clang::Stmt *S);
-
- private:
- RSContext* mCtxt;
- clang::ASTContext& mASTCtxt;
-
- const clang::FunctionDecl* matchFunctionDesignator(clang::Expr* expr);
- const clang::FunctionDecl* matchKernelLaunchCall(clang::CallExpr* CE);
- clang::FunctionDecl* CreateForEachInternalFunctionDecl();
- clang::Expr* CreateCalleeExprForInternalForEach();
-}; // RSForEachLowering
-
-} // namespace slang
-
-#endif // _FRAMEWORKS_COMPILE_SLANG_RS_FOREACH_LOWERING_H