Merge "Add bitcast to invoke helper pass."
diff --git a/include/bcc/Compiler.h b/include/bcc/Compiler.h
index 865947e..2c0995b 100644
--- a/include/bcc/Compiler.h
+++ b/include/bcc/Compiler.h
@@ -84,6 +84,7 @@
bool addCustomPasses(Script &pScript, llvm::PassManager &pPM);
bool addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM);
bool addExpandForEachPass(Script &pScript, llvm::PassManager &pPM);
+ bool addInvariantPass(llvm::PassManager &pPM);
bool addInvokeHelperPass(llvm::PassManager &pPM);
public:
diff --git a/include/bcc/Renderscript/RSCompilerDriver.h b/include/bcc/Renderscript/RSCompilerDriver.h
index 5c0d6e8..b33ff2b 100644
--- a/include/bcc/Renderscript/RSCompilerDriver.h
+++ b/include/bcc/Renderscript/RSCompilerDriver.h
@@ -18,12 +18,12 @@
#define BCC_RS_COMPILER_DRIVER_H
#include "bcc/Compiler.h"
-#include "bcc/Renderscript/RSInfo.h"
#include "bcc/Renderscript/RSScript.h"
#include "bcinfo/MetadataExtractor.h"
#include <list>
+#include <string>
#include <vector>
namespace bcc {
@@ -61,18 +61,12 @@
bool setupConfig(const RSScript &pScript);
// Compiles the provided bitcode, placing the binary at pOutputPath.
- // - If saveInfoFile is true, it also stores the RSInfo data in a file with a path derived from
- // pOutputPath.
- // - pSourceHash and commandLineToEmbed are values to embed in the RSInfo for future cache
- // invalidation decision.
// - If pDumpIR is true, a ".ll" file will also be created.
Compiler::ErrorCode compileScript(RSScript& pScript, const char* pScriptName,
const char* pOutputPath,
- const char *pRuntimePath,
- const RSInfo::DependencyHashTy& pSourceHash,
- const char* commandLineToEmbed,
+ const char* pRuntimePath,
const char* pBuildChecksum,
- bool saveInfoFile, bool pDumpIR);
+ bool pDumpIR);
public:
RSCompilerDriver(bool pUseCompilerRT = true);
@@ -114,7 +108,7 @@
// SymbolResolverInterface is not a const-method.
// Returns true if script is successfully compiled.
bool build(BCCContext& pContext, const char* pCacheDir, const char* pResName,
- const char* pBitcode, size_t pBitcodeSize, const char* commandLine,
+ const char* pBitcode, size_t pBitcodeSize,
const char *pBuildChecksum, const char* pRuntimePath,
RSLinkRuntimeCallback pLinkRuntimeCallback = nullptr,
bool pDumpIR = false);
diff --git a/include/bcc/Renderscript/RSInfo.h b/include/bcc/Renderscript/RSInfo.h
deleted file mode 100644
index 31b8da5..0000000
--- a/include/bcc/Renderscript/RSInfo.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright 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 BCC_RS_INFO_H
-#define BCC_RS_INFO_H
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/Sha1Util.h"
-
-namespace llvm {
-class Module;
-}
-
-namespace bcc {
-
-// Forward declarations
-class FileBase;
-class InputFile;
-class OutputFile;
-class Source;
-class RSScript;
-
-typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
-
-namespace rsinfo {
-
-/* RS info file magic */
-#define RSINFO_MAGIC "\0rsinfo\n"
-
-/* RS info file version, encoded in 4 bytes of ASCII */
-#define RSINFO_VERSION "006\0"
-
-struct __attribute__((packed)) ListHeader {
- // The offset from the beginning of the file of data
- uint32_t offset;
- // Number of item in the list
- uint32_t count;
- // Size of each item
- uint8_t itemSize;
-};
-
-typedef uint32_t StringIndexTy;
-
-/* RS info file header */
-struct __attribute__((packed)) Header {
- // Magic versus version
- uint8_t magic[8];
- uint8_t version[4];
-
- uint8_t isThreadable;
- uint8_t hasDebugInformation;
-
- uint16_t headerSize;
-
- uint32_t strPoolSize;
-
- // The index in the pool of the SHA-1 checksum of the source file.
- // It has a fixed-length of SHA1_DIGEST_LENGTH (=20) bytes.
- StringIndexTy sourceSha1Idx;
- // The index in the pool of the command used to compile this source.
- StringIndexTy compileCommandLineIdx;
- // The index in the pool of the build fingerprint of Android when the source was compiled.
- StringIndexTy buildFingerprintIdx;
-
- struct ListHeader pragmaList;
- struct ListHeader objectSlotList;
- struct ListHeader exportVarNameList;
- struct ListHeader exportFuncNameList;
- struct ListHeader exportForeachFuncList;
-};
-
-// Use value -1 as an invalid string index marker. No need to declare with
-// 'static' modifier since 'const' variable has internal linkage by default.
-const StringIndexTy gInvalidStringIndex = static_cast<StringIndexTy>(-1);
-
-struct __attribute__((packed)) PragmaItem {
- // Pragma is a key-value pair.
- StringIndexTy key;
- StringIndexTy value;
-};
-
-struct __attribute__((packed)) ObjectSlotItem {
- uint32_t slot;
-};
-
-struct __attribute__((packed)) ExportVarNameItem {
- StringIndexTy name;
-};
-
-struct __attribute__((packed)) ExportFuncNameItem {
- StringIndexTy name;
-};
-
-struct __attribute__((packed)) ExportForeachFuncItem {
- StringIndexTy name;
- uint32_t signature;
-};
-
-// Return the human-readable name of the given rsinfo::*Item in the template
-// parameter. This is for debugging and error message.
-template<typename Item>
-inline const char *GetItemTypeName();
-
-template<>
-inline const char *GetItemTypeName<PragmaItem>()
-{ return "rs pragma"; }
-
-template<>
-inline const char *GetItemTypeName<ObjectSlotItem>()
-{ return "rs object slot"; }
-
-template<>
-inline const char *GetItemTypeName<ExportVarNameItem>()
-{ return "rs export var"; }
-
-template<>
-inline const char *GetItemTypeName<ExportFuncNameItem>()
-{ return "rs export func"; }
-
-template<>
-inline const char *GetItemTypeName<ExportForeachFuncItem>()
-{ return "rs export foreach"; }
-
-} // end namespace rsinfo
-
-class RSInfo {
-public:
- typedef const uint8_t* DependencyHashTy;
- typedef std::vector<std::pair<const char*, const char*> > PragmaListTy;
- typedef std::vector<uint32_t> ObjectSlotListTy;
- typedef std::vector<const char *> ExportVarNameListTy;
- typedef std::vector<const char *> ExportFuncNameListTy;
- typedef std::vector<std::pair<const char *,
- uint32_t> > ExportForeachFuncListTy;
-
-public:
- // Return the path of the RS info file corresponded to the given output
- // executable file.
- static std::string GetPath(const char *pFilename);
-
- // Check whether this info contains the same source hash, compile command line, and fingerprint.
- // If not, it's an indication we need to recompile.
- bool IsConsistent(const char* pInputFilename, const DependencyHashTy& sourceHash,
- const char* compileCommandLine, const char* buildFingerprint);
-
-private:
-
- rsinfo::Header mHeader;
-
- char *mStringPool;
-
- // Pointer to the hash of the souce file, somewhere in the string pool.
- DependencyHashTy mSourceHash;
- // Pointer to the command used to compile this source, somewhere in the string pool.
- const char* mCompileCommandLine;
- // Pointer to the build fingerprint of Android when the source was compiled, somewhere in the
- // string pool.
- const char* mBuildFingerprint;
-
- PragmaListTy mPragmas;
- ObjectSlotListTy mObjectSlots;
- ExportVarNameListTy mExportVarNames;
- ExportFuncNameListTy mExportFuncNames;
- ExportForeachFuncListTy mExportForeachFuncs;
-
- // Initialize an empty RSInfo with its size of string pool is pStringPoolSize.
- RSInfo(size_t pStringPoolSize);
-
- // layout() assigns value of offset in each ListHeader (i.e., it decides where
- // data should go in the file.) It also updates fields other than offset to
- // reflect the current RSInfo object states to mHeader.
- bool layout(off_t initial_offset);
-
-public:
- ~RSInfo();
-
- // Implemented in RSInfoExtractor.cpp.
- static RSInfo *ExtractFromSource(const Source &pSource,
- const DependencyHashTy &sourceHashToEmbed,
- const char* compileCommandLineToEmbed,
- const char* buildFingerprintToEmbed);
-
- // Implemented in RSInfoReader.cpp.
- static RSInfo *ReadFromFile(InputFile &pInput);
-
- // Implemneted in RSInfoWriter.cpp
- bool write(OutputFile &pOutput);
-
- void dump() const;
-
- // const getter
- inline bool isThreadable() const
- { return mHeader.isThreadable; }
- inline bool hasDebugInformation() const
- { return mHeader.hasDebugInformation; }
- inline const PragmaListTy &getPragmas() const
- { return mPragmas; }
- inline const ObjectSlotListTy &getObjectSlots() const
- { return mObjectSlots; }
- inline const ExportVarNameListTy &getExportVarNames() const
- { return mExportVarNames; }
- inline const ExportFuncNameListTy &getExportFuncNames() const
- { return mExportFuncNames; }
- inline const ExportForeachFuncListTy &getExportForeachFuncs() const
- { return mExportForeachFuncs; }
-
- const char *getStringFromPool(rsinfo::StringIndexTy pStrIdx) const;
- rsinfo::StringIndexTy getStringIdxInPool(const char *pStr) const;
-
- // setter
- inline void setThreadable(bool pThreadable = true)
- { mHeader.isThreadable = pThreadable; }
-
-public:
- enum FloatPrecision {
- FP_Full,
- FP_Relaxed,
- };
-
- // Return the minimal floating point precision required for the associated
- // script.
- FloatPrecision getFloatPrecisionRequirement() const;
-};
-
-// Returns the arguments concatenated into one string.
-std::string getCommandLine(int argc, const char* const* argv);
-
-} // end namespace bcc
-
-#endif // BCC_RS_INFO_H
diff --git a/include/bcc/Renderscript/RSScript.h b/include/bcc/Renderscript/RSScript.h
index cd4385f..8dc53b9 100644
--- a/include/bcc/Renderscript/RSScript.h
+++ b/include/bcc/Renderscript/RSScript.h
@@ -18,14 +18,20 @@
#define BCC_RS_SCRIPT_H
#include "bcc/Script.h"
-#include "bcc/Renderscript/RSInfo.h"
#include "bcc/Support/Sha1Util.h"
+namespace llvm {
+ class Module;
+}
+
namespace bcc {
class RSScript;
class Source;
+typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
+
+
class RSScript : public Script {
public:
// This is one-one mapping with the llvm::CodeGenOpt::Level in
@@ -39,8 +45,6 @@
};
private:
- const RSInfo *mInfo;
-
unsigned mCompilerVersion;
OptimizationLevel mOptimizationLevel;
@@ -58,18 +62,7 @@
RSScript(Source &pSource);
- virtual ~RSScript() {
- delete mInfo;
- }
-
- // Set the associated RSInfo of the script.
- void setInfo(const RSInfo *pInfo) {
- mInfo = pInfo;
- }
-
- const RSInfo *getInfo() const {
- return mInfo;
- }
+ virtual ~RSScript() { }
void setCompilerVersion(unsigned pCompilerVersion) {
mCompilerVersion = pCompilerVersion;
diff --git a/include/bcc/Renderscript/RSTransforms.h b/include/bcc/Renderscript/RSTransforms.h
index 647ac4d..c2ca439 100644
--- a/include/bcc/Renderscript/RSTransforms.h
+++ b/include/bcc/Renderscript/RSTransforms.h
@@ -28,6 +28,9 @@
createRSForEachExpandPass(bool pEnableStepOpt);
llvm::FunctionPass *
+createRSInvariantPass();
+
+llvm::FunctionPass *
createRSInvokeHelperPass();
llvm::ModulePass * createRSEmbedInfoPass();
diff --git a/lib/Core/Compiler.cpp b/lib/Core/Compiler.cpp
index 4f1dc8e..00c6fb2 100644
--- a/lib/Core/Compiler.cpp
+++ b/lib/Core/Compiler.cpp
@@ -374,6 +374,14 @@
return true;
}
+bool Compiler::addInvariantPass(llvm::PassManager &pPM) {
+ // Mark Loads from RsExpandKernelDriverInfo as "load.invariant".
+ // Should run after ExpandForEach and before inlining.
+ pPM.add(createRSInvariantPass());
+
+ return true;
+}
+
bool Compiler::addCustomPasses(Script &pScript, llvm::PassManager &pPM) {
if (!addInvokeHelperPass(pPM))
return false;
@@ -381,6 +389,9 @@
if (!addExpandForEachPass(pScript, pPM))
return false;
+ if (!addInvariantPass(pPM))
+ return false;
+
if (!addInternalizeSymbolsPass(pScript, pPM))
return false;
diff --git a/lib/Renderscript/Android.mk b/lib/Renderscript/Android.mk
index 8e692f9..bbb289d 100644
--- a/lib/Renderscript/Android.mk
+++ b/lib/Renderscript/Android.mk
@@ -25,10 +25,7 @@
RSCompilerDriver.cpp \
RSEmbedInfo.cpp \
RSForEachExpand.cpp \
- RSInfo.cpp \
- RSInfoExtractor.cpp \
- RSInfoReader.cpp \
- RSInfoWriter.cpp \
+ RSInvariant.cpp \
RSScript.cpp \
RSInvokeHelperPass.cpp \
RSIsThreadablePass.cpp \
diff --git a/lib/Renderscript/RSCompilerDriver.cpp b/lib/Renderscript/RSCompilerDriver.cpp
index 757d920..903e056 100644
--- a/lib/Renderscript/RSCompilerDriver.cpp
+++ b/lib/Renderscript/RSCompilerDriver.cpp
@@ -25,10 +25,10 @@
#include "bcinfo/BitcodeWrapper.h"
#include "bcc/Assert.h"
+#include "bcinfo/MetadataExtractor.h"
#include "bcc/BCCContext.h"
#include "bcc/Compiler.h"
#include "bcc/Config/Config.h"
-#include "bcc/Renderscript/RSInfo.h"
#include "bcc/Renderscript/RSScript.h"
#include "bcc/Renderscript/RSScriptGroupFusion.h"
#include "bcc/Support/CompilerConfig.h"
@@ -37,7 +37,6 @@
#include "bcc/Support/Log.h"
#include "bcc/Support/InputFile.h"
#include "bcc/Support/Initialization.h"
-#include "bcc/Support/Sha1Util.h"
#include "bcc/Support/OutputFile.h"
#include <sstream>
@@ -50,17 +49,6 @@
using namespace bcc;
-// Get the build fingerprint of the Android device we are running on.
-static std::string getBuildFingerPrint() {
-#ifdef HAVE_ANDROID_OS
- char fingerprint[PROPERTY_VALUE_MAX];
- property_get("ro.build.fingerprint", fingerprint, "");
- return fingerprint;
-#else
- return "HostBuild";
-#endif
-}
-
RSCompilerDriver::RSCompilerDriver(bool pUseCompilerRT) :
mConfig(nullptr), mCompiler(), mDebugContext(false),
mLinkRuntimeCallback(nullptr), mEnableGlobalMerge(true) {
@@ -105,9 +93,12 @@
}
#if defined(PROVIDE_ARM_CODEGEN)
- assert((pScript.getInfo() != nullptr) && "NULL RS info!");
- bool script_full_prec = (pScript.getInfo()->getFloatPrecisionRequirement() ==
- RSInfo::FP_Full);
+ bcinfo::MetadataExtractor me(&pScript.getSource().getModule());
+ if (!me.extract()) {
+ assert("Could not extract RS pragma metadata for module!");
+ }
+
+ bool script_full_prec = (me.getRSFloatPrecision() == bcinfo::RS_FP_Full);
if (mConfig->getFullPrecision() != script_full_prec) {
mConfig->setFullPrecision(script_full_prec);
changed = true;
@@ -120,37 +111,13 @@
Compiler::ErrorCode RSCompilerDriver::compileScript(RSScript& pScript, const char* pScriptName,
const char* pOutputPath,
const char* pRuntimePath,
- const RSInfo::DependencyHashTy& pSourceHash,
- const char* compileCommandLineToEmbed,
const char* pBuildChecksum,
- bool saveInfoFile, bool pDumpIR) {
- // android::StopWatch compile_time("bcc: RSCompilerDriver::compileScript time");
-
+ bool pDumpIR) {
// embed build checksum metadata into the source
if (pBuildChecksum != nullptr && strlen(pBuildChecksum) > 0) {
pScript.getSource().addBuildChecksumMetadata(pBuildChecksum);
}
- RSInfo *info = nullptr;
-
- //===--------------------------------------------------------------------===//
- // Extract RS-specific information from source bitcode.
- //===--------------------------------------------------------------------===//
- // RS info may contains configuration (such as #optimization_level) to the
- // compiler therefore it should be extracted before compilation.
- info = RSInfo::ExtractFromSource(pScript.getSource(), pSourceHash, compileCommandLineToEmbed,
- getBuildFingerPrint().c_str());
- if (info == nullptr) {
- return Compiler::kErrInvalidSource;
- }
-
- //===--------------------------------------------------------------------===//
- // Associate script with its info
- //===--------------------------------------------------------------------===//
- // This is required since RS compiler may need information in the info file
- // to do some transformation (e.g., expand foreach-able function.)
- pScript.setInfo(info);
-
//===--------------------------------------------------------------------===//
// Link RS script with Renderscript runtime.
//===--------------------------------------------------------------------===//
@@ -229,30 +196,6 @@
}
}
- if (saveInfoFile) {
- std::string info_path = RSInfo::GetPath(pOutputPath);
- OutputFile info_file(info_path.c_str(), FileBase::kTruncate);
-
- if (info_file.hasError()) {
- ALOGE("Failed to open the info file %s for write! (%s)",
- info_path.c_str(), info_file.getErrorMessage().c_str());
- return Compiler::kErrInvalidSource;
- }
-
- FileMutex<FileBase::kWriteLock> write_info_mutex(info_path.c_str());
- if (write_info_mutex.hasError() || !write_info_mutex.lock()) {
- ALOGE("Unable to acquire the lock for writing %s! (%s)",
- info_path.c_str(), write_info_mutex.getErrorMessage().c_str());
- return Compiler::kErrInvalidSource;
- }
-
- // Perform the write.
- if (!info->write(info_file)) {
- ALOGE("Failed to sync the RS info file %s!", info_path.c_str());
- return Compiler::kErrInvalidSource;
- }
- }
-
return Compiler::kSuccess;
}
@@ -261,7 +204,6 @@
const char *pResName,
const char *pBitcode,
size_t pBitcodeSize,
- const char *commandLine,
const char *pBuildChecksum,
const char *pRuntimePath,
RSLinkRuntimeCallback pLinkRuntimeCallback,
@@ -284,12 +226,6 @@
}
//===--------------------------------------------------------------------===//
- // Prepare dependency information.
- //===--------------------------------------------------------------------===//
- uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
- Sha1Util::GetSHA1DigestFromBuffer(bitcode_sha1, pBitcode, pBitcodeSize);
-
- //===--------------------------------------------------------------------===//
// Construct output path.
// {pCacheDir}/{pResName}.o
//===--------------------------------------------------------------------===//
@@ -324,8 +260,9 @@
//===--------------------------------------------------------------------===//
Compiler::ErrorCode status = compileScript(script, pResName,
output_path.c_str(),
- pRuntimePath, bitcode_sha1, commandLine,
- pBuildChecksum, true, pDumpIR);
+ pRuntimePath,
+ pBuildChecksum,
+ pDumpIR);
return status == Compiler::kSuccess;
}
@@ -397,17 +334,7 @@
Source::CreateFromModule(Context, pOutputFilepath, module, true));
RSScript script(*source);
- uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
- const char* compileCommandLineToEmbed = "";
const char* buildChecksum = "DummyChecksumForScriptGroup";
- const char* buildFingerprintToEmbed = "";
-
- RSInfo* info = RSInfo::ExtractFromSource(*source, bitcode_sha1,
- compileCommandLineToEmbed, buildFingerprintToEmbed);
- if (info == nullptr) {
- return false;
- }
- script.setInfo(info);
// Embed the info string directly in the ELF
script.setEmbedInfo(true);
@@ -427,8 +354,7 @@
}
compileScript(script, pOutputFilepath, output_path.c_str(), coreLibPath,
- bitcode_sha1, compileCommandLineToEmbed, buildChecksum,
- true, dumpIR);
+ buildChecksum, dumpIR);
return true;
}
@@ -437,28 +363,12 @@
const char *pBuildChecksum,
const char *pRuntimePath,
bool pDumpIR) {
- // For compat lib, we don't check the RS info file so we don't need the source hash,
- // compile command, and build fingerprint.
- // TODO We may want to make them optional or embed real values.
- uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH] = {0};
- const char* compileCommandLineToEmbed = "";
- const char* buildFingerprintToEmbed = "";
-
- RSInfo* info = RSInfo::ExtractFromSource(pScript.getSource(), bitcode_sha1,
- compileCommandLineToEmbed, buildFingerprintToEmbed);
- if (info == nullptr) {
- return false;
- }
- pScript.setInfo(info);
-
// Embed the info string directly in the ELF, since this path is for an
// offline (host) compilation.
pScript.setEmbedInfo(true);
Compiler::ErrorCode status = compileScript(pScript, pOut, pOut, pRuntimePath,
- bitcode_sha1,
- compileCommandLineToEmbed,
- pBuildChecksum, false, pDumpIR);
+ pBuildChecksum, pDumpIR);
if (status != Compiler::kSuccess) {
return false;
}
diff --git a/lib/Renderscript/RSForEachExpand.cpp b/lib/Renderscript/RSForEachExpand.cpp
index 865e695..2f036a6 100644
--- a/lib/Renderscript/RSForEachExpand.cpp
+++ b/lib/Renderscript/RSForEachExpand.cpp
@@ -245,7 +245,7 @@
llvm::StructType *RsLaunchDimensionsTy =
llvm::StructType::create(RsLaunchDimensionsTypes, "RsLaunchDimensions");
- /* Defined in frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h:
+ /* Defined as the beginning of RsExpandKernelDriverInfo in frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h:
*
* struct RsExpandKernelDriverInfoPfx {
* const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT];
@@ -269,6 +269,8 @@
* // So the compiler must assume there are an unknown number of fields of unknown type
* // beginning here.
* };
+ *
+ * The name "RsExpandKernelDriverInfoPfx" is known to RSInvariantPass (RSInvariant.cpp).
*/
llvm::SmallVector<llvm::Type*, RsExpandKernelDriverInfoPfxFieldCount> RsExpandKernelDriverInfoPfxTypes;
RsExpandKernelDriverInfoPfxTypes.push_back(Int8PtrArrayInputLimitTy); // const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT]
diff --git a/lib/Renderscript/RSInfo.cpp b/lib/Renderscript/RSInfo.cpp
deleted file mode 100644
index ba203ca..0000000
--- a/lib/Renderscript/RSInfo.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 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.
- */
-
-// #define LOG_NDEBUG 0
-#include "bcc/Renderscript/RSInfo.h"
-
-#if !defined(_WIN32) /* TODO create a HAVE_DLFCN_H */
-#include <dlfcn.h>
-#endif
-
-#include <cstring>
-#include <new>
-#include <string>
-
-#include "bcc/Support/FileBase.h"
-#include "bcc/Support/Log.h"
-
-#ifdef HAVE_ANDROID_OS
-#include <cutils/properties.h>
-#endif
-
-using namespace bcc;
-
-std::string RSInfo::GetPath(const char *pFilename) {
- std::string result(pFilename);
- result.append(".info");
- return result;
-}
-
-static std::string stringFromSourceHash(const RSInfo::DependencyHashTy& hash) {
- std::string s;
- s.reserve(SHA1_DIGEST_LENGTH + 1);
- for (int i = 0; i < SHA1_DIGEST_LENGTH; i++) {
- char buf[4];
- snprintf(buf, sizeof(buf), "%02x", hash[i]);
- s.append(buf);
- }
- return s;
-}
-
-std::string bcc::getCommandLine(int argc, const char* const* argv) {
- std::string s;
- for (int i = 0; i < argc; i++) {
- if (i > 0) {
- s += ' ';
- }
- s += argv[i];
- }
- return s;
-}
-
-bool RSInfo::IsConsistent(const char* pInputFilename, const DependencyHashTy& expectedSourceHash,
- const char* expectedCompileCommandLine,
- const char* expectedBuildFingerprint) {
- if (::memcmp(mSourceHash, expectedSourceHash, SHA1_DIGEST_LENGTH) != 0) {
- ALOGD("Cache %s is dirty due to the source it depends on has been changed:",
- pInputFilename);
- ALOGD("expected: %s", stringFromSourceHash(expectedSourceHash).c_str());
- ALOGD("cached : %s", stringFromSourceHash(mSourceHash).c_str());
- return false;
- }
- if (strcmp(expectedCompileCommandLine, mCompileCommandLine) != 0) {
- ALOGD("Cache %s is dirty because the command line used to compile it has changed:",
- pInputFilename);
- ALOGD("expected: %s", expectedCompileCommandLine);
- ALOGD("cached : %s", mCompileCommandLine);
- return false;
- }
- if (strcmp(expectedBuildFingerprint, mBuildFingerprint) != 0) {
- ALOGD("Cache %s is dirty because the build fingerprint has changed:", pInputFilename);
- ALOGD("expected: %s", expectedBuildFingerprint);
- ALOGD("cached : %s", mBuildFingerprint);
- return false;
- }
- return true;
-}
-
-RSInfo::RSInfo(size_t pStringPoolSize) : mStringPool(nullptr) {
- ::memset(&mHeader, 0, sizeof(mHeader));
-
- ::memcpy(mHeader.magic, RSINFO_MAGIC, sizeof(mHeader.magic));
- ::memcpy(mHeader.version, RSINFO_VERSION, sizeof(mHeader.version));
-
- mHeader.headerSize = sizeof(mHeader);
-
- mHeader.pragmaList.itemSize = sizeof(rsinfo::PragmaItem);
- mHeader.objectSlotList.itemSize = sizeof(rsinfo::ObjectSlotItem);
- mHeader.exportVarNameList.itemSize = sizeof(rsinfo::ExportVarNameItem);
- mHeader.exportFuncNameList.itemSize = sizeof(rsinfo::ExportFuncNameItem);
- mHeader.exportForeachFuncList.itemSize = sizeof(rsinfo::ExportForeachFuncItem);
-
- if (pStringPoolSize > 0) {
- mHeader.strPoolSize = pStringPoolSize;
- mStringPool = new (std::nothrow) char [ mHeader.strPoolSize ];
- if (mStringPool == nullptr) {
- ALOGE("Out of memory when allocate memory for string pool in RSInfo "
- "constructor (size: %u)!", mHeader.strPoolSize);
- }
- ::memset(mStringPool, 0, mHeader.strPoolSize);
- }
- mSourceHash = nullptr;
- mCompileCommandLine = nullptr;
- mBuildFingerprint = nullptr;
-}
-
-RSInfo::~RSInfo() {
- delete [] mStringPool;
-}
-
-bool RSInfo::layout(off_t initial_offset) {
- mHeader.pragmaList.offset = initial_offset +
- mHeader.headerSize +
- mHeader.strPoolSize;
- mHeader.pragmaList.count = mPragmas.size();
-
-#define AFTER(_list) ((_list).offset + (_list).itemSize * (_list).count)
- mHeader.objectSlotList.offset = AFTER(mHeader.pragmaList);
- mHeader.objectSlotList.count = mObjectSlots.size();
-
- mHeader.exportVarNameList.offset = AFTER(mHeader.objectSlotList);
- mHeader.exportVarNameList.count = mExportVarNames.size();
-
- mHeader.exportFuncNameList.offset = AFTER(mHeader.exportVarNameList);
- mHeader.exportFuncNameList.count = mExportFuncNames.size();
-
- mHeader.exportForeachFuncList.offset = AFTER(mHeader.exportFuncNameList);
- mHeader.exportForeachFuncList.count = mExportForeachFuncs.size();
-#undef AFTER
-
- return true;
-}
-
-void RSInfo::dump() const {
- // Hide the codes to save the code size when debugging is disabled.
-#if !LOG_NDEBUG
-
- // Dump header
- ALOGV("RSInfo Header:");
- ALOGV("\tIs threadable: %s", ((mHeader.isThreadable) ? "true" : "false"));
- ALOGV("\tHeader size: %u", mHeader.headerSize);
- ALOGV("\tString pool size: %u", mHeader.strPoolSize);
-
- if (mSourceHash == nullptr) {
- ALOGV("Source hash: NULL!");
- } else {
- ALOGV("Source hash: %s", stringFromSourceHash(mSourceHash).c_str());
- }
-
- ALOGV("Compile Command Line: %s", mCompileCommandLine ? mCompileCommandLine :
- "(NULL)");
- ALOGV("mBuildFingerprint: %s", mBuildFingerprint ? mBuildFingerprint :
- "(NULL)");
-
-#define DUMP_LIST_HEADER(_name, _header) do { \
- ALOGV(_name ":"); \
- ALOGV("\toffset: %u", (_header).offset); \
- ALOGV("\t# of item: %u", (_header).count); \
- ALOGV("\tsize of each item: %u", (_header).itemSize); \
-} while (false)
-
- DUMP_LIST_HEADER("Pragma list", mHeader.pragmaList);
- for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
- pragma_end = mPragmas.end(); pragma_iter != pragma_end; pragma_iter++) {
- ALOGV("\tkey: %s, value: %s", pragma_iter->first, pragma_iter->second);
- }
-
- DUMP_LIST_HEADER("RS object slots", mHeader.objectSlotList);
- for (ObjectSlotListTy::const_iterator slot_iter = mObjectSlots.begin(),
- slot_end = mObjectSlots.end(); slot_iter != slot_end; slot_iter++) {
- ALOGV("slot: %u", *slot_iter);
- }
-
- DUMP_LIST_HEADER("RS export variables", mHeader.exportVarNameList);
- for (ExportVarNameListTy::const_iterator var_iter = mExportVarNames.begin(),
- var_end = mExportVarNames.end(); var_iter != var_end; var_iter++) {
- ALOGV("name: %s", *var_iter);
- }
-
- DUMP_LIST_HEADER("RS export functions", mHeader.exportFuncNameList);
- for (ExportFuncNameListTy::const_iterator func_iter = mExportFuncNames.begin(),
- func_end = mExportFuncNames.end(); func_iter != func_end; func_iter++) {
- ALOGV("name: %s", *func_iter);
- }
-
- DUMP_LIST_HEADER("RS foreach list", mHeader.exportForeachFuncList);
- for (ExportForeachFuncListTy::const_iterator
- foreach_iter = mExportForeachFuncs.begin(),
- foreach_end = mExportForeachFuncs.end(); foreach_iter != foreach_end;
- foreach_iter++) {
- ALOGV("name: %s, signature: %05x", foreach_iter->first,
- foreach_iter->second);
- }
-#undef DUMP_LIST_HEADER
-
-#endif // LOG_NDEBUG
- return;
-}
-
-const char *RSInfo::getStringFromPool(rsinfo::StringIndexTy pStrIdx) const {
- // String pool uses direct indexing. Ensure that the pStrIdx is within the
- // range.
- if (pStrIdx >= mHeader.strPoolSize) {
- ALOGE("String index #%u is out of range in string pool (size: %u)!",
- pStrIdx, mHeader.strPoolSize);
- return nullptr;
- }
- return &mStringPool[ pStrIdx ];
-}
-
-rsinfo::StringIndexTy RSInfo::getStringIdxInPool(const char *pStr) const {
- // Assume we are on the flat memory architecture (i.e., the memory space is
- // continuous.)
- if ((mStringPool + mHeader.strPoolSize) < pStr) {
- ALOGE("String %s does not in the string pool!", pStr);
- return rsinfo::gInvalidStringIndex;
- }
- return (pStr - mStringPool);
-}
-
-RSInfo::FloatPrecision RSInfo::getFloatPrecisionRequirement() const {
- // Check to see if we have any FP precision-related pragmas.
- std::string relaxed_pragma("rs_fp_relaxed");
- std::string imprecise_pragma("rs_fp_imprecise");
- std::string full_pragma("rs_fp_full");
- bool relaxed_pragma_seen = false;
- bool full_pragma_seen = false;
-
- for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
- pragma_end = mPragmas.end(); pragma_iter != pragma_end;
- pragma_iter++) {
- const char *pragma_key = pragma_iter->first;
- if (!relaxed_pragma.compare(pragma_key)) {
- relaxed_pragma_seen = true;
- } else if (!imprecise_pragma.compare(pragma_key)) {
- ALOGW("rs_fp_imprecise is deprecated. Assuming rs_fp_relaxed instead.");
- relaxed_pragma_seen = true;
- } else if (!full_pragma.compare(pragma_key)) {
- full_pragma_seen = true;
- }
- }
-
- if (relaxed_pragma_seen && full_pragma_seen) {
- ALOGE("Full and relaxed precision specified at the same time!");
- }
- RSInfo::FloatPrecision result = relaxed_pragma_seen ? FP_Relaxed : FP_Full;
-
-#ifdef HAVE_ANDROID_OS
- // Provide an override for precsion via adb shell setprop
- // adb shell setprop debug.rs.precision rs_fp_full
- // adb shell setprop debug.rs.precision rs_fp_relaxed
- // adb shell setprop debug.rs.precision rs_fp_imprecise
- char precision_prop_buf[PROPERTY_VALUE_MAX];
- property_get("debug.rs.precision", precision_prop_buf, "");
-
- if (precision_prop_buf[0]) {
- if (!relaxed_pragma.compare(precision_prop_buf)) {
- ALOGI("Switching to RS FP relaxed mode via setprop");
- result = FP_Relaxed;
- } else if (!imprecise_pragma.compare(precision_prop_buf)) {
- ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was specified but is "
- "deprecated ");
- result = FP_Relaxed;
- } else if (!full_pragma.compare(precision_prop_buf)) {
- ALOGI("Switching to RS FP full mode via setprop");
- result = FP_Full;
- } else {
- ALOGE("Unrecognized debug.rs.precision %s", precision_prop_buf);
- }
- }
-#endif
-
- return result;
-}
diff --git a/lib/Renderscript/RSInfoExtractor.cpp b/lib/Renderscript/RSInfoExtractor.cpp
deleted file mode 100644
index 78d1b4c..0000000
--- a/lib/Renderscript/RSInfoExtractor.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright 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.
- */
-
-//===----------------------------------------------------------------------===//
-// This file implements RSInfo::ExtractFromSource()
-//===----------------------------------------------------------------------===//
-#include "bcc/Renderscript/RSInfo.h"
-
-#include <llvm/IR/Constants.h>
-#include <llvm/IR/Metadata.h>
-#include <llvm/IR/Module.h>
-
-#include "bcc/Source.h"
-#include "bcc/Support/Log.h"
-
-using namespace bcc;
-
-namespace {
-
-// Name of metadata node where pragma info resides (should be synced with
-// slang.cpp)
-const llvm::StringRef pragma_metadata_name("#pragma");
-
-/*
- * The following names should be synced with the one appeared in
- * slang_rs_metadata.h.
- */
-// Name of metadata node where exported variable names reside
-const llvm::StringRef export_var_metadata_name("#rs_export_var");
-
-// Name of metadata node where exported function names reside
-const llvm::StringRef export_func_metadata_name("#rs_export_func");
-
-// Name of metadata node where exported ForEach name information resides
-const llvm::StringRef export_foreach_name_metadata_name("#rs_export_foreach_name");
-
-// Name of metadata node where exported ForEach signature information resides
-const llvm::StringRef export_foreach_metadata_name("#rs_export_foreach");
-
-// Name of metadata node where RS object slot info resides (should be
-const llvm::StringRef object_slot_metadata_name("#rs_object_slots");
-
-inline llvm::StringRef getStringFromOperand(const llvm::Value *pString) {
- if ((pString != nullptr) && (pString->getValueID() == llvm::Value::MDStringVal)) {
- return static_cast<const llvm::MDString *>(pString)->getString();
- }
- return llvm::StringRef();
-}
-
-template<size_t NumOperands>
-inline size_t getMetadataStringLength(const llvm::NamedMDNode *pMetadata) {
- if (pMetadata == nullptr) {
- return 0;
- }
-
- size_t string_size = 0;
- for (unsigned i = 0, e = pMetadata->getNumOperands(); i < e; i++) {
- llvm::MDNode *node = pMetadata->getOperand(i);
- if ((node != nullptr) && (node->getNumOperands() >= NumOperands)) {
- // Compiler try its best to unroll this loop since NumOperands is a
- // template parameter (therefore the number of iteration can be determined
- // at compile-time and it's usually small.)
- for (unsigned j = 0; j < NumOperands; j++) {
- llvm::StringRef s = getStringFromOperand(node->getOperand(j));
- if (s.size() > 0) {
- // +1 is for the null-terminator at the end of string.
- string_size += (s.size() + 1);
- }
- }
- }
- }
-
- return string_size;
-}
-
-// Write a string pString to the string pool pStringPool at offset pWriteStart.
-// Return the pointer the pString resides within the string pool.
-// Updates pWriteStart to the next available spot.
-const char *writeString(const llvm::StringRef &pString, char *pStringPool,
- off_t *pWriteStart) {
- if (pString.empty()) {
- return pStringPool;
- }
-
- char *pStringWriteStart = pStringPool + *pWriteStart;
- // Copy the string.
- ::memcpy(pStringWriteStart, pString.data(), pString.size());
- // Write null-terminator at the end of the string.
- pStringWriteStart[ pString.size() ] = '\0';
- // Update pWriteStart.
- *pWriteStart += (pString.size() + 1);
-
- return pStringWriteStart;
-}
-
-} // end anonymous namespace
-
-RSInfo* RSInfo::ExtractFromSource(const Source& pSource, const DependencyHashTy& sourceHashToEmbed,
- const char* compileCommandLineToEmbed,
- const char* buildFingerprintToEmbed) {
- const llvm::Module &module = pSource.getModule();
- const char *module_name = module.getModuleIdentifier().c_str();
-
- const llvm::NamedMDNode *pragma =
- module.getNamedMetadata(pragma_metadata_name);
- const llvm::NamedMDNode *export_var =
- module.getNamedMetadata(export_var_metadata_name);
- const llvm::NamedMDNode *export_func =
- module.getNamedMetadata(export_func_metadata_name);
- const llvm::NamedMDNode *export_foreach_name =
- module.getNamedMetadata(export_foreach_name_metadata_name);
- const llvm::NamedMDNode *export_foreach_signature =
- module.getNamedMetadata(export_foreach_metadata_name);
- const llvm::NamedMDNode *object_slots =
- module.getNamedMetadata(object_slot_metadata_name);
-
- // Always write a byte 0x0 at the beginning of the string pool.
- size_t string_pool_size = 1;
- off_t cur_string_pool_offset = 0;
-
- RSInfo *result = nullptr;
-
- // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
- // section for ForEach. We generate a full signature for a "root" function.
- if ((export_foreach_name == nullptr) || (export_foreach_signature == nullptr)) {
- export_foreach_name = nullptr;
- export_foreach_signature = nullptr;
- string_pool_size += 5; // insert "root\0" for #rs_export_foreach_name
- }
-
- string_pool_size += getMetadataStringLength<2>(pragma);
- string_pool_size += getMetadataStringLength<1>(export_var);
- string_pool_size += getMetadataStringLength<1>(export_func);
- string_pool_size += getMetadataStringLength<1>(export_foreach_name);
-
- // Reserve the space for the source hash, command line, and fingerprint
- string_pool_size += SHA1_DIGEST_LENGTH;
- string_pool_size += strlen(compileCommandLineToEmbed) + 1;
- string_pool_size += strlen(buildFingerprintToEmbed) + 1;
-
- // Allocate result object
- result = new (std::nothrow) RSInfo(string_pool_size);
- if (result == nullptr) {
- ALOGE("Out of memory when create RSInfo object for %s!", module_name);
- goto bail;
- }
-
- // Check string pool.
- if (result->mStringPool == nullptr) {
- ALOGE("Out of memory when allocate string pool in RSInfo object for %s!",
- module_name);
- goto bail;
- }
-
- // First byte of string pool should be an empty string
- result->mStringPool[ cur_string_pool_offset++ ] = '\0';
-
- // Populate all the strings and data.
-#define FOR_EACH_NODE_IN(_metadata, _node) \
- for (unsigned i = 0, e = (_metadata)->getNumOperands(); i != e; i++) \
- if (((_node) = (_metadata)->getOperand(i)) != nullptr)
- //===--------------------------------------------------------------------===//
- // #pragma
- //===--------------------------------------------------------------------===//
- // Pragma is actually a key-value pair. The value can be an empty string while
- // the key cannot.
- if (pragma != nullptr) {
- llvm::MDNode *node;
- FOR_EACH_NODE_IN(pragma, node) {
- llvm::StringRef key = getStringFromOperand(node->getOperand(0));
- llvm::StringRef val = getStringFromOperand(node->getOperand(1));
- if (key.empty()) {
- ALOGW("%s contains pragma metadata with empty key (skip)!",
- module_name);
- } else {
- result->mPragmas.push_back(std::make_pair(
- writeString(key, result->mStringPool, &cur_string_pool_offset),
- writeString(val, result->mStringPool, &cur_string_pool_offset)));
- } // key.empty()
- } // FOR_EACH_NODE_IN
- } // pragma != nullptr
-
- //===--------------------------------------------------------------------===//
- // #rs_export_var
- //===--------------------------------------------------------------------===//
- if (export_var != nullptr) {
- llvm::MDNode *node;
- FOR_EACH_NODE_IN(export_var, node) {
- llvm::StringRef name = getStringFromOperand(node->getOperand(0));
- if (name.empty()) {
- ALOGW("%s contains empty entry in #rs_export_var metadata (skip)!",
- module_name);
- } else {
- result->mExportVarNames.push_back(
- writeString(name, result->mStringPool, &cur_string_pool_offset));
- }
- }
- }
-
- //===--------------------------------------------------------------------===//
- // #rs_export_func
- //===--------------------------------------------------------------------===//
- if (export_func != nullptr) {
- llvm::MDNode *node;
- FOR_EACH_NODE_IN(export_func, node) {
- llvm::StringRef name = getStringFromOperand(node->getOperand(0));
- if (name.empty()) {
- ALOGW("%s contains empty entry in #rs_export_func metadata (skip)!",
- module_name);
- } else {
- result->mExportFuncNames.push_back(
- writeString(name, result->mStringPool, &cur_string_pool_offset));
- }
- }
- }
-
- //===--------------------------------------------------------------------===//
- // #rs_export_foreach and #rs_export_foreach_name
- //===--------------------------------------------------------------------===//
- // It's a little bit complicated to deal with #rs_export_foreach (the
- // signature of foreach-able function) and #rs_export_foreach_name (the name
- // of function which is foreach-able). We have to maintain a legacy case:
- //
- // In pre-ICS bitcode, forEach feature only supports non-graphic root()
- // function and only one signature corresponded to that non-graphic root()
- // was written to the #rs_export_foreach metadata section. There's no
- // #rs_export_foreach_name metadata section.
- //
- // Currently, not only non-graphic root() is supported but also other
- // functions that are exportable. Therefore, a new metadata section
- // #rs_export_foreach_name is added to specify which functions are
- // for-eachable. In this case, #rs_export_foreach (the function name) and
- // #rs_export_foreach metadata (the signature) is one-to-one mapping among
- // their entries.
- if ((export_foreach_name != nullptr) && (export_foreach_signature != nullptr)) {
- unsigned num_foreach_function;
-
- // Should be one-to-one mapping.
- if (export_foreach_name->getNumOperands() !=
- export_foreach_signature->getNumOperands()) {
- ALOGE("Mismatch number of foreach-able function names (%u) in "
- "#rs_export_foreach_name and number of signatures (%u) "
- "in %s!", export_foreach_name->getNumOperands(),
- export_foreach_signature->getNumOperands(), module_name);
- goto bail;
- }
-
- num_foreach_function = export_foreach_name->getNumOperands();
- for (unsigned i = 0; i < num_foreach_function; i++) {
- llvm::MDNode *name_node = export_foreach_name->getOperand(i);
- llvm::MDNode *signature_node = export_foreach_signature->getOperand(i);
-
- llvm::StringRef name, signature_string;
- if (name_node != nullptr) {
- name = getStringFromOperand(name_node->getOperand(0));
- }
- if (signature_node != nullptr) {
- signature_string = getStringFromOperand(signature_node->getOperand(0));
- }
-
- if (!name.empty() && !signature_string.empty()) {
- // Both name_node and signature_node are not nullptr nodes.
- uint32_t signature;
- if (signature_string.getAsInteger(10, signature)) {
- ALOGE("Non-integer signature value '%s' for function %s found in %s!",
- signature_string.str().c_str(), name.str().c_str(), module_name);
- goto bail;
- }
- result->mExportForeachFuncs.push_back(std::make_pair(
- writeString(name, result->mStringPool, &cur_string_pool_offset),
- signature));
- } else {
- // One or both of the name and signature value are empty. It's safe only
- // if both of them are empty.
- if (name.empty() && signature_string.empty()) {
- ALOGW("Entries #%u at #rs_export_foreach_name and #rs_export_foreach"
- " are both nullptr in %s! (skip)", i, module_name);
- continue;
- } else {
- ALOGE("Entries #%u at %s is NULL in %s! (skip)", i,
- (name.empty() ? "#rs_export_foreach_name" :
- "#rs_export_foreach"), module_name);
- goto bail;
- }
- }
- } // end for
- } else {
- // To handle the legacy case, we generate a full signature for a "root"
- // function which means that we need to set the bottom 5 bits (0x1f) in the
- // mask.
- result->mExportForeachFuncs.push_back(std::make_pair(
- writeString(llvm::StringRef("root"), result->mStringPool,
- &cur_string_pool_offset), 0x1f));
- }
-
- //===--------------------------------------------------------------------===//
- // #rs_object_slots
- //===--------------------------------------------------------------------===//
- if (object_slots != nullptr) {
- llvm::MDNode *node;
- for (unsigned int i = 0; i <= export_var->getNumOperands(); i++) {
- result->mObjectSlots.push_back(0);
- }
- FOR_EACH_NODE_IN(object_slots, node) {
- llvm::StringRef val = getStringFromOperand(node->getOperand(0));
- if (val.empty()) {
- ALOGW("%s contains empty entry in #rs_object_slots (skip)!",
- module.getModuleIdentifier().c_str());
- } else {
- uint32_t slot;
- if (val.getAsInteger(10, slot)) {
- ALOGE("Non-integer object slot value '%s' in %s!", val.str().c_str(),
- module.getModuleIdentifier().c_str());
- goto bail;
- } else {
- result->mObjectSlots[slot] = 1;
- }
- }
- }
- }
-#undef FOR_EACH_NODE_IN
-
- //===------------------------------------------------------------------===//
- // Record information used to invalidate the cache
- //===------------------------------------------------------------------===//
- {
- // Store the SHA-1 in the string pool but without a null-terminator.
- result->mHeader.sourceSha1Idx = cur_string_pool_offset;
- uint8_t* sha1 = reinterpret_cast<uint8_t*>(result->mStringPool + cur_string_pool_offset);
- ::memcpy(sha1, sourceHashToEmbed, SHA1_DIGEST_LENGTH);
- // Update the string pool pointer.
- cur_string_pool_offset += SHA1_DIGEST_LENGTH;
- result->mSourceHash = sha1;
-
- result->mHeader.compileCommandLineIdx = cur_string_pool_offset;
- result->mCompileCommandLine = writeString(compileCommandLineToEmbed, result->mStringPool,
- &cur_string_pool_offset);
-
- result->mHeader.buildFingerprintIdx = cur_string_pool_offset;
- result->mBuildFingerprint = writeString(buildFingerprintToEmbed, result->mStringPool,
- &cur_string_pool_offset);
- }
-
- //===--------------------------------------------------------------------===//
- // Determine whether the bitcode contains debug information
- //===--------------------------------------------------------------------===//
- // The root context of the debug information in the bitcode is put under
- // the metadata named "llvm.dbg.cu".
- result->mHeader.hasDebugInformation =
- static_cast<uint8_t>(module.getNamedMetadata("llvm.dbg.cu") != nullptr);
-
- assert(((size_t)cur_string_pool_offset == string_pool_size) &&
- "Unexpected string pool size!");
-
- return result;
-
-bail:
- delete result;
- return nullptr;
-}
diff --git a/lib/Renderscript/RSInfoReader.cpp b/lib/Renderscript/RSInfoReader.cpp
deleted file mode 100644
index 611742c..0000000
--- a/lib/Renderscript/RSInfoReader.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright 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.
- */
-
-//===----------------------------------------------------------------------===//
-// This file implements RSInfo::ReadFromFile()
-//===----------------------------------------------------------------------===//
-
-#include "bcc/Renderscript/RSInfo.h"
-
-#include <new>
-
-#include <utils/FileMap.h>
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/InputFile.h"
-
-using namespace bcc;
-
-namespace {
-
-template<typename ItemType, typename ItemContainer>
-inline bool helper_read_list_item(const ItemType &pItem,
- const RSInfo &pInfo,
- ItemContainer &pResult);
-
-// Process PragmaItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
- const rsinfo::PragmaItem &pItem,
- const RSInfo &pInfo,
- RSInfo::PragmaListTy &pResult)
-{
- const char *key = pInfo.getStringFromPool(pItem.key);
- const char *value =pInfo.getStringFromPool(pItem.value);
-
- if (key == nullptr) {
- ALOGE("Invalid string index %d for key in RS pragma list.", pItem.key);
- return false;
- }
-
- if (value == nullptr) {
- ALOGE("Invalid string index %d for value in RS pragma list.", pItem.value);
- return false;
- }
-
- pResult.push_back(std::make_pair(key, value));
- return true;
-}
-
-// Procee ObjectSlotItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
- const rsinfo::ObjectSlotItem &pItem,
- const RSInfo &pInfo,
- RSInfo::ObjectSlotListTy &pResult)
-{
- pResult.push_back(pItem.slot);
- return true;
-}
-
-// Procee ExportVarNameItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
- const rsinfo::ExportVarNameItem &pItem,
- const RSInfo &pInfo,
- RSInfo::ExportVarNameListTy &pResult)
-{
- const char *name = pInfo.getStringFromPool(pItem.name);
-
- if (name == nullptr) {
- ALOGE("Invalid string index %d for name in RS export vars.", pItem.name);
- return false;
- }
-
- pResult.push_back(name);
- return true;
-}
-
-// Procee ExportFuncNameItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ExportFuncNameItem, RSInfo::ExportFuncNameListTy>(
- const rsinfo::ExportFuncNameItem &pItem,
- const RSInfo &pInfo,
- RSInfo::ExportFuncNameListTy &pResult)
-{
- const char *name = pInfo.getStringFromPool(pItem.name);
-
- if (name == nullptr) {
- ALOGE("Invalid string index %d for name in RS export funcs.", pItem.name);
- return false;
- }
-
- pResult.push_back(name);
- return true;
-}
-
-// Procee ExportForeachFuncItem in the file
-template<> inline bool
-helper_read_list_item<rsinfo::ExportForeachFuncItem, RSInfo::ExportForeachFuncListTy>(
- const rsinfo::ExportForeachFuncItem &pItem,
- const RSInfo &pInfo,
- RSInfo::ExportForeachFuncListTy &pResult)
-{
- const char *name = pInfo.getStringFromPool(pItem.name);
-
- if (name == nullptr) {
- ALOGE("Invalid string index %d for name in RS export foreachs.", pItem.name);
- return false;
- }
-
- pResult.push_back(std::make_pair(name, pItem.signature));
- return true;
-}
-
-template<typename ItemType, typename ItemContainer>
-inline bool helper_read_list(const uint8_t *pData,
- const RSInfo &pInfo,
- const rsinfo::ListHeader &pHeader,
- ItemContainer &pResult) {
- const ItemType *item;
-
- // Out-of-range exception has been checked.
- for (uint32_t i = 0; i < pHeader.count; i++) {
- item = reinterpret_cast<const ItemType *>(pData +
- pHeader.offset +
- i * pHeader.itemSize);
- if (!helper_read_list_item<ItemType, ItemContainer>(*item, pInfo, pResult)) {
- return false;
- }
- }
- return true;
-}
-
-} // end anonymous namespace
-
-RSInfo *RSInfo::ReadFromFile(InputFile &pInput) {
- android::FileMap *map = nullptr;
- RSInfo *result = nullptr;
- const uint8_t *data;
- const rsinfo::Header *header;
- size_t filesize;
- const char *input_filename = pInput.getName().c_str();
- const off_t cur_input_offset = pInput.tell();
-
- if (pInput.hasError()) {
- ALOGE("Invalid RS info file %s! (%s)", input_filename,
- pInput.getErrorMessage().c_str());
- goto bail;
- }
-
- filesize = pInput.getSize();
- if (pInput.hasError()) {
- ALOGE("Failed to get the size of RS info file %s! (%s)",
- input_filename, pInput.getErrorMessage().c_str());
- goto bail;
- }
-
- // Create memory map for the file.
- map = pInput.createMap(/* pOffset */cur_input_offset,
- /* pLength */filesize - cur_input_offset);
- if (map == nullptr) {
- ALOGE("Failed to map RS info file %s to the memory! (%s)",
- input_filename, pInput.getErrorMessage().c_str());
- goto bail;
- }
-
- data = reinterpret_cast<const uint8_t *>(map->getDataPtr());
-
- // Header starts at the beginning of the file.
- header = reinterpret_cast<const rsinfo::Header *>(data);
-
- // Check the magic.
- if (::memcmp(header->magic, RSINFO_MAGIC, sizeof(header->magic)) != 0) {
- ALOGV("Wrong magic found in the RS info file %s. Treat it as a dirty "
- "cache.", input_filename);
- goto bail;
- }
-
- // Check the version.
- if (::memcmp(header->version,
- RSINFO_VERSION,
- sizeof(header->version)) != 0) {
- ALOGV("Mismatch the version of RS info file %s: (current) %s v.s. (file) "
- "%s. Treat it as as a dirty cache.", input_filename, RSINFO_VERSION,
- header->version);
- goto bail;
- }
-
- // Check the size.
- if ((header->headerSize != sizeof(rsinfo::Header)) ||
- (header->pragmaList.itemSize != sizeof(rsinfo::PragmaItem)) ||
- (header->objectSlotList.itemSize != sizeof(rsinfo::ObjectSlotItem)) ||
- (header->exportVarNameList.itemSize != sizeof(rsinfo::ExportVarNameItem)) ||
- (header->exportFuncNameList.itemSize != sizeof(rsinfo::ExportFuncNameItem)) ||
- (header->exportForeachFuncList.itemSize != sizeof(rsinfo::ExportForeachFuncItem))) {
- ALOGW("Corrupted RS info file %s! (unexpected size found)", input_filename);
- goto bail;
- }
-
- // Check the range.
-#define LIST_DATA_RANGE(_list_header) \
- ((_list_header).offset + (_list_header).count * (_list_header).itemSize)
- if (((header->headerSize + header->strPoolSize) > filesize) ||
- (LIST_DATA_RANGE(header->pragmaList) > filesize) ||
- (LIST_DATA_RANGE(header->objectSlotList) > filesize) ||
- (LIST_DATA_RANGE(header->exportVarNameList) > filesize) ||
- (LIST_DATA_RANGE(header->exportFuncNameList) > filesize) ||
- (LIST_DATA_RANGE(header->exportForeachFuncList) > filesize)) {
- ALOGW("Corrupted RS info file %s! (data out of the range)", input_filename);
- goto bail;
- }
-#undef LIST_DATA_RANGE
-
- // File seems ok, create result RSInfo object.
- result = new (std::nothrow) RSInfo(header->strPoolSize);
- if (result == nullptr) {
- ALOGE("Out of memory when create RSInfo object for %s!", input_filename);
- goto bail;
- }
-
- // Make advice on our access pattern.
- map->advise(android::FileMap::SEQUENTIAL);
-
- // Copy the header.
- ::memcpy(&result->mHeader, header, sizeof(rsinfo::Header));
-
- if (header->strPoolSize > 0) {
- // Copy the string pool. The string pool is immediately after the header at
- // the offset header->headerSize.
- if (result->mStringPool == nullptr) {
- ALOGE("Out of memory when allocate string pool for RS info file %s!",
- input_filename);
- goto bail;
- }
- ::memcpy(result->mStringPool, data + result->mHeader.headerSize,
- result->mHeader.strPoolSize);
- }
-
- // Populate all the data to the result object.
- result->mSourceHash =
- reinterpret_cast<const uint8_t*>(result->getStringFromPool(header->sourceSha1Idx));
- if (result->mSourceHash == nullptr) {
- ALOGE("Invalid string index %d for SHA-1 checksum of source.", header->sourceSha1Idx);
- goto bail;
- }
-
- result->mCompileCommandLine = result->getStringFromPool(header->compileCommandLineIdx);
- if (result->mCompileCommandLine == nullptr) {
- ALOGE("Invalid string index %d for compile command line.", header->compileCommandLineIdx);
- goto bail;
- }
-
- result->mBuildFingerprint = result->getStringFromPool(header->buildFingerprintIdx);
- if (result->mBuildFingerprint == nullptr) {
- ALOGE("Invalid string index %d for build fingerprint.", header->buildFingerprintIdx);
- goto bail;
- }
-
- if (!helper_read_list<rsinfo::PragmaItem, PragmaListTy>
- (data, *result, header->pragmaList, result->mPragmas)) {
- goto bail;
- }
-
- if (!helper_read_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
- (data, *result, header->objectSlotList, result->mObjectSlots)) {
- goto bail;
- }
-
- if (!helper_read_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
- (data, *result, header->exportVarNameList, result->mExportVarNames)) {
- goto bail;
- }
-
- if (!helper_read_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
- (data, *result, header->exportFuncNameList, result->mExportFuncNames)) {
- goto bail;
- }
-
- if (!helper_read_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
- (data, *result, header->exportForeachFuncList, result->mExportForeachFuncs)) {
- goto bail;
- }
-
- // Clean up.
- delete map;
-
- return result;
-
-bail:
- delete map;
-
- delete result;
-
- return nullptr;
-} // RSInfo::ReadFromFile
diff --git a/lib/Renderscript/RSInfoWriter.cpp b/lib/Renderscript/RSInfoWriter.cpp
deleted file mode 100644
index f9e2e2f..0000000
--- a/lib/Renderscript/RSInfoWriter.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 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.
- */
-
-//===----------------------------------------------------------------------===//
-// This file implements RSInfo::write()
-//===----------------------------------------------------------------------===//
-
-#include "bcc/Renderscript/RSInfo.h"
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/OutputFile.h"
-
-using namespace bcc;
-
-namespace {
-
-template<typename ItemType, typename ItemContainer> inline bool
-helper_adapt_list_item(ItemType &pResult, const RSInfo &pInfo,
- const typename ItemContainer::const_iterator &pItem);
-
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
- rsinfo::PragmaItem &pResult,
- const RSInfo &pInfo,
- const RSInfo::PragmaListTy::const_iterator &pItem) {
- pResult.key = pInfo.getStringIdxInPool(pItem->first);
- pResult.value = pInfo.getStringIdxInPool(pItem->second);
-
- if (pResult.key == rsinfo::gInvalidStringIndex) {
- ALOGE("RS pragma list contains invalid string '%s' for key.", pItem->first);
- return false;
- }
-
- if (pResult.value == rsinfo::gInvalidStringIndex) {
- ALOGE("RS pragma list contains invalid string '%s' for value.",
- pItem->second);
- return false;
- }
-
- return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
- rsinfo::ObjectSlotItem &pResult,
- const RSInfo &pInfo,
- const RSInfo::ObjectSlotListTy::const_iterator &pItem) {
- pResult.slot = *pItem;
- return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
- rsinfo::ExportVarNameItem &pResult,
- const RSInfo &pInfo,
- const RSInfo::ExportVarNameListTy::const_iterator &pItem) {
- pResult.name = pInfo.getStringIdxInPool(*pItem);
-
- if (pResult.name == rsinfo::gInvalidStringIndex) {
- ALOGE("RS export vars contains invalid string '%s' for name.", *pItem);
- return false;
- }
-
- return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ExportFuncNameItem,
- RSInfo::ExportFuncNameListTy>(
- rsinfo::ExportFuncNameItem &pResult,
- const RSInfo &pInfo,
- const RSInfo::ExportFuncNameListTy::const_iterator &pItem) {
- pResult.name = pInfo.getStringIdxInPool(*pItem);
-
- if (pResult.name == rsinfo::gInvalidStringIndex) {
- ALOGE("RS export funcs contains invalid string '%s' for name.", *pItem);
- return false;
- }
-
- return true;
-}
-
-template<> inline bool
-helper_adapt_list_item<rsinfo::ExportForeachFuncItem,
- RSInfo::ExportForeachFuncListTy>(
- rsinfo::ExportForeachFuncItem &pResult,
- const RSInfo &pInfo,
- const RSInfo::ExportForeachFuncListTy::const_iterator &pItem) {
- pResult.name = pInfo.getStringIdxInPool(pItem->first);
- pResult.signature = pItem->second;
-
- if (pResult.name == rsinfo::gInvalidStringIndex) {
- ALOGE("RS export foreach contains invalid string '%s' for name.",
- pItem->first);
- return false;
- }
-
- return true;
-}
-
-template<typename ItemType, typename ItemContainer>
-inline bool helper_write_list(OutputFile &pOutput,
- const RSInfo &pInfo,
- const rsinfo::ListHeader &pHeader,
- ItemContainer &pList) {
- ItemType item;
-
- for (typename ItemContainer::const_iterator item_iter = pList.begin(),
- item_end = pList.end(); item_iter != item_end; item_iter++) {
- // Convert each entry in the pList to ItemType.
- if (!helper_adapt_list_item<ItemType, ItemContainer>(item,
- pInfo,
- item_iter)) {
- return false;
- }
- // And write out an item.
- if (pOutput.write(&item, sizeof(item)) != sizeof(item)) {
- ALOGE("Cannot write out item of %s for RSInfo file %s! (%s)",
- rsinfo::GetItemTypeName<ItemType>(), pOutput.getName().c_str(),
- pOutput.getErrorMessage().c_str());
- return false;
- }
- }
-
- return true;
-}
-
-} // end anonymous namespace
-
-bool RSInfo::write(OutputFile &pOutput) {
- off_t initial_offset = pOutput.tell();
- const char *output_filename = pOutput.getName().c_str();
-
- if (pOutput.hasError()) {
- ALOGE("Invalid RS info file %s for output! (%s)",
- output_filename, pOutput.getErrorMessage().c_str());
- return false;
- }
-
- // Layout.
- if (!layout(initial_offset)) {
- return false;
- }
-
- // Write header.
- if (pOutput.write(&mHeader, sizeof(mHeader)) != sizeof(mHeader)) {
- ALOGE("Cannot write out the header for RSInfo file %s! (%s)",
- output_filename, pOutput.getErrorMessage().c_str());
- return false;
- }
-
- // Write string pool.
- if (static_cast<size_t>(pOutput.write(mStringPool, mHeader.strPoolSize))
- != mHeader.strPoolSize) {
- ALOGE("Cannot write out the string pool for RSInfo file %s! (%s)",
- output_filename, pOutput.getErrorMessage().c_str());
- return false;
- }
-
- // Write pragmaList.
- if (!helper_write_list<rsinfo::PragmaItem, PragmaListTy>
- (pOutput, *this, mHeader.pragmaList, mPragmas)) {
- return false;
- }
-
- // Write objectSlotList.
- if (!helper_write_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
- (pOutput, *this, mHeader.objectSlotList, mObjectSlots)) {
- return false;
- }
-
- // Write exportVarNameList.
- if (!helper_write_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
- (pOutput, *this, mHeader.exportVarNameList, mExportVarNames)) {
- return false;
- }
-
- // Write exportFuncNameList.
- if (!helper_write_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
- (pOutput, *this, mHeader.exportFuncNameList, mExportFuncNames)) {
- return false;
- }
-
- // Write exportForeachFuncList.
- if (!helper_write_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
- (pOutput, *this, mHeader.exportForeachFuncList, mExportForeachFuncs)) {
- return false;
- }
-
- return true;
-}
diff --git a/lib/Renderscript/RSInvariant.cpp b/lib/Renderscript/RSInvariant.cpp
new file mode 100644
index 0000000..1119a7a
--- /dev/null
+++ b/lib/Renderscript/RSInvariant.cpp
@@ -0,0 +1,150 @@
+/*
+ * 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 "bcc/Renderscript/RSTransforms.h"
+
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Metadata.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Pass.h>
+
+namespace {
+
+/*
+ * RSInvariantPass - This pass looks for Loads that access
+ * RsExpandKernelDriverInfo instances (which should never be written by
+ * a script, only by the driver) and marks them "invariant.load".
+ *
+ * There should be only two sources of Loads from such instances:
+ * - An instance can appear as an argument of type
+ * "RsExpandKernelDriverInfoPfx*" passed to a .expand function by
+ * the driver.
+ * - An instance can appear as an argument of type
+ * "rs_kernel_context_t*" passed to an API query function by the
+ * user.
+ * Only the compiler-generated .expand functions and the API query
+ * functions can see the fields of RsExpandKernelDriverInfo --
+ * rs_kernel_context_t is opaque to user code, so there cannot be any
+ * Loads from it in user code.
+ *
+ * This pass should be run
+ * - after foreachexp, so that it can see the Loads generated within
+ * .expand functions
+ * - before inlining, so that it can recognize API query function
+ * arguments.
+ *
+ * WARNINGS:
+ * - If user code or APIs can modify RsExpandKernelDriverInfo
+ * instances, this pass MAY ALLOW ILLEGAL OPTIMIZATION.
+ * - If this pass runs at a different time, it may be ineffective
+ * (fail to mark some or all eligible Loads, and thereby cost
+ * performance).
+ * - If the names of the data types change, this pass may be
+ * ineffective.
+ * - If the patterns by which fields are loaded from
+ * RsExpandKernelDriverInfo instances change, this pass may be
+ * ineffective.
+ */
+class RSInvariantPass : public llvm::FunctionPass {
+public:
+ static char ID;
+
+ RSInvariantPass() : FunctionPass(ID), EmptyMDNode(nullptr) { }
+
+ virtual bool doInitialization(llvm::Module &M) {
+ EmptyMDNode = llvm::MDNode::get(M.getContext(), llvm::None);
+ return true;
+ }
+
+ virtual bool runOnFunction(llvm::Function &F) {
+ bool Changed = false;
+
+ for (llvm::Value &Arg : F.args()) {
+ const llvm::Type *ArgType = Arg.getType();
+ if (ArgType->isPointerTy()) {
+ const llvm::Type *ArgPtrDomainType = ArgType->getPointerElementType();
+ if (ArgPtrDomainType->isStructTy()) {
+ const llvm::StringRef StructName = ArgPtrDomainType->getStructName();
+ if (StructName.equals("struct.rs_kernel_context_t") || StructName.equals("RsExpandKernelDriverInfoPfx")) {
+ Changed |= markInvariantUserLoads(&Arg);
+ }
+ }
+ }
+ }
+
+ return Changed;
+ }
+
+ virtual const char *getPassName() const {
+ return "Renderscript Invariant Load Annotation";
+ }
+
+private:
+
+ /*
+ * Follow def->use chains rooted at Value through calculations
+ * "based on" Value (see the "based on" definition at
+ * http://llvm.org/docs/LangRef.html#pointer-aliasing-rules). If a
+ * chain reaches the pointer operand of a Load, mark that Load as
+ * "invariant.load" -- i.e., it accesses memory which does not
+ * change.
+ */
+ bool markInvariantUserLoads(llvm::Value *Value) {
+ bool Changed = false;
+ for (llvm::Use &Use : Value->uses()) {
+ llvm::Instruction *Inst = llvm::cast<llvm::Instruction>(Use.getUser());
+
+ /*
+ * We only examine a small set of opcodes here, because these
+ * are the opcodes that currently appear in the patterns of
+ * interest (foreachexp-generated code, and
+ * rsGet*(rs_kernel_context_t*) APIs). Other opcodes could be
+ * added if necessary.
+ */
+ if (auto BitCast = llvm::dyn_cast<llvm::BitCastInst>(Inst)) {
+ Changed |= markInvariantUserLoads(BitCast);
+ } else if (auto GetElementPtr = llvm::dyn_cast<llvm::GetElementPtrInst>(Inst)) {
+ if (Use.get() == GetElementPtr->getPointerOperand())
+ Changed |= markInvariantUserLoads(GetElementPtr);
+ } else if (auto Load = llvm::dyn_cast<llvm::LoadInst>(Inst)) {
+ if (Use.get() == Load->getPointerOperand()) {
+ Load->setMetadata("invariant.load", EmptyMDNode);
+ Changed = true;
+ }
+ }
+ }
+ return Changed;
+ }
+
+ // Pointer to empty metadata node used for "invariant.load" marking.
+ llvm::MDNode *EmptyMDNode;
+}; // end RSInvariantPass
+
+char RSInvariantPass::ID = 0;
+llvm::RegisterPass<RSInvariantPass> X("rsinvariant", "RS Invariant Load Pass");
+
+} // end anonymous namespace
+
+namespace bcc {
+
+llvm::FunctionPass *
+createRSInvariantPass() {
+ return new RSInvariantPass();
+}
+
+} // end namespace bcc
diff --git a/lib/Renderscript/RSScript.cpp b/lib/Renderscript/RSScript.cpp
index c93ca64..396b47d 100644
--- a/lib/Renderscript/RSScript.cpp
+++ b/lib/Renderscript/RSScript.cpp
@@ -17,7 +17,6 @@
#include "bcc/Renderscript/RSScript.h"
#include "bcc/Assert.h"
-#include "bcc/Renderscript/RSInfo.h"
#include "bcc/Source.h"
#include "bcc/Support/Log.h"
@@ -50,12 +49,11 @@
}
RSScript::RSScript(Source &pSource)
- : Script(pSource), mInfo(nullptr), mCompilerVersion(0),
+ : Script(pSource), mCompilerVersion(0),
mOptimizationLevel(kOptLvl3), mLinkRuntimeCallback(nullptr),
mEmbedInfo(false) { }
bool RSScript::doReset() {
- mInfo = nullptr;
mCompilerVersion = 0;
mOptimizationLevel = kOptLvl3;
return true;
diff --git a/lib/Support/Android.mk b/lib/Support/Android.mk
index f228f9d..b8cdc60 100644
--- a/lib/Support/Android.mk
+++ b/lib/Support/Android.mk
@@ -28,8 +28,6 @@
Initialization.cpp \
InputFile.cpp \
OutputFile.cpp \
- Sha1Util.cpp \
- sha1.c \
#=====================================================================
# Device Static Library: libbccSupport
diff --git a/lib/Support/Sha1Util.cpp b/lib/Support/Sha1Util.cpp
deleted file mode 100644
index 7cc636c..0000000
--- a/lib/Support/Sha1Util.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * copyright 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 "bcc/Support/Sha1Util.h"
-
-#include <sha1.h>
-
-#include <cstring>
-
-#include "bcc/Support/Log.h"
-#include "bcc/Support/InputFile.h"
-
-using namespace bcc;
-
-bool Sha1Util::GetSHA1DigestFromFile(uint8_t pResult[SHA1_DIGEST_LENGTH],
- const char *pFilename) {
- InputFile file(pFilename);
-
- if (file.hasError()) {
- ALOGE("Unable to open the file %s before SHA-1 checksum "
- "calculation! (%s)", pFilename, file.getErrorMessage().c_str());
- return false;
- }
-
- SHA1_CTX sha1_context;
- SHA1Init(&sha1_context);
-
- char buf[256];
- while (true) {
- ssize_t nread = file.read(buf, sizeof(buf));
-
- if (nread < 0) {
- // Some errors occurred during file reading.
- return false;
- }
-
- SHA1Update(&sha1_context,
- reinterpret_cast<unsigned char *>(buf),
- static_cast<unsigned long>(nread));
-
- if (static_cast<size_t>(nread) < sizeof(buf)) {
- break;
- }
- }
-
- SHA1Final(pResult, &sha1_context);
-
- return true;
-}
-
-bool Sha1Util::GetSHA1DigestFromBuffer(uint8_t pResult[SHA1_DIGEST_LENGTH],
- const uint8_t *pData, size_t pSize) {
- SHA1_CTX sha1_context;
-
- SHA1Init(&sha1_context);
-
- SHA1Update(&sha1_context,
- reinterpret_cast<const unsigned char *>(pData),
- static_cast<unsigned long>(pSize));
-
- SHA1Final(pResult, &sha1_context);
-
- return true;
-}
diff --git a/lib/Support/sha1.c b/lib/Support/sha1.c
deleted file mode 100644
index 553e560..0000000
--- a/lib/Support/sha1.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/* This file is derived from libdex project */
-
-/*
- * Tweaked in various ways for Google/Android:
- * - Changed from .cpp to .c.
- * - Made argument to SHA1Update a const pointer, and enabled
- * SHA1HANDSOFF. This incurs a speed penalty but prevents us from
- * trashing the input.
- * - Include <endian.h> to get endian info.
- * - Split a small piece into a header file.
- */
-
-/*
-sha1sum: inspired by md5sum.
-
-SHA-1 in C
-By Steve Reid <steve@edmweb.com>
-100% Public Domain
-
------------------
-Modified 7/98
-By James H. Brown <jbrown@burgoyne.com>
-Still 100% Public Domain
-
-bit machines
-Routine SHA1Update changed from
- void SHA1Update(SHA1_CTX* context, unsigned char* data,
- unsigned int len)
-to
- void SHA1Update(SHA1_CTX* context, unsigned char* data,
- unsigned long len)
-
-The 'len' parameter was declared an int which works fine on 32
-bit machines. However, on 16 bit machines an int is too small
-for the shifts being done against it. This caused the hash
-function to generate incorrect values if len was greater than
-8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
-
-Since the file IO in main() reads 16K at a time, any file 8K or
-larger would be guaranteed to generate the wrong hash (e.g.
-Test Vector #3, a million "a"s).
-
-I also changed the declaration of variables i & j in SHA1Update
-to unsigned long from unsigned int for the same reason.
-
-These changes should make no difference to any 32 bit
-implementations since an int and a long are the same size in
-those environments.
-
---
-I also corrected a few compiler warnings generated by Borland
-C.
-1. Added #include <process.h> for exit() prototype
-2. Removed unused variable 'j' in SHA1Final
-3. Changed exit(0) to return(0) at end of main.
-
-ALL changes I made can be located by searching for comments
-containing 'JHB'
-
------------------
-Modified 13 August 2000
-By Michael Paul Johnson <mpj@cryptography.org>
-Still 100% Public Domain
-
-Changed command line syntax, added feature to automatically
-check files against their previous SHA-1 check values, kind of
-like md5sum does. Added functions hexval, verifyfile,
-and sha1file. Rewrote main().
------------------
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-#define SHA1HANDSOFF /*Copies data before messing with it.*/
-
-/*#define CMDLINE * include main() and file processing */
-//#ifdef CMDLINE
-//# undef CMDLINE /* Never include main() for libbcc */
-//#endif
-
-#include "sha1.h"
-
-#include <stdio.h>
-#include <string.h>
-#ifdef __BORLANDC__
-#include <dir.h>
-#include <dos.h>
-#include <process.h> /* prototype for exit() - JHB
- needed for Win32, but chokes Linux - MPJ */
-#define X_LITTLE_ENDIAN /* This should be #define'd if true.*/
-#else
-# define X_LITTLE_ENDIAN
-# include <unistd.h>
-# include <stdlib.h>
-#endif
-#include <ctype.h>
-
-#define LINESIZE 2048
-
-static void SHA1Transform(uint32_t state[5], const uint8_t buffer[64]);
-
-#define rol(value,bits) \
- (((value)<<(bits))|((value)>>(32-(bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from
- SSLeay */
-#ifdef X_LITTLE_ENDIAN
-#define blk0(i) (block->l[i]=(rol(block->l[i],24)&0xFF00FF00) \
- |(rol(block->l[i],8)&0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
- ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-static void SHA1Transform(uint32_t state[5],
- const uint8_t buffer[64])
-{
-uint32_t a, b, c, d, e;
-typedef union {
- uint8_t c[64];
- uint32_t l[16];
-} CHAR64LONG16;
-CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-static uint8_t workspace[64];
- block = (CHAR64LONG16*)workspace;
- memcpy(block, buffer, 64);
-#else
- block = (CHAR64LONG16*)buffer;
-#endif
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2);
- R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5);
- R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8);
- R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14);
- R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17);
- R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20);
- R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26);
- R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29);
- R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32);
- R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38);
- R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41);
- R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44);
- R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50);
- R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53);
- R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56);
- R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62);
- R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65);
- R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68);
- R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74);
- R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77);
- R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- /* Wipe variables */
-/* a = b = c = d = e = 0; Nice try, but the compiler
-optimizes this out, anyway, and it produces an annoying
-warning. */
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, const uint8_t* data,
- uint32_t len) /* JHB */
-{
- uint32_t i, j; /* JHB */
-
- j = (context->count[0] >> 3) & 63;
- if ((context->count[0] += len << 3) < (len << 3))
- context->count[1]++;
- context->count[1] += (len >> 29);
- if ((j + len) > 63)
- {
- memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64) {
- SHA1Transform(context->state, &data[i]);
- }
- j = 0;
- }
- else
- i = 0;
- memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(uint8_t digest[HASHSIZE], SHA1_CTX*
-context)
-{
-uint32_t i; /* JHB */
-uint8_t finalcount[8];
-
- for (i = 0; i < 8; i++)
- {
- finalcount[i] = (uint8_t)((context->count[(i>=4?
- 0:1)]>>((3-(i&3))*8))&255);
- /* Endian independent */
- }
- SHA1Update(context, (uint8_t *)"\200", 1);
- while ((context->count[0] & 504) != 448) {
- SHA1Update(context, (uint8_t *)"\0", 1);
- }
- SHA1Update(context, finalcount, 8);
- /* Should cause a SHA1Transform() */
- for (i = 0; i < HASHSIZE; i++) {
- digest[i] = (uint8_t)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
- /* Wipe variables */
- memset(context->buffer, 0, 64);
- memset(context->state, 0, HASHSIZE);
- memset(context->count, 0, 8);
- memset(&finalcount, 0, 8);
-#ifdef SHA1HANDSOFF
- /* make SHA1Transform overwrite it's own static vars */
- SHA1Transform(context->state, context->buffer);
-#endif
-}
-
-
-
-#ifdef CMDLINE
-
-/* sha1file computes the SHA-1 hash of the named file and puts
- it in the 20-byte array digest. If fname is NULL, stdin is
- assumed.
-*/
-void sha1file(char *fname, uint8_t* digest)
-{
- int bytesread;
- SHA1_CTX context;
- uint8_t buffer[16384];
- FILE* f;
-
- if (fname)
- {
- f = fopen(fname, "rb");
- if (!f)
- {
- fprintf(stderr, "Can't open %s\n", fname);
- memset(digest, 0, HASHSIZE);
- return;
- }
- }
- else
- {
- f = stdin;
- }
- SHA1Init(&context);
- while (!feof(f))
- {
- bytesread = fread(buffer, 1, 16384, f);
- SHA1Update(&context, buffer, bytesread);
- }
- SHA1Final(digest, &context);
- if (fname)
- fclose(f);
-}
-
-/* Convert ASCII hexidecimal digit to 4-bit value. */
-uint8_t hexval(char c)
-{
- uint8_t h;
-
- c = toupper(c);
- if (c >= 'A')
- h = c - 'A' + 10;
- else
- h = c - '0';
- return h;
-}
-
-/* Verify a file created with sha1sum by redirecting output
- to a file. */
-int verifyfile(char *fname)
-{
- int j, k;
- int found = 0;
- uint8_t digest[HASHSIZE];
- uint8_t expected_digest[HASHSIZE];
- FILE *checkfile;
- char checkline[LINESIZE];
- char *s;
- uint8_t err;
-
- checkfile = fopen(fname, "rt");
- if (!checkfile)
- {
- fprintf(stderr, "Can't open %s\n", fname);
- return(0);
- }
- do
- {
- s = fgets(checkline, LINESIZE, checkfile);
- if (s)
- {
- if ((strlen(checkline)>26)&&
- 1 /*(!strncmp(checkline,"SHA1=", 5))*/)
- {
- /* Overwrite newline. */
- checkline[strlen(checkline)-1]=0;
- found = 1;
-
- /* Read expected check value. */
- for (k=0, j=5; k < HASHSIZE; k++)
- {
- expected_digest[k]=hexval(checkline[j++]);
- expected_digest[k]=(expected_digest[k]<<4)
- +hexval(checkline[j++]);
- }
-
- /* Compute fingerprints */
- s = checkline+46;
- sha1file(s, digest);
-
- /* Compare fingerprints */
- err = 0;
- for (k=0; k<HASHSIZE; k++)
- err |= digest[k]-
- expected_digest[k];
- if (err)
- {
- fprintf(stderr, "FAILED: %s\n"
- " EXPECTED: ", s);
- for (k=0; k<HASHSIZE; k++)
- fprintf(stderr, "%02X",
- expected_digest[k]);
- fprintf(stderr,"\n FOUND: ");
- for (k=0; k<HASHSIZE; k++)
- fprintf(stderr, "%02X", digest[k]);
- fprintf(stderr, "\n");
- }
- else
- {
- printf("OK: %s\n", s);
- }
- }
- }
- } while (s);
- return found;
-}
-
-
-
-void syntax(char *progname)
-{
- printf("\nsyntax:\n"
- "%s [-c|-h][-q] file name[s]\n"
- " -c = check files against previous check values\n"
- " -g = generate SHA-1 check values (default action)\n"
- " -h = display this help\n"
- "For example,\n"
- "sha1sum test.txt > check.txt\n"
- "generates check value for test.txt in check.txt, and\n"
- "sha1sum -c check.txt\n"
- "checks test.txt against the check value in check.txt\n",
- progname);
- exit(1);
-}
-
-
-/**********************************************************/
-
-int main(int argc, char** argv)
-{
- int i, j, k;
- int check = 0;
- int found = 0;
- uint8_t digest[HASHSIZE];
- uint8_t expected_digest[HASHSIZE];
- FILE *checkfile;
- char checkline[LINESIZE];
- char *s;
-#ifdef __BORLANDC__
- struct ffblk f;
- int done;
- char path[MAXPATH];
- char drive[MAXDRIVE];
- char dir[MAXDIR];
- char name[MAXFILE];
- char ext[MAXEXT];
-#endif
- uint8_t err;
- const char *binary_output_file = 0;
-
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] == '-')
- {
- switch (argv[i][1])
- {
- case 'B':
- ++i;
- binary_output_file = argv[i];
- break;
- case 'c':
- case 'C':
- check = 1;
- break;
- case 'g':
- case 'G':
- check = 0;
- break;
- default:
- syntax(argv[0]);
- }
- }
- }
-
- // Read from STDIN
- sha1file(NULL, digest);
- if (binary_output_file) {
- FILE *fout = fopen(binary_output_file, "wb");
- if (!fout) {
- fprintf(stderr, "Error: Can not write to %s.\n", binary_output_file);
- return 1;
- }
- fwrite(digest, 1, HASHSIZE, fout);
- fclose(fout);
- return 0;
- }
- for (j = 0; j < HASHSIZE; j++)
- printf("%02x", digest[j]);
- return 0;
-
- for (i=1; i<argc; i++)
- {
- if (argv[i][0] != '-')
- {
-#ifdef __BORLANDC__
- fnsplit(argv[i], drive, dir, name, ext);
- done = findfirst(argv[i], &f, FA_RDONLY |
- FA_HIDDEN|FA_SYSTEM|FA_ARCH);
- while (!done)
- {
- sprintf(path, "%s%s%s", drive, dir, f.ff_name);
- s = path;
-#else
- s = argv[i];
-#endif
-
- if (check)
- { /* Check fingerprint file. */
- found |= verifyfile(s);
- }
- else
- { /* Generate fingerprints & write to
- stdout. */
- sha1file(s, digest);
- //printf("SHA1=");
- for (j=0; j<HASHSIZE; j++)
- printf("%02x", digest[j]);
- printf(" %s\n", s);
- found = 1;
- }
-
-#ifdef __BORLANDC__
- done = findnext(&f);
- }
-#endif
-
- }
- }
- if (!found)
- {
- if (check)
- {
- fprintf(stderr,
- "No SHA1 lines found in %s\n",
- argv[i]);
- }
- else
- {
- fprintf(stderr, "No files checked.\n");
- syntax(argv[0]);
- }
- }
- return(0); /* JHB */
-}
-
-#endif /*CMDLINE*/
diff --git a/tools/bcc/Main.cpp b/tools/bcc/Main.cpp
index a047e88..cfe8b97 100644
--- a/tools/bcc/Main.cpp
+++ b/tools/bcc/Main.cpp
@@ -41,6 +41,7 @@
#include <bcc/Renderscript/RSCompilerDriver.h>
#include <bcc/Script.h>
#include <bcc/Source.h>
+#include <bcc/Support/Log.h>
#include <bcc/Support/CompilerConfig.h>
#include <bcc/Support/Initialization.h>
#include <bcc/Support/InputFile.h>
@@ -288,7 +289,6 @@
init::Initialize();
llvm::cl::SetVersionPrinter(BCCVersionPrinter);
llvm::cl::ParseCommandLineOptions(argc, argv);
- std::string commandLine = bcc::getCommandLine(argc, argv);
BCCContext context;
RSCompilerDriver RSCD;
@@ -334,9 +334,11 @@
size_t bitcodeSize = input_data->getBufferSize();
if (!OptEmbedRSInfo) {
- bool built = RSCD.build(context, OptOutputPath.c_str(), OptOutputFilename.c_str(), bitcode,
- bitcodeSize, commandLine.c_str(), OptChecksum.c_str(), OptBCLibFilename.c_str(), nullptr,
- OptEmitLLVM);
+ bool built = RSCD.build(context, OptOutputPath.c_str(),
+ OptOutputFilename.c_str(),
+ bitcode, bitcodeSize,
+ OptChecksum.c_str(), OptBCLibFilename.c_str(),
+ nullptr, OptEmitLLVM);
if (!built) {
return EXIT_FAILURE;