Merge Slang with SlangRS, Backend with RSBackend.
Change-Id: I4721f92c10ec14a886923778595289f96d3a8de5
(cherry picked from commit 8024ed54c23c08534434da14d3be99c3efcc5754)
diff --git a/Android.mk b/Android.mk
index 72ab0a4..5e2afb5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -144,12 +144,10 @@
LOCAL_SRC_FILES := \
llvm-rs-cc.cpp \
rs_cc_options.cpp \
- slang_rs.cpp \
slang_rs_ast_replace.cpp \
slang_rs_check_ast.cpp \
slang_rs_context.cpp \
slang_rs_pragma_handler.cpp \
- slang_rs_backend.cpp \
slang_rs_exportable.cpp \
slang_rs_export_type.cpp \
slang_rs_export_element.cpp \
diff --git a/llvm-rs-cc.cpp b/llvm-rs-cc.cpp
index 4730710..6b879e0 100644
--- a/llvm-rs-cc.cpp
+++ b/llvm-rs-cc.cpp
@@ -35,7 +35,6 @@
#include "slang.h"
#include "slang_assert.h"
#include "slang_diagnostic_buffer.h"
-#include "slang_rs.h"
#include "slang_rs_reflect_utils.h"
#include <list>
@@ -181,7 +180,7 @@
IOFiles->push_back(std::make_pair(InputFile, OutputFile));
}
- std::unique_ptr<slang::SlangRS> Compiler(new slang::SlangRS());
+ std::unique_ptr<slang::Slang> Compiler(new slang::Slang());
Compiler->init(Opts.mBitWidth, DiagEngine, DiagClient);
int CompileFailed = !Compiler->compile(*IOFiles, *IOFiles32, DepFiles, Opts);
// We suppress warnings (via reset) if we are doing a second compilation.
diff --git a/slang.cpp b/slang.cpp
index 731e671..fd51e7a 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -18,7 +18,11 @@
#include <stdlib.h>
+#include <cstring>
+#include <list>
+#include <sstream>
#include <string>
+#include <utility>
#include <vector>
#include "clang/AST/ASTConsumer.h"
@@ -29,6 +33,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
@@ -47,6 +52,8 @@
#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Bitcode/ReaderWriter.h"
@@ -66,9 +73,19 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "os_sep.h"
+#include "rs_cc_options.h"
#include "slang_assert.h"
#include "slang_backend.h"
+#include "slang_backend.h"
+#include "slang_rs_context.h"
+#include "slang_rs_export_type.h"
+
+#include "slang_rs_reflection.h"
+#include "slang_rs_reflection_cpp.h"
+
+
namespace {
static const char *kRSTriple32 = "armv7-none-linux-gnueabi";
@@ -78,6 +95,32 @@
namespace slang {
+
+#define FS_SUFFIX "fs"
+
+#define RS_HEADER_SUFFIX "rsh"
+
+/* RS_HEADER_ENTRY(name) */
+#define ENUM_RS_HEADER() \
+ RS_HEADER_ENTRY(rs_allocation_data) \
+ RS_HEADER_ENTRY(rs_atomic) \
+ RS_HEADER_ENTRY(rs_convert) \
+ RS_HEADER_ENTRY(rs_core) \
+ RS_HEADER_ENTRY(rs_debug) \
+ RS_HEADER_ENTRY(rs_for_each) \
+ RS_HEADER_ENTRY(rs_graphics) \
+ RS_HEADER_ENTRY(rs_graphics_types) \
+ RS_HEADER_ENTRY(rs_io) \
+ RS_HEADER_ENTRY(rs_math) \
+ RS_HEADER_ENTRY(rs_matrix) \
+ RS_HEADER_ENTRY(rs_object_info) \
+ RS_HEADER_ENTRY(rs_object_types) \
+ RS_HEADER_ENTRY(rs_quaternion) \
+ RS_HEADER_ENTRY(rs_time) \
+ RS_HEADER_ENTRY(rs_value_types) \
+ RS_HEADER_ENTRY(rs_vector_math) \
+
+
bool Slang::GlobalInitialized = false;
// Language option (define the language feature for compiler such as C99)
@@ -216,27 +259,38 @@
}
void Slang::createASTContext() {
- mASTContext.reset(new clang::ASTContext(LangOpts,
- *mSourceMgr,
- mPP->getIdentifierTable(),
- mPP->getSelectorTable(),
- mPP->getBuiltinInfo()));
+ mASTContext.reset(
+ new clang::ASTContext(LangOpts, *mSourceMgr, mPP->getIdentifierTable(),
+ mPP->getSelectorTable(), mPP->getBuiltinInfo()));
mASTContext->InitBuiltinTypes(getTargetInfo());
initASTContext();
}
clang::ASTConsumer *
-Slang::createBackend(const clang::CodeGenOptions& CodeGenOpts,
- llvm::raw_ostream *OS, OutputType OT) {
- return new Backend(mDiagEngine, CodeGenOpts, getTargetOptions(),
- &mPragmas, OS, OT);
+Slang::createBackend(const clang::CodeGenOptions &CodeGenOpts,
+ llvm::raw_ostream *OS, Slang::OutputType OT) {
+ return new Backend(mRSContext, &getDiagnostics(), CodeGenOpts,
+ getTargetOptions(), &mPragmas, OS, OT, getSourceManager(),
+ mAllowRSPrefix, mIsFilterscript);
}
-Slang::Slang() : mInitialized(false), mDiagClient(nullptr),
- mTargetOpts(new clang::TargetOptions()), mOT(OT_Default) {
+Slang::Slang()
+ : mInitialized(false), mDiagClient(nullptr),
+ mTargetOpts(new clang::TargetOptions()), mOT(OT_Default),
+ mRSContext(nullptr), mAllowRSPrefix(false), mTargetAPI(0),
+ mVerbose(false), mIsFilterscript(false) {
GlobalInitialization();
}
+Slang::~Slang() {
+ delete mRSContext;
+ for (ReflectedDefinitionListTy::iterator I = ReflectedDefinitions.begin(),
+ E = ReflectedDefinitions.end();
+ I != E; I++) {
+ delete I->getValue().first;
+ }
+}
+
void Slang::init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
DiagnosticBuffer *DiagClient) {
if (mInitialized)
@@ -264,26 +318,6 @@
return clang::ModuleLoadResult();
}
-bool Slang::setInputSource(llvm::StringRef InputFile,
- const char *Text,
- size_t TextLength) {
- mInputFileName = InputFile.str();
-
- // Reset the ID tables if we are reusing the SourceManager
- mSourceMgr->clearIDTables();
-
- // Load the source
- std::unique_ptr<llvm::MemoryBuffer> SB =
- llvm::MemoryBuffer::getMemBuffer(Text, Text + TextLength);
- mSourceMgr->setMainFileID(mSourceMgr->createFileID(std::move(SB)));
-
- if (mSourceMgr->getMainFileID().isInvalid()) {
- mDiagEngine->Report(clang::diag::err_fe_error_reading) << InputFile;
- return false;
- }
- return true;
-}
-
bool Slang::setInputSource(llvm::StringRef InputFile) {
mInputFileName = InputFile.str();
@@ -441,6 +475,10 @@
}
void Slang::reset(bool SuppressWarnings) {
+ delete mRSContext;
+ mRSContext = nullptr;
+ mGeneratedFileNames.clear();
+
// Always print diagnostics if we had an error occur, but don't print
// warnings if we suppressed them (i.e. we are doing the 64-bit compile after
// an existing 32-bit compile).
@@ -459,7 +497,358 @@
llvm::remove_fatal_error_handler();
}
-Slang::~Slang() {
+// Returns true if \p Filename ends in ".fs".
+bool Slang::isFilterscript(const char *Filename) {
+ const char *c = strrchr(Filename, '.');
+ if (c && !strncmp(FS_SUFFIX, c + 1, strlen(FS_SUFFIX) + 1)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Slang::generateJavaBitcodeAccessor(const std::string &OutputPathBase,
+ const std::string &PackageName,
+ const std::string *LicenseNote) {
+ RSSlangReflectUtils::BitCodeAccessorContext BCAccessorContext;
+
+ BCAccessorContext.rsFileName = getInputFileName().c_str();
+ BCAccessorContext.bc32FileName = getOutput32FileName().c_str();
+ BCAccessorContext.bc64FileName = getOutputFileName().c_str();
+ BCAccessorContext.reflectPath = OutputPathBase.c_str();
+ BCAccessorContext.packageName = PackageName.c_str();
+ BCAccessorContext.licenseNote = LicenseNote;
+ BCAccessorContext.bcStorage = BCST_JAVA_CODE; // Must be BCST_JAVA_CODE
+ BCAccessorContext.verbose = false;
+
+ return RSSlangReflectUtils::GenerateJavaBitCodeAccessor(BCAccessorContext);
+}
+
+bool Slang::checkODR(const char *CurInputFile) {
+ for (RSContext::ExportableList::iterator I = mRSContext->exportable_begin(),
+ E = mRSContext->exportable_end();
+ I != E;
+ I++) {
+ RSExportable *RSE = *I;
+ if (RSE->getKind() != RSExportable::EX_TYPE)
+ continue;
+
+ RSExportType *ET = static_cast<RSExportType *>(RSE);
+ if (ET->getClass() != RSExportType::ExportClassRecord)
+ continue;
+
+ RSExportRecordType *ERT = static_cast<RSExportRecordType *>(ET);
+
+ // Artificial record types (create by us not by user in the source) always
+ // conforms the ODR.
+ if (ERT->isArtificial())
+ continue;
+
+ // Key to lookup ERT in ReflectedDefinitions
+ llvm::StringRef RDKey(ERT->getName());
+ ReflectedDefinitionListTy::const_iterator RD =
+ ReflectedDefinitions.find(RDKey);
+
+ if (RD != ReflectedDefinitions.end()) {
+ const RSExportRecordType *Reflected = RD->getValue().first;
+ // There's a record (struct) with the same name reflected before. Enforce
+ // ODR checking - the Reflected must hold *exactly* the same "definition"
+ // as the one defined previously. We say two record types A and B have the
+ // same definition iff:
+ //
+ // struct A { struct B {
+ // Type(a1) a1, Type(b1) b1,
+ // Type(a2) a2, Type(b1) b2,
+ // ... ...
+ // Type(aN) aN Type(b3) b3,
+ // }; }
+ // Cond. #1. They have same number of fields, i.e., N = M;
+ // Cond. #2. for (i := 1 to N)
+ // Type(ai) = Type(bi) must hold;
+ // Cond. #3. for (i := 1 to N)
+ // Name(ai) = Name(bi) must hold;
+ //
+ // where,
+ // Type(F) = the type of field F and
+ // Name(F) = the field name.
+
+ bool PassODR = false;
+ // Cond. #1 and Cond. #2
+ if (Reflected->equals(ERT)) {
+ // Cond #3.
+ RSExportRecordType::const_field_iterator AI = Reflected->fields_begin(),
+ BI = ERT->fields_begin();
+
+ for (unsigned i = 0, e = Reflected->getFields().size(); i != e; i++) {
+ if ((*AI)->getName() != (*BI)->getName())
+ break;
+ AI++;
+ BI++;
+ }
+ PassODR = (AI == (Reflected->fields_end()));
+ }
+
+ if (!PassODR) {
+ getDiagnostics().Report(mDiagErrorODR) << Reflected->getName()
+ << getInputFileName()
+ << RD->getValue().second;
+ return false;
+ }
+ } else {
+ llvm::StringMapEntry<ReflectedDefinitionTy> *ME =
+ llvm::StringMapEntry<ReflectedDefinitionTy>::Create(RDKey);
+ ME->setValue(std::make_pair(ERT, CurInputFile));
+
+ if (!ReflectedDefinitions.insert(ME))
+ delete ME;
+
+ // Take the ownership of ERT such that it won't be freed in ~RSContext().
+ ERT->keep();
+ }
+ }
+ return true;
+}
+
+void Slang::initDiagnostic() {
+ clang::DiagnosticsEngine &DiagEngine = getDiagnostics();
+ const auto Flavor = clang::diag::Flavor::WarningOrError;
+
+ if (DiagEngine.setSeverityForGroup(Flavor, "implicit-function-declaration",
+ clang::diag::Severity::Error)) {
+ DiagEngine.Report(clang::diag::warn_unknown_diag_option)
+ << /* clang::diag::Flavor::WarningOrError */ 0
+ << "implicit-function-declaration";
+ }
+
+ DiagEngine.setSeverity(
+ clang::diag::ext_typecheck_convert_discards_qualifiers,
+ clang::diag::Severity::Error,
+ clang::SourceLocation());
+
+ mDiagErrorInvalidOutputDepParameter =
+ DiagEngine.getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "invalid parameter for output dependencies files.");
+
+ mDiagErrorODR =
+ DiagEngine.getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "type '%0' in different translation unit (%1 v.s. %2) "
+ "has incompatible type definition");
+
+ mDiagErrorTargetAPIRange =
+ DiagEngine.getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "target API level '%0' is out of range ('%1' - '%2')");
+}
+
+void Slang::initPreprocessor() {
+ clang::Preprocessor &PP = getPreprocessor();
+
+ std::stringstream RSH;
+ RSH << PP.getPredefines();
+ RSH << "#define RS_VERSION " << mTargetAPI << "\n";
+ RSH << "#include \"rs_core." RS_HEADER_SUFFIX "\"\n";
+ PP.setPredefines(RSH.str());
+}
+
+void Slang::initASTContext() {
+ mRSContext = new RSContext(getPreprocessor(),
+ getASTContext(),
+ getTargetInfo(),
+ &mPragmas,
+ mTargetAPI,
+ mVerbose);
+}
+
+bool Slang::IsRSHeaderFile(const char *File) {
+#define RS_HEADER_ENTRY(name) \
+ if (::strcmp(File, #name "." RS_HEADER_SUFFIX) == 0) \
+ return true;
+ENUM_RS_HEADER()
+#undef RS_HEADER_ENTRY
+ return false;
+}
+
+bool Slang::IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
+ const clang::SourceManager &SourceMgr) {
+ clang::FullSourceLoc FSL(Loc, SourceMgr);
+ clang::PresumedLoc PLoc = SourceMgr.getPresumedLoc(FSL);
+
+ const char *Filename = PLoc.getFilename();
+ if (!Filename) {
+ return false;
+ } else {
+ return IsRSHeaderFile(llvm::sys::path::filename(Filename).data());
+ }
+}
+
+bool Slang::compile(
+ const std::list<std::pair<const char*, const char*> > &IOFiles64,
+ const std::list<std::pair<const char*, const char*> > &IOFiles32,
+ const std::list<std::pair<const char*, const char*> > &DepFiles,
+ const RSCCOptions &Opts) {
+ if (IOFiles32.empty())
+ return true;
+
+ if (Opts.mEmitDependency && (DepFiles.size() != IOFiles32.size())) {
+ getDiagnostics().Report(mDiagErrorInvalidOutputDepParameter);
+ return false;
+ }
+
+ if (Opts.mEmit3264 && (IOFiles64.size() != IOFiles32.size())) {
+ slangAssert(false && "Should have equal number of 32/64-bit files");
+ return false;
+ }
+
+ std::string RealPackageName;
+
+ const char *InputFile, *Output64File, *Output32File, *BCOutputFile,
+ *DepOutputFile;
+ std::list<std::pair<const char*, const char*> >::const_iterator
+ IOFile64Iter = IOFiles64.begin(),
+ IOFile32Iter = IOFiles32.begin(),
+ DepFileIter = DepFiles.begin();
+
+ setIncludePaths(Opts.mIncludePaths);
+ setOutputType(Opts.mOutputType);
+ if (Opts.mEmitDependency) {
+ setAdditionalDepTargets(Opts.mAdditionalDepTargets);
+ }
+
+ setDebugMetadataEmission(Opts.mDebugEmission);
+
+ setOptimizationLevel(Opts.mOptimizationLevel);
+
+ mAllowRSPrefix = Opts.mAllowRSPrefix;
+
+ mTargetAPI = Opts.mTargetAPI;
+ if (mTargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
+ (mTargetAPI < SLANG_MINIMUM_TARGET_API ||
+ mTargetAPI > SLANG_MAXIMUM_TARGET_API)) {
+ getDiagnostics().Report(mDiagErrorTargetAPIRange) << mTargetAPI
+ << SLANG_MINIMUM_TARGET_API << SLANG_MAXIMUM_TARGET_API;
+ return false;
+ }
+
+ mVerbose = Opts.mVerbose;
+
+ // Skip generation of warnings a second time if we are doing more than just
+ // a single pass over the input file.
+ bool SuppressAllWarnings = (Opts.mOutputType != Slang::OT_Dependency);
+
+ bool CompileSecondTimeFor64Bit = Opts.mEmit3264 && Opts.mBitWidth == 64;
+
+ for (unsigned i = 0, e = IOFiles32.size(); i != e; i++) {
+ InputFile = IOFile64Iter->first;
+ Output64File = IOFile64Iter->second;
+ Output32File = IOFile32Iter->second;
+
+ // We suppress warnings (via reset) if we are doing a second compilation.
+ reset(CompileSecondTimeFor64Bit);
+
+ if (!setInputSource(InputFile))
+ return false;
+
+ if (!setOutput(Output64File))
+ return false;
+
+ setOutput32(Output32File);
+
+ mIsFilterscript = isFilterscript(InputFile);
+
+ if (Slang::compile() > 0)
+ return false;
+
+ if (!Opts.mJavaReflectionPackageName.empty()) {
+ mRSContext->setReflectJavaPackageName(Opts.mJavaReflectionPackageName);
+ }
+ const std::string &RealPackageName =
+ mRSContext->getReflectJavaPackageName();
+
+ bool doReflection = true;
+ if (Opts.mEmit3264 && (Opts.mBitWidth == 32)) {
+ // Skip reflection on the 32-bit path if we are going to emit it on the
+ // 64-bit path.
+ doReflection = false;
+ }
+ if (Opts.mOutputType != Slang::OT_Dependency && doReflection) {
+
+ if (Opts.mBitcodeStorage == BCST_CPP_CODE) {
+ const std::string &outputFileName = (Opts.mBitWidth == 64) ?
+ getOutputFileName() : getOutput32FileName();
+ RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
+ getInputFileName(), outputFileName);
+ if (!R.reflect()) {
+ return false;
+ }
+ } else {
+ if (!Opts.mRSPackageName.empty()) {
+ mRSContext->setRSPackageName(Opts.mRSPackageName);
+ }
+
+ RSReflectionJava R(mRSContext, &mGeneratedFileNames,
+ Opts.mJavaReflectionPathBase, getInputFileName(),
+ getOutputFileName(),
+ Opts.mBitcodeStorage == BCST_JAVA_CODE);
+ if (!R.reflect()) {
+ // TODO Is this needed or will the error message have been printed
+ // already? and why not for the C++ case?
+ fprintf(stderr, "RSContext::reflectToJava : failed to do reflection "
+ "(%s)\n",
+ R.getLastError());
+ return false;
+ }
+
+ for (std::vector<std::string>::const_iterator
+ I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
+ I != E;
+ I++) {
+ std::string ReflectedName = RSSlangReflectUtils::ComputePackagedPath(
+ Opts.mJavaReflectionPathBase.c_str(),
+ (RealPackageName + OS_PATH_SEPARATOR_STR + *I).c_str());
+ appendGeneratedFileName(ReflectedName + ".java");
+ }
+
+ if ((Opts.mOutputType == Slang::OT_Bitcode) &&
+ (Opts.mBitcodeStorage == BCST_JAVA_CODE) &&
+ !generateJavaBitcodeAccessor(Opts.mJavaReflectionPathBase,
+ RealPackageName.c_str(),
+ mRSContext->getLicenseNote())) {
+ return false;
+ }
+ }
+ }
+
+ if (Opts.mEmitDependency) {
+ BCOutputFile = DepFileIter->first;
+ DepOutputFile = DepFileIter->second;
+
+ setDepTargetBC(BCOutputFile);
+
+ if (!setDepOutput(DepOutputFile))
+ return false;
+
+ if (SuppressAllWarnings) {
+ getDiagnostics().setSuppressAllDiagnostics(true);
+ }
+ if (generateDepFile() > 0)
+ return false;
+ if (SuppressAllWarnings) {
+ getDiagnostics().setSuppressAllDiagnostics(false);
+ }
+
+ DepFileIter++;
+ }
+
+ if (!checkODR(InputFile))
+ return false;
+
+ IOFile64Iter++;
+ IOFile32Iter++;
+ }
+
+ return true;
}
} // namespace slang
diff --git a/slang.h b/slang.h
index 6483c44..2b40adb 100644
--- a/slang.h
+++ b/slang.h
@@ -18,9 +18,16 @@
#define _FRAMEWORKS_COMPILE_SLANG_SLANG_H_
#include <cstdio>
+#include <list>
#include <string>
+#include <utility>
#include <vector>
+#include "llvm/ADT/StringMap.h"
+
+#include "slang_rs_reflect_utils.h"
+#include "slang_version.h"
+
// Terrible workaround for TargetOptions.h not using llvm::RefCountedBase!
#include "llvm/ADT/IntrusiveRefCntPtr.h"
using llvm::RefCountedBase;
@@ -56,15 +63,11 @@
namespace slang {
+class RSCCOptions;
+class RSContext;
+class RSExportRecordType;
+
class Slang : public clang::ModuleLoader {
- static clang::LangOptions LangOpts;
- static clang::CodeGenOptions CodeGenOpts;
-
- static bool GlobalInitialized;
-
- static void LLVMErrorHandler(void *UserData, const std::string &Message,
- bool GenCrashDialog);
-
public:
enum OutputType {
OT_Dependency,
@@ -78,6 +81,17 @@
};
private:
+ static clang::LangOptions LangOpts;
+ static clang::CodeGenOptions CodeGenOpts;
+
+ static bool GlobalInitialized;
+
+ static void LLVMErrorHandler(void *UserData, const std::string &Message,
+ bool GenCrashDialog);
+
+ // Returns true if this is a Filterscript file.
+ static bool isFilterscript(const char *Filename);
+
bool mInitialized;
// Diagnostics Mediator (An interface for both Producer and Consumer)
@@ -95,32 +109,26 @@
std::unique_ptr<clang::TargetInfo> mTarget;
void createTarget(uint32_t BitWidth);
-
// File manager (for prepocessor doing the job such as header file search)
std::unique_ptr<clang::FileManager> mFileMgr;
std::unique_ptr<clang::FileSystemOptions> mFileSysOpt;
void createFileManager();
-
// Source manager (responsible for the source code handling)
std::unique_ptr<clang::SourceManager> mSourceMgr;
void createSourceManager();
-
// Preprocessor (source code preprocessor)
std::unique_ptr<clang::Preprocessor> mPP;
void createPreprocessor();
-
// AST context (the context to hold long-lived AST nodes)
std::unique_ptr<clang::ASTContext> mASTContext;
void createASTContext();
-
// AST consumer, responsible for code generation
std::unique_ptr<clang::ASTConsumer> mBackend;
-
// File names
std::string mInputFileName;
std::string mOutputFileName;
@@ -129,7 +137,6 @@
std::string mDepOutputFileName;
std::string mDepTargetBCFileName;
std::vector<std::string> mAdditionalDepTargets;
- std::vector<std::string> mGeneratedFileNames;
OutputType mOT;
@@ -141,9 +148,45 @@
std::vector<std::string> mIncludePaths;
- protected:
+ // Context for Renderscript
+ RSContext *mRSContext;
+
+ bool mAllowRSPrefix;
+
+ unsigned int mTargetAPI;
+
+ bool mVerbose;
+
+ bool mIsFilterscript;
+
+ // Custom diagnostic identifiers
+ unsigned mDiagErrorInvalidOutputDepParameter;
+ unsigned mDiagErrorODR;
+ unsigned mDiagErrorTargetAPIRange;
+
+ // Collect generated filenames (without the .java) for dependency generation
+ std::vector<std::string> mGeneratedFileNames;
+
PragmaList mPragmas;
+ // FIXME: Should be std::list<RSExportable *> here. But currently we only
+ // check ODR on record type.
+ //
+ // ReflectedDefinitions maps record type name to a pair:
+ // <its RSExportRecordType instance,
+ // the first file contains this record type definition>
+ typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy;
+ typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy;
+ ReflectedDefinitionListTy ReflectedDefinitions;
+
+ bool generateJavaBitcodeAccessor(const std::string &OutputPathBase,
+ const std::string &PackageName,
+ const std::string *LicenseNote);
+
+ // CurInputFile is the pointer to a char array holding the input filename
+ // and is valid before compile() ends.
+ bool checkODR(const char *CurInputFile);
+
clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
clang::FileManager &getFileManager() { return *mFileMgr; }
@@ -154,34 +197,32 @@
inline clang::TargetOptions const &getTargetOptions() const
{ return *mTargetOpts.get(); }
- virtual void initDiagnostic() {}
- virtual void initPreprocessor() {}
- virtual void initASTContext() {}
+ void initDiagnostic();
+ void initPreprocessor();
+ void initASTContext();
- virtual clang::ASTConsumer *
- createBackend(const clang::CodeGenOptions& CodeGenOpts,
- llvm::raw_ostream *OS,
- OutputType OT);
+ clang::ASTConsumer *createBackend(const clang::CodeGenOptions &CodeGenOpts,
+ llvm::raw_ostream *OS,
+ Slang::OutputType OT);
public:
static const llvm::StringRef PragmaMetadataName;
static void GlobalInitialization();
+ static bool IsRSHeaderFile(const char *File);
+ // FIXME: Determine whether a location is in RS header (i.e., one of the RS
+ // built-in APIs) should only need its names (we need a "list" of RS
+ // built-in APIs).
+ static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
+ const clang::SourceManager &SourceMgr);
+
Slang();
+ virtual ~Slang();
void init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
DiagnosticBuffer *DiagClient);
- virtual clang::ModuleLoadResult loadModule(
- clang::SourceLocation ImportLoc,
- clang::ModuleIdPath Path,
- clang::Module::NameVisibilityKind VK,
- bool IsInclusionDirective);
-
- bool setInputSource(llvm::StringRef InputFile, const char *Text,
- size_t TextLength);
-
bool setInputSource(llvm::StringRef InputFile);
std::string const &getInputFileName() const { return mInputFileName; }
@@ -235,11 +276,41 @@
// Reset the slang compiler state such that it can be reused to compile
// another file
- virtual void reset(bool SuppressWarnings = false);
+ void reset(bool SuppressWarnings = false);
- virtual ~Slang();
+ // Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
+ // all given input files are successfully compiled without errors.
+ //
+ // @IOFiles - List of pairs of <input file path, output file path>.
+ //
+ // @DepFiles - List of pairs of <output dep. file path, dependent bitcode
+ // target>. If @OutputDep is true, this parameter must be given
+ // with the same number of pairs given in @IOFiles.
+ //
+ // @Opts - Selection of options defined from invoking llvm-rs-cc
+ bool
+ compile(const std::list<std::pair<const char *, const char *>> &IOFiles64,
+ const std::list<std::pair<const char *, const char *>> &IOFiles32,
+ const std::list<std::pair<const char *, const char *>> &DepFiles,
+ const RSCCOptions &Opts);
+
+ clang::ModuleLoadResult loadModule(clang::SourceLocation ImportLoc,
+ clang::ModuleIdPath Path,
+ clang::Module::NameVisibilityKind VK,
+ bool IsInclusionDirective) override;
+
+ void makeModuleVisible(clang::Module *Mod,
+ clang::Module::NameVisibilityKind Visibility,
+ clang::SourceLocation ImportLoc,
+ bool Complain = false) override {}
+
+ clang::GlobalModuleIndex *
+ loadGlobalModuleIndex(clang::SourceLocation TriggerLoc) override {}
+
+ bool lookupMissingImports(llvm::StringRef Name,
+ clang::SourceLocation TriggerLoc) override {}
};
-} // namespace slang
+} // namespace slang
#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_ NOLINT
diff --git a/slang_backend.cpp b/slang_backend.cpp
index 9ed1a88..1a45b41 100644
--- a/slang_backend.cpp
+++ b/slang_backend.cpp
@@ -34,20 +34,28 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
-#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/TargetRegistry.h"
@@ -55,6 +63,14 @@
#include "llvm/MC/SubtargetFeature.h"
#include "slang_assert.h"
+#include "slang.h"
+#include "slang_rs_context.h"
+#include "slang_rs_export_foreach.h"
+#include "slang_rs_export_func.h"
+#include "slang_rs_export_type.h"
+#include "slang_rs_export_var.h"
+#include "slang_rs_metadata.h"
+
#include "strip_unknown_attributes.h"
#include "BitWriter_2_9/ReaderWriter_2_9.h"
#include "BitWriter_2_9_func/ReaderWriter_2_9_func.h"
@@ -198,25 +214,23 @@
return true;
}
-Backend::Backend(clang::DiagnosticsEngine *DiagEngine,
+Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
const clang::CodeGenOptions &CodeGenOpts,
- const clang::TargetOptions &TargetOpts,
- PragmaList *Pragmas,
- llvm::raw_ostream *OS,
- Slang::OutputType OT)
- : ASTConsumer(),
- mTargetOpts(TargetOpts),
- mpModule(nullptr),
- mpOS(OS),
- mOT(OT),
- mGen(nullptr),
- mPerFunctionPasses(nullptr),
- mPerModulePasses(nullptr),
- mCodeGenPasses(nullptr),
- mLLVMContext(llvm::getGlobalContext()),
- mDiagEngine(*DiagEngine),
- mCodeGenOpts(CodeGenOpts),
- mPragmas(Pragmas) {
+ const clang::TargetOptions &TargetOpts, PragmaList *Pragmas,
+ llvm::raw_ostream *OS, Slang::OutputType OT,
+ clang::SourceManager &SourceMgr, bool AllowRSPrefix,
+ bool IsFilterscript)
+ : ASTConsumer(), mTargetOpts(TargetOpts), mpModule(nullptr), mpOS(OS),
+ mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr),
+ mPerModulePasses(nullptr), mCodeGenPasses(nullptr), mContext(Context),
+ mSourceMgr(SourceMgr), mAllowRSPrefix(AllowRSPrefix),
+ mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
+ mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
+ mExportForEachSignatureMetadata(nullptr), mExportTypeMetadata(nullptr),
+ mRSObjectSlotsMetadata(nullptr), mRefCount(mContext->getASTContext()),
+ mASTChecker(Context, Context->getTargetAPI(), IsFilterscript),
+ mLLVMContext(llvm::getGlobalContext()), mDiagEngine(*DiagEngine),
+ mCodeGenOpts(CodeGenOpts), mPragmas(Pragmas) {
FormattedOutStream.setStream(*mpOS,
llvm::formatted_raw_ostream::PRESERVE_STREAM);
mGen = CreateLLVMCodeGen(mDiagEngine, "", mCodeGenOpts, mLLVMContext);
@@ -244,10 +258,6 @@
FormattedOutStream << Bitcode.str();
}
-bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
- return mGen->HandleTopLevelDecl(D);
-}
-
void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
HandleTranslationUnitPre(Ctx);
@@ -400,4 +410,455 @@
delete mCodeGenPasses;
}
+// 1) Add zero initialization of local RS object types
+void Backend::AnnotateFunction(clang::FunctionDecl *FD) {
+ if (FD &&
+ FD->hasBody() &&
+ !Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
+ mRefCount.Init();
+ mRefCount.Visit(FD->getBody());
+ }
+}
+
+bool Backend::HandleTopLevelDecl(clang::DeclGroupRef D) {
+ // Disallow user-defined functions with prefix "rs"
+ if (!mAllowRSPrefix) {
+ // Iterate all function declarations in the program.
+ for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
+ I != E; I++) {
+ clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
+ if (FD == nullptr)
+ continue;
+ if (!FD->getName().startswith("rs")) // Check prefix
+ continue;
+ if (!Slang::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
+ mContext->ReportError(FD->getLocation(),
+ "invalid function name prefix, "
+ "\"rs\" is reserved: '%0'")
+ << FD->getName();
+ }
+ }
+
+ // 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);
+ if (FD && FD->isGlobal()) {
+ // Check that we don't have any array parameters being misintrepeted as
+ // kernel pointers due to the C type system's array to pointer decay.
+ size_t numParams = FD->getNumParams();
+ for (size_t i = 0; i < numParams; i++) {
+ const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
+ clang::QualType QT = PVD->getOriginalType();
+ if (QT->isArrayType()) {
+ mContext->ReportError(
+ PVD->getTypeSpecStartLoc(),
+ "exported function parameters may not have array type: %0")
+ << QT;
+ }
+ }
+ AnnotateFunction(FD);
+ }
+ }
+ return mGen->HandleTopLevelDecl(D);
+}
+
+void Backend::HandleTranslationUnitPre(clang::ASTContext &C) {
+ clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
+
+ // If we have an invalid RS/FS AST, don't check further.
+ if (!mASTChecker.Validate()) {
+ return;
+ }
+
+ if (mIsFilterscript) {
+ mContext->addPragma("rs_fp_relaxed", "");
+ }
+
+ int version = mContext->getVersion();
+ if (version == 0) {
+ // Not setting a version is an error
+ mDiagEngine.Report(
+ mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
+ mDiagEngine.getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "missing pragma for version in source file"));
+ } else {
+ slangAssert(version == 1);
+ }
+
+ if (mContext->getReflectJavaPackageName().empty()) {
+ mDiagEngine.Report(
+ mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
+ mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
+ "missing \"#pragma rs "
+ "java_package_name(com.foo.bar)\" "
+ "in source file"));
+ return;
+ }
+
+ // Create a static global destructor if necessary (to handle RS object
+ // runtime cleanup).
+ clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
+ if (FD) {
+ HandleTopLevelDecl(clang::DeclGroupRef(FD));
+ }
+
+ // Process any static function declarations
+ for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
+ E = TUDecl->decls_end(); I != E; I++) {
+ if ((I->getKind() >= clang::Decl::firstFunction) &&
+ (I->getKind() <= clang::Decl::lastFunction)) {
+ clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
+ if (FD && !FD->isGlobal()) {
+ AnnotateFunction(FD);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void Backend::dumpExportVarInfo(llvm::Module *M) {
+ int slotCount = 0;
+ if (mExportVarMetadata == nullptr)
+ mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
+
+ llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
+
+ // We emit slot information (#rs_object_slots) for any reference counted
+ // RS type or pointer (which can also be bound).
+
+ for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
+ E = mContext->export_vars_end();
+ I != E;
+ I++) {
+ const RSExportVar *EV = *I;
+ const RSExportType *ET = EV->getType();
+ bool countsAsRSObject = false;
+
+ // Variable name
+ ExportVarInfo.push_back(
+ llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
+
+ // Type name
+ switch (ET->getClass()) {
+ case RSExportType::ExportClassPrimitive: {
+ const RSExportPrimitiveType *PT =
+ static_cast<const RSExportPrimitiveType*>(ET);
+ ExportVarInfo.push_back(
+ llvm::MDString::get(
+ mLLVMContext, llvm::utostr_32(PT->getType())));
+ if (PT->isRSObjectType()) {
+ countsAsRSObject = true;
+ }
+ break;
+ }
+ case RSExportType::ExportClassPointer: {
+ ExportVarInfo.push_back(
+ llvm::MDString::get(
+ mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
+ ->getPointeeType()->getName()).c_str()));
+ break;
+ }
+ case RSExportType::ExportClassMatrix: {
+ ExportVarInfo.push_back(
+ llvm::MDString::get(
+ mLLVMContext, llvm::utostr_32(
+ /* TODO Strange value. This pushes just a number, quite
+ * different than the other cases. What is this used for?
+ * These are the metadata values that some partner drivers
+ * want to reference (for TBAA, etc.). We may want to look
+ * at whether these provide any reasonable value (or have
+ * distinct enough values to actually depend on).
+ */
+ DataTypeRSMatrix2x2 +
+ static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
+ break;
+ }
+ case RSExportType::ExportClassVector:
+ case RSExportType::ExportClassConstantArray:
+ case RSExportType::ExportClassRecord: {
+ ExportVarInfo.push_back(
+ llvm::MDString::get(mLLVMContext,
+ EV->getType()->getName().c_str()));
+ break;
+ }
+ }
+
+ mExportVarMetadata->addOperand(
+ llvm::MDNode::get(mLLVMContext, ExportVarInfo));
+ ExportVarInfo.clear();
+
+ if (mRSObjectSlotsMetadata == nullptr) {
+ mRSObjectSlotsMetadata =
+ M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
+ }
+
+ if (countsAsRSObject) {
+ mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
+ llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
+ }
+
+ slotCount++;
+ }
+}
+
+void Backend::dumpExportFunctionInfo(llvm::Module *M) {
+ if (mExportFuncMetadata == nullptr)
+ mExportFuncMetadata =
+ M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
+
+ llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
+
+ for (RSContext::const_export_func_iterator
+ I = mContext->export_funcs_begin(),
+ E = mContext->export_funcs_end();
+ I != E;
+ I++) {
+ const RSExportFunc *EF = *I;
+
+ // Function name
+ if (!EF->hasParam()) {
+ ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
+ EF->getName().c_str()));
+ } else {
+ llvm::Function *F = M->getFunction(EF->getName());
+ llvm::Function *HelperFunction;
+ const std::string HelperFunctionName(".helper_" + EF->getName());
+
+ slangAssert(F && "Function marked as exported disappeared in Bitcode");
+
+ // Create helper function
+ {
+ llvm::StructType *HelperFunctionParameterTy = nullptr;
+ std::vector<bool> isStructInput;
+
+ if (!F->getArgumentList().empty()) {
+ std::vector<llvm::Type*> HelperFunctionParameterTys;
+ for (llvm::Function::arg_iterator AI = F->arg_begin(),
+ AE = F->arg_end(); AI != AE; AI++) {
+ if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
+ HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
+ isStructInput.push_back(true);
+ } else {
+ HelperFunctionParameterTys.push_back(AI->getType());
+ isStructInput.push_back(false);
+ }
+ }
+ HelperFunctionParameterTy =
+ llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
+ }
+
+ if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
+ fprintf(stderr, "Failed to export function %s: parameter type "
+ "mismatch during creation of helper function.\n",
+ EF->getName().c_str());
+
+ const RSExportRecordType *Expected = EF->getParamPacketType();
+ if (Expected) {
+ fprintf(stderr, "Expected:\n");
+ Expected->getLLVMType()->dump();
+ }
+ if (HelperFunctionParameterTy) {
+ fprintf(stderr, "Got:\n");
+ HelperFunctionParameterTy->dump();
+ }
+ }
+
+ std::vector<llvm::Type*> Params;
+ if (HelperFunctionParameterTy) {
+ llvm::PointerType *HelperFunctionParameterTyP =
+ llvm::PointerType::getUnqual(HelperFunctionParameterTy);
+ Params.push_back(HelperFunctionParameterTyP);
+ }
+
+ llvm::FunctionType * HelperFunctionType =
+ llvm::FunctionType::get(F->getReturnType(),
+ Params,
+ /* IsVarArgs = */false);
+
+ HelperFunction =
+ llvm::Function::Create(HelperFunctionType,
+ llvm::GlobalValue::ExternalLinkage,
+ HelperFunctionName,
+ M);
+
+ HelperFunction->addFnAttr(llvm::Attribute::NoInline);
+ HelperFunction->setCallingConv(F->getCallingConv());
+
+ // Create helper function body
+ {
+ llvm::Argument *HelperFunctionParameter =
+ &(*HelperFunction->arg_begin());
+ llvm::BasicBlock *BB =
+ llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
+ llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
+ llvm::SmallVector<llvm::Value*, 6> Params;
+ llvm::Value *Idx[2];
+
+ Idx[0] =
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
+
+ // getelementptr and load instruction for all elements in
+ // parameter .p
+ for (size_t i = 0; i < EF->getNumParameters(); i++) {
+ // getelementptr
+ Idx[1] = llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(mLLVMContext), i);
+
+ llvm::Value *Ptr = NULL;
+
+ Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
+
+ // Load is only required for non-struct ptrs
+ if (isStructInput[i]) {
+ Params.push_back(Ptr);
+ } else {
+ llvm::Value *V = IB->CreateLoad(Ptr);
+ Params.push_back(V);
+ }
+ }
+
+ // Call and pass the all elements as parameter to F
+ llvm::CallInst *CI = IB->CreateCall(F, Params);
+
+ CI->setCallingConv(F->getCallingConv());
+
+ if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
+ IB->CreateRetVoid();
+ else
+ IB->CreateRet(CI);
+
+ delete IB;
+ }
+ }
+
+ ExportFuncInfo.push_back(
+ llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
+ }
+
+ mExportFuncMetadata->addOperand(
+ llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
+ ExportFuncInfo.clear();
+ }
+}
+
+void Backend::dumpExportForEachInfo(llvm::Module *M) {
+ if (mExportForEachNameMetadata == nullptr) {
+ mExportForEachNameMetadata =
+ M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
+ }
+ if (mExportForEachSignatureMetadata == nullptr) {
+ mExportForEachSignatureMetadata =
+ M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
+ }
+
+ llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
+ llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
+
+ for (RSContext::const_export_foreach_iterator
+ I = mContext->export_foreach_begin(),
+ E = mContext->export_foreach_end();
+ I != E;
+ I++) {
+ const RSExportForEach *EFE = *I;
+
+ ExportForEachName.push_back(
+ llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
+
+ mExportForEachNameMetadata->addOperand(
+ llvm::MDNode::get(mLLVMContext, ExportForEachName));
+ ExportForEachName.clear();
+
+ ExportForEachInfo.push_back(
+ llvm::MDString::get(mLLVMContext,
+ llvm::utostr_32(EFE->getSignatureMetadata())));
+
+ mExportForEachSignatureMetadata->addOperand(
+ llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
+ ExportForEachInfo.clear();
+ }
+}
+
+void Backend::dumpExportTypeInfo(llvm::Module *M) {
+ llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
+
+ for (RSContext::const_export_type_iterator
+ I = mContext->export_types_begin(),
+ E = mContext->export_types_end();
+ I != E;
+ I++) {
+ // First, dump type name list to export
+ const RSExportType *ET = I->getValue();
+
+ ExportTypeInfo.clear();
+ // Type name
+ ExportTypeInfo.push_back(
+ llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
+
+ if (ET->getClass() == RSExportType::ExportClassRecord) {
+ const RSExportRecordType *ERT =
+ static_cast<const RSExportRecordType*>(ET);
+
+ if (mExportTypeMetadata == nullptr)
+ mExportTypeMetadata =
+ M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
+
+ mExportTypeMetadata->addOperand(
+ llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
+
+ // Now, export struct field information to %[struct name]
+ std::string StructInfoMetadataName("%");
+ StructInfoMetadataName.append(ET->getName());
+ llvm::NamedMDNode *StructInfoMetadata =
+ M->getOrInsertNamedMetadata(StructInfoMetadataName);
+ llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
+
+ slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
+ "Metadata with same name was created before");
+ for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
+ FE = ERT->fields_end();
+ FI != FE;
+ FI++) {
+ const RSExportRecordType::Field *F = *FI;
+
+ // 1. field name
+ FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
+ F->getName().c_str()));
+
+ // 2. field type name
+ FieldInfo.push_back(
+ llvm::MDString::get(mLLVMContext,
+ F->getType()->getName().c_str()));
+
+ StructInfoMetadata->addOperand(
+ llvm::MDNode::get(mLLVMContext, FieldInfo));
+ FieldInfo.clear();
+ }
+ } // ET->getClass() == RSExportType::ExportClassRecord
+ }
+}
+
+void Backend::HandleTranslationUnitPost(llvm::Module *M) {
+
+ if (!mContext->is64Bit()) {
+ M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
+ }
+
+ if (!mContext->processExport()) {
+ return;
+ }
+
+ if (mContext->hasExportVar())
+ dumpExportVarInfo(M);
+
+ if (mContext->hasExportFunc())
+ dumpExportFunctionInfo(M);
+
+ if (mContext->hasExportForEach())
+ dumpExportForEachInfo(M);
+
+ if (mContext->hasExportType())
+ dumpExportTypeInfo(M);
+}
+
} // namespace slang
diff --git a/slang_backend.h b/slang_backend.h
index f7075dd..1a97bd6 100644
--- a/slang_backend.h
+++ b/slang_backend.h
@@ -25,6 +25,8 @@
#include "slang.h"
#include "slang_pragma_recorder.h"
+#include "slang_rs_check_ast.h"
+#include "slang_rs_object_ref_count.h"
#include "slang_version.h"
namespace llvm {
@@ -35,15 +37,22 @@
}
namespace clang {
+ class ASTConsumer;
+ class ASTContext;
class CodeGenOptions;
class CodeGenerator;
class DeclGroupRef;
+ class DiagnosticsEngine;
+ class FunctionDecl;
class TagDecl;
+ class TargetOptions;
class VarDecl;
}
namespace slang {
+class RSContext;
+
class Backend : public clang::ASTConsumer {
private:
const clang::TargetOptions &mTargetOpts;
@@ -74,6 +83,32 @@
void WrapBitcode(llvm::raw_string_ostream &Bitcode);
+ RSContext *mContext;
+
+ clang::SourceManager &mSourceMgr;
+
+ bool mAllowRSPrefix;
+
+ bool mIsFilterscript;
+
+ llvm::NamedMDNode *mExportVarMetadata;
+ llvm::NamedMDNode *mExportFuncMetadata;
+ llvm::NamedMDNode *mExportForEachNameMetadata;
+ llvm::NamedMDNode *mExportForEachSignatureMetadata;
+ llvm::NamedMDNode *mExportTypeMetadata;
+ llvm::NamedMDNode *mRSObjectSlotsMetadata;
+
+ RSObjectRefCount mRefCount;
+
+ RSCheckAST mASTChecker;
+
+ void AnnotateFunction(clang::FunctionDecl *FD);
+
+ void dumpExportVarInfo(llvm::Module *M);
+ void dumpExportFunctionInfo(llvm::Module *M);
+ void dumpExportForEachInfo(llvm::Module *M);
+ void dumpExportTypeInfo(llvm::Module *M);
+
protected:
llvm::LLVMContext &mLLVMContext;
clang::DiagnosticsEngine &mDiagEngine;
@@ -81,9 +116,9 @@
PragmaList *mPragmas;
- virtual unsigned int getTargetAPI() const {
- return SLANG_MAXIMUM_TARGET_API;
- }
+ unsigned int getTargetAPI() const { return mContext->getTargetAPI(); }
+
+ // TODO These are no longer virtual from base. Look into merging into caller.
// This handler will be invoked before Clang translates @Ctx to LLVM IR. This
// give you an opportunity to modified the IR in AST level (scope information,
@@ -91,47 +126,54 @@
// translate @Ctx into LLVM IR. One should not operate on @Ctx afterwards
// since the changes applied on that never reflects to the LLVM module used
// in the final codegen.
- virtual void HandleTranslationUnitPre(clang::ASTContext &Ctx) { }
+ void HandleTranslationUnitPre(clang::ASTContext &Ctx);
// This handler will be invoked when Clang have converted AST tree to LLVM IR.
// The @M contains the resulting LLVM IR tree. After the return from this
// method, slang will start doing optimization and code generation for @M.
- virtual void HandleTranslationUnitPost(llvm::Module *M) { }
+ void HandleTranslationUnitPost(llvm::Module *M);
public:
- Backend(clang::DiagnosticsEngine *DiagEngine,
- const clang::CodeGenOptions &CodeGenOpts,
- const clang::TargetOptions &TargetOpts,
- PragmaList *Pragmas,
- llvm::raw_ostream *OS,
- Slang::OutputType OT);
+ Backend(RSContext *Context,
+ clang::DiagnosticsEngine *DiagEngine,
+ const clang::CodeGenOptions &CodeGenOpts,
+ const clang::TargetOptions &TargetOpts,
+ PragmaList *Pragmas,
+ llvm::raw_ostream *OS,
+ Slang::OutputType OT,
+ clang::SourceManager &SourceMgr,
+ bool AllowRSPrefix,
+ bool IsFilterscript);
+
+ virtual ~Backend();
// Initialize - This is called to initialize the consumer, providing the
// ASTContext.
- virtual void Initialize(clang::ASTContext &Ctx);
+ void Initialize(clang::ASTContext &Ctx) override;
+
+ // TODO Clean up what should be private, protected
+ // TODO Also clean up the include files
// HandleTopLevelDecl - Handle the specified top-level declaration. This is
// called by the parser to process every top-level Decl*. Note that D can be
// the head of a chain of Decls (e.g. for `int a, b` the chain will have two
// elements). Use Decl::getNextDeclarator() to walk the chain.
- virtual bool HandleTopLevelDecl(clang::DeclGroupRef D);
+ bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
// HandleTranslationUnit - This method is called when the ASTs for entire
// translation unit have been parsed.
- virtual void HandleTranslationUnit(clang::ASTContext &Ctx);
+ void HandleTranslationUnit(clang::ASTContext &Ctx) override;
// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
// (e.g. struct, union, enum, class) is completed. This allows the client to
// hack on the type, which can occur at any point in the file (because these
// can be defined in declspecs).
- virtual void HandleTagDeclDefinition(clang::TagDecl *D);
+ void HandleTagDeclDefinition(clang::TagDecl *D) override;
// CompleteTentativeDefinition - Callback invoked at the end of a translation
// unit to notify the consumer that the given tentative definition should be
// completed.
- virtual void CompleteTentativeDefinition(clang::VarDecl *D);
-
- virtual ~Backend();
+ void CompleteTentativeDefinition(clang::VarDecl *D) override;
};
} // namespace slang
diff --git a/slang_rs.cpp b/slang_rs.cpp
deleted file mode 100644
index a388bfa..0000000
--- a/slang_rs.cpp
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright 2010-2012, 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.h"
-
-#include <cstring>
-#include <list>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "clang/Basic/SourceLocation.h"
-
-#include "clang/Frontend/FrontendDiagnostic.h"
-
-#include "clang/Sema/SemaDiagnostic.h"
-
-#include "llvm/Support/Path.h"
-
-#include "os_sep.h"
-#include "rs_cc_options.h"
-#include "slang_rs_backend.h"
-#include "slang_rs_context.h"
-#include "slang_rs_export_type.h"
-
-#include "slang_rs_reflection.h"
-#include "slang_rs_reflection_cpp.h"
-
-namespace slang {
-
-#define FS_SUFFIX "fs"
-
-#define RS_HEADER_SUFFIX "rsh"
-
-/* RS_HEADER_ENTRY(name) */
-#define ENUM_RS_HEADER() \
- RS_HEADER_ENTRY(rs_allocation_data) \
- RS_HEADER_ENTRY(rs_atomic) \
- RS_HEADER_ENTRY(rs_convert) \
- RS_HEADER_ENTRY(rs_core) \
- RS_HEADER_ENTRY(rs_debug) \
- RS_HEADER_ENTRY(rs_for_each) \
- RS_HEADER_ENTRY(rs_graphics) \
- RS_HEADER_ENTRY(rs_graphics_types) \
- RS_HEADER_ENTRY(rs_io) \
- RS_HEADER_ENTRY(rs_math) \
- RS_HEADER_ENTRY(rs_matrix) \
- RS_HEADER_ENTRY(rs_object_info) \
- RS_HEADER_ENTRY(rs_object_types) \
- RS_HEADER_ENTRY(rs_quaternion) \
- RS_HEADER_ENTRY(rs_time) \
- RS_HEADER_ENTRY(rs_value_types) \
- RS_HEADER_ENTRY(rs_vector_math) \
-
-// Returns true if \p Filename ends in ".fs".
-bool SlangRS::isFilterscript(const char *Filename) {
- const char *c = strrchr(Filename, '.');
- if (c && !strncmp(FS_SUFFIX, c + 1, strlen(FS_SUFFIX) + 1)) {
- return true;
- } else {
- return false;
- }
-}
-
-bool SlangRS::generateJavaBitcodeAccessor(const std::string &OutputPathBase,
- const std::string &PackageName,
- const std::string *LicenseNote) {
- RSSlangReflectUtils::BitCodeAccessorContext BCAccessorContext;
-
- BCAccessorContext.rsFileName = getInputFileName().c_str();
- BCAccessorContext.bc32FileName = getOutput32FileName().c_str();
- BCAccessorContext.bc64FileName = getOutputFileName().c_str();
- BCAccessorContext.reflectPath = OutputPathBase.c_str();
- BCAccessorContext.packageName = PackageName.c_str();
- BCAccessorContext.licenseNote = LicenseNote;
- BCAccessorContext.bcStorage = BCST_JAVA_CODE; // Must be BCST_JAVA_CODE
- BCAccessorContext.verbose = false;
-
- return RSSlangReflectUtils::GenerateJavaBitCodeAccessor(BCAccessorContext);
-}
-
-bool SlangRS::checkODR(const char *CurInputFile) {
- for (RSContext::ExportableList::iterator I = mRSContext->exportable_begin(),
- E = mRSContext->exportable_end();
- I != E;
- I++) {
- RSExportable *RSE = *I;
- if (RSE->getKind() != RSExportable::EX_TYPE)
- continue;
-
- RSExportType *ET = static_cast<RSExportType *>(RSE);
- if (ET->getClass() != RSExportType::ExportClassRecord)
- continue;
-
- RSExportRecordType *ERT = static_cast<RSExportRecordType *>(ET);
-
- // Artificial record types (create by us not by user in the source) always
- // conforms the ODR.
- if (ERT->isArtificial())
- continue;
-
- // Key to lookup ERT in ReflectedDefinitions
- llvm::StringRef RDKey(ERT->getName());
- ReflectedDefinitionListTy::const_iterator RD =
- ReflectedDefinitions.find(RDKey);
-
- if (RD != ReflectedDefinitions.end()) {
- const RSExportRecordType *Reflected = RD->getValue().first;
- // There's a record (struct) with the same name reflected before. Enforce
- // ODR checking - the Reflected must hold *exactly* the same "definition"
- // as the one defined previously. We say two record types A and B have the
- // same definition iff:
- //
- // struct A { struct B {
- // Type(a1) a1, Type(b1) b1,
- // Type(a2) a2, Type(b1) b2,
- // ... ...
- // Type(aN) aN Type(b3) b3,
- // }; }
- // Cond. #1. They have same number of fields, i.e., N = M;
- // Cond. #2. for (i := 1 to N)
- // Type(ai) = Type(bi) must hold;
- // Cond. #3. for (i := 1 to N)
- // Name(ai) = Name(bi) must hold;
- //
- // where,
- // Type(F) = the type of field F and
- // Name(F) = the field name.
-
- bool PassODR = false;
- // Cond. #1 and Cond. #2
- if (Reflected->equals(ERT)) {
- // Cond #3.
- RSExportRecordType::const_field_iterator AI = Reflected->fields_begin(),
- BI = ERT->fields_begin();
-
- for (unsigned i = 0, e = Reflected->getFields().size(); i != e; i++) {
- if ((*AI)->getName() != (*BI)->getName())
- break;
- AI++;
- BI++;
- }
- PassODR = (AI == (Reflected->fields_end()));
- }
-
- if (!PassODR) {
- getDiagnostics().Report(mDiagErrorODR) << Reflected->getName()
- << getInputFileName()
- << RD->getValue().second;
- return false;
- }
- } else {
- llvm::StringMapEntry<ReflectedDefinitionTy> *ME =
- llvm::StringMapEntry<ReflectedDefinitionTy>::Create(RDKey);
- ME->setValue(std::make_pair(ERT, CurInputFile));
-
- if (!ReflectedDefinitions.insert(ME))
- delete ME;
-
- // Take the ownership of ERT such that it won't be freed in ~RSContext().
- ERT->keep();
- }
- }
- return true;
-}
-
-void SlangRS::initDiagnostic() {
- clang::DiagnosticsEngine &DiagEngine = getDiagnostics();
- const auto Flavor = clang::diag::Flavor::WarningOrError;
-
- if (DiagEngine.setSeverityForGroup(Flavor, "implicit-function-declaration",
- clang::diag::Severity::Error)) {
- DiagEngine.Report(clang::diag::warn_unknown_diag_option)
- << /* clang::diag::Flavor::WarningOrError */ 0
- << "implicit-function-declaration";
- }
-
- DiagEngine.setSeverity(
- clang::diag::ext_typecheck_convert_discards_qualifiers,
- clang::diag::Severity::Error,
- clang::SourceLocation());
-
- mDiagErrorInvalidOutputDepParameter =
- DiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "invalid parameter for output dependencies files.");
-
- mDiagErrorODR =
- DiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "type '%0' in different translation unit (%1 v.s. %2) "
- "has incompatible type definition");
-
- mDiagErrorTargetAPIRange =
- DiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "target API level '%0' is out of range ('%1' - '%2')");
-}
-
-void SlangRS::initPreprocessor() {
- clang::Preprocessor &PP = getPreprocessor();
-
- std::stringstream RSH;
- RSH << PP.getPredefines();
- RSH << "#define RS_VERSION " << mTargetAPI << "\n";
- RSH << "#include \"rs_core." RS_HEADER_SUFFIX "\"\n";
- PP.setPredefines(RSH.str());
-}
-
-void SlangRS::initASTContext() {
- mRSContext = new RSContext(getPreprocessor(),
- getASTContext(),
- getTargetInfo(),
- &mPragmas,
- mTargetAPI,
- mVerbose);
-}
-
-clang::ASTConsumer
-*SlangRS::createBackend(const clang::CodeGenOptions& CodeGenOpts,
- llvm::raw_ostream *OS,
- Slang::OutputType OT) {
- return new RSBackend(mRSContext,
- &getDiagnostics(),
- CodeGenOpts,
- getTargetOptions(),
- &mPragmas,
- OS,
- OT,
- getSourceManager(),
- mAllowRSPrefix,
- mIsFilterscript);
-}
-
-bool SlangRS::IsRSHeaderFile(const char *File) {
-#define RS_HEADER_ENTRY(name) \
- if (::strcmp(File, #name "." RS_HEADER_SUFFIX) == 0) \
- return true;
-ENUM_RS_HEADER()
-#undef RS_HEADER_ENTRY
- return false;
-}
-
-bool SlangRS::IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
- const clang::SourceManager &SourceMgr) {
- clang::FullSourceLoc FSL(Loc, SourceMgr);
- clang::PresumedLoc PLoc = SourceMgr.getPresumedLoc(FSL);
-
- const char *Filename = PLoc.getFilename();
- if (!Filename) {
- return false;
- } else {
- return IsRSHeaderFile(llvm::sys::path::filename(Filename).data());
- }
-}
-
-SlangRS::SlangRS()
- : Slang(), mRSContext(nullptr), mAllowRSPrefix(false), mTargetAPI(0),
- mVerbose(false), mIsFilterscript(false) {
-}
-
-bool SlangRS::compile(
- const std::list<std::pair<const char*, const char*> > &IOFiles64,
- const std::list<std::pair<const char*, const char*> > &IOFiles32,
- const std::list<std::pair<const char*, const char*> > &DepFiles,
- const RSCCOptions &Opts) {
- if (IOFiles32.empty())
- return true;
-
- if (Opts.mEmitDependency && (DepFiles.size() != IOFiles32.size())) {
- getDiagnostics().Report(mDiagErrorInvalidOutputDepParameter);
- return false;
- }
-
- if (Opts.mEmit3264 && (IOFiles64.size() != IOFiles32.size())) {
- slangAssert(false && "Should have equal number of 32/64-bit files");
- return false;
- }
-
- std::string RealPackageName;
-
- const char *InputFile, *Output64File, *Output32File, *BCOutputFile,
- *DepOutputFile;
- std::list<std::pair<const char*, const char*> >::const_iterator
- IOFile64Iter = IOFiles64.begin(),
- IOFile32Iter = IOFiles32.begin(),
- DepFileIter = DepFiles.begin();
-
- setIncludePaths(Opts.mIncludePaths);
- setOutputType(Opts.mOutputType);
- if (Opts.mEmitDependency) {
- setAdditionalDepTargets(Opts.mAdditionalDepTargets);
- }
-
- setDebugMetadataEmission(Opts.mDebugEmission);
-
- setOptimizationLevel(Opts.mOptimizationLevel);
-
- mAllowRSPrefix = Opts.mAllowRSPrefix;
-
- mTargetAPI = Opts.mTargetAPI;
- if (mTargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
- (mTargetAPI < SLANG_MINIMUM_TARGET_API ||
- mTargetAPI > SLANG_MAXIMUM_TARGET_API)) {
- getDiagnostics().Report(mDiagErrorTargetAPIRange) << mTargetAPI
- << SLANG_MINIMUM_TARGET_API << SLANG_MAXIMUM_TARGET_API;
- return false;
- }
-
- mVerbose = Opts.mVerbose;
-
- // Skip generation of warnings a second time if we are doing more than just
- // a single pass over the input file.
- bool SuppressAllWarnings = (Opts.mOutputType != Slang::OT_Dependency);
-
- bool CompileSecondTimeFor64Bit = Opts.mEmit3264 && Opts.mBitWidth == 64;
-
- for (unsigned i = 0, e = IOFiles32.size(); i != e; i++) {
- InputFile = IOFile64Iter->first;
- Output64File = IOFile64Iter->second;
- Output32File = IOFile32Iter->second;
-
- // We suppress warnings (via reset) if we are doing a second compilation.
- reset(CompileSecondTimeFor64Bit);
-
- if (!setInputSource(InputFile))
- return false;
-
- if (!setOutput(Output64File))
- return false;
-
- setOutput32(Output32File);
-
- mIsFilterscript = isFilterscript(InputFile);
-
- if (Slang::compile() > 0)
- return false;
-
- if (!Opts.mJavaReflectionPackageName.empty()) {
- mRSContext->setReflectJavaPackageName(Opts.mJavaReflectionPackageName);
- }
- const std::string &RealPackageName =
- mRSContext->getReflectJavaPackageName();
-
- bool doReflection = true;
- if (Opts.mEmit3264 && (Opts.mBitWidth == 32)) {
- // Skip reflection on the 32-bit path if we are going to emit it on the
- // 64-bit path.
- doReflection = false;
- }
- if (Opts.mOutputType != Slang::OT_Dependency && doReflection) {
-
- if (Opts.mBitcodeStorage == BCST_CPP_CODE) {
- const std::string &outputFileName = (Opts.mBitWidth == 64) ?
- getOutputFileName() : getOutput32FileName();
- RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
- getInputFileName(), outputFileName);
- if (!R.reflect()) {
- return false;
- }
- } else {
- if (!Opts.mRSPackageName.empty()) {
- mRSContext->setRSPackageName(Opts.mRSPackageName);
- }
-
- RSReflectionJava R(mRSContext, &mGeneratedFileNames,
- Opts.mJavaReflectionPathBase, getInputFileName(),
- getOutputFileName(),
- Opts.mBitcodeStorage == BCST_JAVA_CODE);
- if (!R.reflect()) {
- // TODO Is this needed or will the error message have been printed
- // already? and why not for the C++ case?
- fprintf(stderr, "RSContext::reflectToJava : failed to do reflection "
- "(%s)\n",
- R.getLastError());
- return false;
- }
-
- for (std::vector<std::string>::const_iterator
- I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
- I != E;
- I++) {
- std::string ReflectedName = RSSlangReflectUtils::ComputePackagedPath(
- Opts.mJavaReflectionPathBase.c_str(),
- (RealPackageName + OS_PATH_SEPARATOR_STR + *I).c_str());
- appendGeneratedFileName(ReflectedName + ".java");
- }
-
- if ((Opts.mOutputType == Slang::OT_Bitcode) &&
- (Opts.mBitcodeStorage == BCST_JAVA_CODE) &&
- !generateJavaBitcodeAccessor(Opts.mJavaReflectionPathBase,
- RealPackageName.c_str(),
- mRSContext->getLicenseNote())) {
- return false;
- }
- }
- }
-
- if (Opts.mEmitDependency) {
- BCOutputFile = DepFileIter->first;
- DepOutputFile = DepFileIter->second;
-
- setDepTargetBC(BCOutputFile);
-
- if (!setDepOutput(DepOutputFile))
- return false;
-
- if (SuppressAllWarnings) {
- getDiagnostics().setSuppressAllDiagnostics(true);
- }
- if (generateDepFile() > 0)
- return false;
- if (SuppressAllWarnings) {
- getDiagnostics().setSuppressAllDiagnostics(false);
- }
-
- DepFileIter++;
- }
-
- if (!checkODR(InputFile))
- return false;
-
- IOFile64Iter++;
- IOFile32Iter++;
- }
-
- return true;
-}
-
-void SlangRS::reset(bool SuppressWarnings) {
- delete mRSContext;
- mRSContext = nullptr;
- mGeneratedFileNames.clear();
- Slang::reset(SuppressWarnings);
-}
-
-SlangRS::~SlangRS() {
- delete mRSContext;
- for (ReflectedDefinitionListTy::iterator I = ReflectedDefinitions.begin(),
- E = ReflectedDefinitions.end();
- I != E;
- I++) {
- delete I->getValue().first;
- }
-}
-
-} // namespace slang
diff --git a/slang_rs.h b/slang_rs.h
deleted file mode 100644
index 828b656..0000000
--- a/slang_rs.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2010-2012, 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_SLANG_RS_H_ // NOLINT
-#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_H_
-
-#include "slang.h"
-
-#include <list>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "llvm/ADT/StringMap.h"
-
-#include "slang_rs_reflect_utils.h"
-#include "slang_version.h"
-
-namespace slang {
- class RSCCOptions;
- class RSContext;
- class RSExportRecordType;
-
-class SlangRS : public Slang {
- private:
- // Context for Renderscript
- RSContext *mRSContext;
-
- bool mAllowRSPrefix;
-
- unsigned int mTargetAPI;
-
- bool mVerbose;
-
- bool mIsFilterscript;
-
- // Custom diagnostic identifiers
- unsigned mDiagErrorInvalidOutputDepParameter;
- unsigned mDiagErrorODR;
- unsigned mDiagErrorTargetAPIRange;
-
- // Collect generated filenames (without the .java) for dependency generation
- std::vector<std::string> mGeneratedFileNames;
-
- // FIXME: Should be std::list<RSExportable *> here. But currently we only
- // check ODR on record type.
- //
- // ReflectedDefinitions maps record type name to a pair:
- // <its RSExportRecordType instance,
- // the first file contains this record type definition>
- typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy;
- typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy;
- ReflectedDefinitionListTy ReflectedDefinitions;
-
- bool generateJavaBitcodeAccessor(const std::string &OutputPathBase,
- const std::string &PackageName,
- const std::string *LicenseNote);
-
- // CurInputFile is the pointer to a char array holding the input filename
- // and is valid before compile() ends.
- bool checkODR(const char *CurInputFile);
-
- // Returns true if this is a Filterscript file.
- static bool isFilterscript(const char *Filename);
-
- protected:
- virtual void initDiagnostic();
- virtual void initPreprocessor();
- virtual void initASTContext();
-
- virtual clang::ASTConsumer
- *createBackend(const clang::CodeGenOptions& CodeGenOpts,
- llvm::raw_ostream *OS,
- Slang::OutputType OT);
-
-
- public:
- static bool IsRSHeaderFile(const char *File);
- // FIXME: Determine whether a location is in RS header (i.e., one of the RS
- // built-in APIs) should only need its names (we need a "list" of RS
- // built-in APIs).
- static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
- const clang::SourceManager &SourceMgr);
-
- SlangRS();
-
- // Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
- // all given input files are successfully compiled without errors.
- //
- // @IOFiles - List of pairs of <input file path, output file path>.
- //
- // @DepFiles - List of pairs of <output dep. file path, dependent bitcode
- // target>. If @OutputDep is true, this parameter must be given
- // with the same number of pairs given in @IOFiles.
- //
- // @Opts - Selection of options defined from invoking llvm-rs-cc
- bool compile(const std::list<std::pair<const char*, const char*> > &IOFiles64,
- const std::list<std::pair<const char*, const char*> > &IOFiles32,
- const std::list<std::pair<const char*, const char*> > &DepFiles,
- const RSCCOptions &Opts);
-
- virtual void reset(bool SuppressWarnings = false);
-
- virtual ~SlangRS();
-
- virtual void makeModuleVisible(clang::Module *Mod,
- clang::Module::NameVisibilityKind Visibility,
- clang::SourceLocation ImportLoc,
- bool Complain = false) { }
-
- virtual clang::GlobalModuleIndex *loadGlobalModuleIndex(
- clang::SourceLocation TriggerLoc) { }
-
- virtual bool lookupMissingImports(llvm::StringRef Name,
- clang::SourceLocation TriggerLoc) { }
-};
-} // namespace slang
-
-#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_H_ NOLINT
diff --git a/slang_rs_backend.cpp b/slang_rs_backend.cpp
deleted file mode 100644
index eb59077..0000000
--- a/slang_rs_backend.cpp
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright 2010-2012, 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_backend.h"
-
-#include <string>
-#include <vector>
-
-#include "clang/AST/ASTContext.h"
-#include "clang/Frontend/CodeGenOptions.h"
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/StringExtras.h"
-
-#include "llvm/IR/Constant.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DerivedTypes.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Metadata.h"
-#include "llvm/IR/Module.h"
-
-#include "llvm/IR/DebugLoc.h"
-
-#include "slang_assert.h"
-#include "slang_rs.h"
-#include "slang_rs_context.h"
-#include "slang_rs_export_foreach.h"
-#include "slang_rs_export_func.h"
-#include "slang_rs_export_type.h"
-#include "slang_rs_export_var.h"
-#include "slang_rs_metadata.h"
-
-namespace slang {
-
-RSBackend::RSBackend(RSContext *Context,
- clang::DiagnosticsEngine *DiagEngine,
- const clang::CodeGenOptions &CodeGenOpts,
- const clang::TargetOptions &TargetOpts,
- PragmaList *Pragmas,
- llvm::raw_ostream *OS,
- Slang::OutputType OT,
- clang::SourceManager &SourceMgr,
- bool AllowRSPrefix,
- bool IsFilterscript)
- : Backend(DiagEngine, CodeGenOpts, TargetOpts, Pragmas, OS, OT),
- mContext(Context),
- mSourceMgr(SourceMgr),
- mAllowRSPrefix(AllowRSPrefix),
- mIsFilterscript(IsFilterscript),
- mExportVarMetadata(nullptr),
- mExportFuncMetadata(nullptr),
- mExportForEachNameMetadata(nullptr),
- mExportForEachSignatureMetadata(nullptr),
- mExportTypeMetadata(nullptr),
- mRSObjectSlotsMetadata(nullptr),
- mRefCount(mContext->getASTContext()),
- mASTChecker(Context, Context->getTargetAPI(), IsFilterscript) {
-}
-
-// 1) Add zero initialization of local RS object types
-void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
- if (FD &&
- FD->hasBody() &&
- !SlangRS::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr)) {
- mRefCount.Init();
- mRefCount.Visit(FD->getBody());
- }
-}
-
-bool RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
- // Disallow user-defined functions with prefix "rs"
- if (!mAllowRSPrefix) {
- // Iterate all function declarations in the program.
- for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
- I != E; I++) {
- clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
- if (FD == nullptr)
- continue;
- if (!FD->getName().startswith("rs")) // Check prefix
- continue;
- if (!SlangRS::IsLocInRSHeaderFile(FD->getLocation(), mSourceMgr))
- mContext->ReportError(FD->getLocation(),
- "invalid function name prefix, "
- "\"rs\" is reserved: '%0'")
- << FD->getName();
- }
- }
-
- // 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);
- if (FD && FD->isGlobal()) {
- // Check that we don't have any array parameters being misintrepeted as
- // kernel pointers due to the C type system's array to pointer decay.
- size_t numParams = FD->getNumParams();
- for (size_t i = 0; i < numParams; i++) {
- const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
- clang::QualType QT = PVD->getOriginalType();
- if (QT->isArrayType()) {
- mContext->ReportError(
- PVD->getTypeSpecStartLoc(),
- "exported function parameters may not have array type: %0")
- << QT;
- }
- }
- AnnotateFunction(FD);
- }
- }
-
- return Backend::HandleTopLevelDecl(D);
-}
-
-
-void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
- clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
-
- // If we have an invalid RS/FS AST, don't check further.
- if (!mASTChecker.Validate()) {
- return;
- }
-
- if (mIsFilterscript) {
- mContext->addPragma("rs_fp_relaxed", "");
- }
-
- int version = mContext->getVersion();
- if (version == 0) {
- // Not setting a version is an error
- mDiagEngine.Report(
- mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
- mDiagEngine.getCustomDiagID(
- clang::DiagnosticsEngine::Error,
- "missing pragma for version in source file"));
- } else {
- slangAssert(version == 1);
- }
-
- if (mContext->getReflectJavaPackageName().empty()) {
- mDiagEngine.Report(
- mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
- mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
- "missing \"#pragma rs "
- "java_package_name(com.foo.bar)\" "
- "in source file"));
- return;
- }
-
- // Create a static global destructor if necessary (to handle RS object
- // runtime cleanup).
- clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
- if (FD) {
- HandleTopLevelDecl(clang::DeclGroupRef(FD));
- }
-
- // Process any static function declarations
- for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
- E = TUDecl->decls_end(); I != E; I++) {
- if ((I->getKind() >= clang::Decl::firstFunction) &&
- (I->getKind() <= clang::Decl::lastFunction)) {
- clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
- if (FD && !FD->isGlobal()) {
- AnnotateFunction(FD);
- }
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-void RSBackend::dumpExportVarInfo(llvm::Module *M) {
- int slotCount = 0;
- if (mExportVarMetadata == nullptr)
- mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
-
- llvm::SmallVector<llvm::Metadata *, 2> ExportVarInfo;
-
- // We emit slot information (#rs_object_slots) for any reference counted
- // RS type or pointer (which can also be bound).
-
- for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
- E = mContext->export_vars_end();
- I != E;
- I++) {
- const RSExportVar *EV = *I;
- const RSExportType *ET = EV->getType();
- bool countsAsRSObject = false;
-
- // Variable name
- ExportVarInfo.push_back(
- llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
-
- // Type name
- switch (ET->getClass()) {
- case RSExportType::ExportClassPrimitive: {
- const RSExportPrimitiveType *PT =
- static_cast<const RSExportPrimitiveType*>(ET);
- ExportVarInfo.push_back(
- llvm::MDString::get(
- mLLVMContext, llvm::utostr_32(PT->getType())));
- if (PT->isRSObjectType()) {
- countsAsRSObject = true;
- }
- break;
- }
- case RSExportType::ExportClassPointer: {
- ExportVarInfo.push_back(
- llvm::MDString::get(
- mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
- ->getPointeeType()->getName()).c_str()));
- break;
- }
- case RSExportType::ExportClassMatrix: {
- ExportVarInfo.push_back(
- llvm::MDString::get(
- mLLVMContext, llvm::utostr_32(
- /* TODO Strange value. This pushes just a number, quite
- * different than the other cases. What is this used for?
- * These are the metadata values that some partner drivers
- * want to reference (for TBAA, etc.). We may want to look
- * at whether these provide any reasonable value (or have
- * distinct enough values to actually depend on).
- */
- DataTypeRSMatrix2x2 +
- static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
- break;
- }
- case RSExportType::ExportClassVector:
- case RSExportType::ExportClassConstantArray:
- case RSExportType::ExportClassRecord: {
- ExportVarInfo.push_back(
- llvm::MDString::get(mLLVMContext,
- EV->getType()->getName().c_str()));
- break;
- }
- }
-
- mExportVarMetadata->addOperand(
- llvm::MDNode::get(mLLVMContext, ExportVarInfo));
- ExportVarInfo.clear();
-
- if (mRSObjectSlotsMetadata == nullptr) {
- mRSObjectSlotsMetadata =
- M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
- }
-
- if (countsAsRSObject) {
- mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
- llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
- }
-
- slotCount++;
- }
-}
-
-void RSBackend::dumpExportFunctionInfo(llvm::Module *M) {
- if (mExportFuncMetadata == nullptr)
- mExportFuncMetadata =
- M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
-
- llvm::SmallVector<llvm::Metadata *, 1> ExportFuncInfo;
-
- for (RSContext::const_export_func_iterator
- I = mContext->export_funcs_begin(),
- E = mContext->export_funcs_end();
- I != E;
- I++) {
- const RSExportFunc *EF = *I;
-
- // Function name
- if (!EF->hasParam()) {
- ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
- EF->getName().c_str()));
- } else {
- llvm::Function *F = M->getFunction(EF->getName());
- llvm::Function *HelperFunction;
- const std::string HelperFunctionName(".helper_" + EF->getName());
-
- slangAssert(F && "Function marked as exported disappeared in Bitcode");
-
- // Create helper function
- {
- llvm::StructType *HelperFunctionParameterTy = nullptr;
- std::vector<bool> isStructInput;
-
- if (!F->getArgumentList().empty()) {
- std::vector<llvm::Type*> HelperFunctionParameterTys;
- for (llvm::Function::arg_iterator AI = F->arg_begin(),
- AE = F->arg_end(); AI != AE; AI++) {
- if (AI->getType()->isPointerTy() && AI->getType()->getPointerElementType()->isStructTy()) {
- HelperFunctionParameterTys.push_back(AI->getType()->getPointerElementType());
- isStructInput.push_back(true);
- } else {
- HelperFunctionParameterTys.push_back(AI->getType());
- isStructInput.push_back(false);
- }
- }
- HelperFunctionParameterTy =
- llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
- }
-
- if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
- fprintf(stderr, "Failed to export function %s: parameter type "
- "mismatch during creation of helper function.\n",
- EF->getName().c_str());
-
- const RSExportRecordType *Expected = EF->getParamPacketType();
- if (Expected) {
- fprintf(stderr, "Expected:\n");
- Expected->getLLVMType()->dump();
- }
- if (HelperFunctionParameterTy) {
- fprintf(stderr, "Got:\n");
- HelperFunctionParameterTy->dump();
- }
- }
-
- std::vector<llvm::Type*> Params;
- if (HelperFunctionParameterTy) {
- llvm::PointerType *HelperFunctionParameterTyP =
- llvm::PointerType::getUnqual(HelperFunctionParameterTy);
- Params.push_back(HelperFunctionParameterTyP);
- }
-
- llvm::FunctionType * HelperFunctionType =
- llvm::FunctionType::get(F->getReturnType(),
- Params,
- /* IsVarArgs = */false);
-
- HelperFunction =
- llvm::Function::Create(HelperFunctionType,
- llvm::GlobalValue::ExternalLinkage,
- HelperFunctionName,
- M);
-
- HelperFunction->addFnAttr(llvm::Attribute::NoInline);
- HelperFunction->setCallingConv(F->getCallingConv());
-
- // Create helper function body
- {
- llvm::Argument *HelperFunctionParameter =
- &(*HelperFunction->arg_begin());
- llvm::BasicBlock *BB =
- llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
- llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
- llvm::SmallVector<llvm::Value*, 6> Params;
- llvm::Value *Idx[2];
-
- Idx[0] =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
-
- // getelementptr and load instruction for all elements in
- // parameter .p
- for (size_t i = 0; i < EF->getNumParameters(); i++) {
- // getelementptr
- Idx[1] = llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(mLLVMContext), i);
-
- llvm::Value *Ptr = NULL;
-
- Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
-
- // Load is only required for non-struct ptrs
- if (isStructInput[i]) {
- Params.push_back(Ptr);
- } else {
- llvm::Value *V = IB->CreateLoad(Ptr);
- Params.push_back(V);
- }
- }
-
- // Call and pass the all elements as parameter to F
- llvm::CallInst *CI = IB->CreateCall(F, Params);
-
- CI->setCallingConv(F->getCallingConv());
-
- if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
- IB->CreateRetVoid();
- else
- IB->CreateRet(CI);
-
- delete IB;
- }
- }
-
- ExportFuncInfo.push_back(
- llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
- }
-
- mExportFuncMetadata->addOperand(
- llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
- ExportFuncInfo.clear();
- }
-}
-
-void RSBackend::dumpExportForEachInfo(llvm::Module *M) {
- if (mExportForEachNameMetadata == nullptr) {
- mExportForEachNameMetadata =
- M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
- }
- if (mExportForEachSignatureMetadata == nullptr) {
- mExportForEachSignatureMetadata =
- M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
- }
-
- llvm::SmallVector<llvm::Metadata *, 1> ExportForEachName;
- llvm::SmallVector<llvm::Metadata *, 1> ExportForEachInfo;
-
- for (RSContext::const_export_foreach_iterator
- I = mContext->export_foreach_begin(),
- E = mContext->export_foreach_end();
- I != E;
- I++) {
- const RSExportForEach *EFE = *I;
-
- ExportForEachName.push_back(
- llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
-
- mExportForEachNameMetadata->addOperand(
- llvm::MDNode::get(mLLVMContext, ExportForEachName));
- ExportForEachName.clear();
-
- ExportForEachInfo.push_back(
- llvm::MDString::get(mLLVMContext,
- llvm::utostr_32(EFE->getSignatureMetadata())));
-
- mExportForEachSignatureMetadata->addOperand(
- llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
- ExportForEachInfo.clear();
- }
-}
-
-void RSBackend::dumpExportTypeInfo(llvm::Module *M) {
- llvm::SmallVector<llvm::Metadata *, 1> ExportTypeInfo;
-
- for (RSContext::const_export_type_iterator
- I = mContext->export_types_begin(),
- E = mContext->export_types_end();
- I != E;
- I++) {
- // First, dump type name list to export
- const RSExportType *ET = I->getValue();
-
- ExportTypeInfo.clear();
- // Type name
- ExportTypeInfo.push_back(
- llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
-
- if (ET->getClass() == RSExportType::ExportClassRecord) {
- const RSExportRecordType *ERT =
- static_cast<const RSExportRecordType*>(ET);
-
- if (mExportTypeMetadata == nullptr)
- mExportTypeMetadata =
- M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
-
- mExportTypeMetadata->addOperand(
- llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
-
- // Now, export struct field information to %[struct name]
- std::string StructInfoMetadataName("%");
- StructInfoMetadataName.append(ET->getName());
- llvm::NamedMDNode *StructInfoMetadata =
- M->getOrInsertNamedMetadata(StructInfoMetadataName);
- llvm::SmallVector<llvm::Metadata *, 3> FieldInfo;
-
- slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
- "Metadata with same name was created before");
- for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
- FE = ERT->fields_end();
- FI != FE;
- FI++) {
- const RSExportRecordType::Field *F = *FI;
-
- // 1. field name
- FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
- F->getName().c_str()));
-
- // 2. field type name
- FieldInfo.push_back(
- llvm::MDString::get(mLLVMContext,
- F->getType()->getName().c_str()));
-
- StructInfoMetadata->addOperand(
- llvm::MDNode::get(mLLVMContext, FieldInfo));
- FieldInfo.clear();
- }
- } // ET->getClass() == RSExportType::ExportClassRecord
- }
-}
-
-void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
-
- if (!mContext->is64Bit()) {
- M->setDataLayout("e-p:32:32-i64:64-v128:64:128-n32-S64");
- }
-
- if (!mContext->processExport()) {
- return;
- }
-
-
-
- if (mContext->hasExportVar())
- dumpExportVarInfo(M);
-
- if (mContext->hasExportFunc())
- dumpExportFunctionInfo(M);
-
- if (mContext->hasExportForEach())
- dumpExportForEachInfo(M);
-
- if (mContext->hasExportType())
- dumpExportTypeInfo(M);
-}
-
-RSBackend::~RSBackend() {
-}
-
-} // namespace slang
diff --git a/slang_rs_backend.h b/slang_rs_backend.h
deleted file mode 100644
index a8fef0e..0000000
--- a/slang_rs_backend.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2010-2012, 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_SLANG_RS_BACKEND_H_ // NOLINT
-#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_BACKEND_H_
-
-#include "slang_backend.h"
-#include "slang_pragma_recorder.h"
-#include "slang_rs_check_ast.h"
-#include "slang_rs_object_ref_count.h"
-
-namespace llvm {
- class NamedMDNode;
-}
-
-namespace clang {
- class ASTConsumer;
- class DiagnosticsEngine;
- class TargetOptions;
- class CodeGenerator;
- class ASTContext;
- class DeclGroupRef;
- class FunctionDecl;
-}
-
-namespace slang {
-
-class RSContext;
-
-class RSBackend : public Backend {
- private:
- RSContext *mContext;
-
- clang::SourceManager &mSourceMgr;
-
- bool mAllowRSPrefix;
-
- bool mIsFilterscript;
-
- llvm::NamedMDNode *mExportVarMetadata;
- llvm::NamedMDNode *mExportFuncMetadata;
- llvm::NamedMDNode *mExportForEachNameMetadata;
- llvm::NamedMDNode *mExportForEachSignatureMetadata;
- llvm::NamedMDNode *mExportTypeMetadata;
- llvm::NamedMDNode *mRSObjectSlotsMetadata;
-
- RSObjectRefCount mRefCount;
-
- RSCheckAST mASTChecker;
-
- void AnnotateFunction(clang::FunctionDecl *FD);
-
- void dumpExportVarInfo(llvm::Module *M);
- void dumpExportFunctionInfo(llvm::Module *M);
- void dumpExportForEachInfo(llvm::Module *M);
- void dumpExportTypeInfo(llvm::Module *M);
-
- protected:
- virtual unsigned int getTargetAPI() const {
- return mContext->getTargetAPI();
- }
-
- virtual bool HandleTopLevelDecl(clang::DeclGroupRef D);
-
- virtual void HandleTranslationUnitPre(clang::ASTContext &C);
-
- virtual void HandleTranslationUnitPost(llvm::Module *M);
-
- public:
- RSBackend(RSContext *Context,
- clang::DiagnosticsEngine *DiagEngine,
- const clang::CodeGenOptions &CodeGenOpts,
- const clang::TargetOptions &TargetOpts,
- PragmaList *Pragmas,
- llvm::raw_ostream *OS,
- Slang::OutputType OT,
- clang::SourceManager &SourceMgr,
- bool AllowRSPrefix,
- bool IsFilterscript);
-
- virtual ~RSBackend();
-};
-} // namespace slang
-
-#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_BACKEND_H_ NOLINT
diff --git a/slang_rs_check_ast.cpp b/slang_rs_check_ast.cpp
index 848a176..a7c1025 100644
--- a/slang_rs_check_ast.cpp
+++ b/slang_rs_check_ast.cpp
@@ -17,7 +17,7 @@
#include "slang_rs_check_ast.h"
#include "slang_assert.h"
-#include "slang_rs.h"
+#include "slang.h"
#include "slang_rs_export_foreach.h"
#include "slang_rs_export_type.h"
@@ -218,7 +218,7 @@
void RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) {
- if (!SlangRS::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) {
+ if (!Slang::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) {
for (clang::DeclStmt::decl_iterator I = DS->decl_begin(),
E = DS->decl_end();
I != E;
@@ -259,7 +259,7 @@
// array accesses rely heavily on them and they are valid.
E = E->IgnoreImpCasts();
if (mIsFilterscript &&
- !SlangRS::IsLocInRSHeaderFile(E->getExprLoc(), mSM) &&
+ !Slang::IsLocInRSHeaderFile(E->getExprLoc(), mSM) &&
!RSExportType::ValidateType(Context, C, E->getType(), nullptr, E->getExprLoc(),
mTargetAPI, mIsFilterscript)) {
mValid = false;
@@ -276,7 +276,7 @@
DE = TUDecl->decls_end();
DI != DE;
DI++) {
- if (!SlangRS::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) {
+ if (!Slang::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) {
if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) {
ValidateVarDecl(VD);
} else if (clang::FunctionDecl *FD =
diff --git a/slang_rs_object_ref_count.cpp b/slang_rs_object_ref_count.cpp
index 05722a2..853afeb 100644
--- a/slang_rs_object_ref_count.cpp
+++ b/slang_rs_object_ref_count.cpp
@@ -26,7 +26,7 @@
#include "clang/AST/StmtVisitor.h"
#include "slang_assert.h"
-#include "slang_rs.h"
+#include "slang.h"
#include "slang_rs_ast_replace.h"
#include "slang_rs_export_type.h"