Use build fingerprint and compile command for caching.
If either of those have changed, we need to invalidate the
compiled bit code.
Change-Id: I9b5cdc19e29237dc7fb2ec1627a167f3f8987702
diff --git a/include/bcc/Renderscript/RSCompilerDriver.h b/include/bcc/Renderscript/RSCompilerDriver.h
index f0246b4..3fe23ed 100644
--- a/include/bcc/Renderscript/RSCompilerDriver.h
+++ b/include/bcc/Renderscript/RSCompilerDriver.h
@@ -58,12 +58,16 @@
// been changed and false if it remains unchanged.
bool setupConfig(const RSScript &pScript);
- Compiler::ErrorCode compileScript(RSScript &pScript,
- const char* pScriptName,
- const char *pOutputPath,
- const char *pRuntimePath,
- const RSInfo::DependencyHashTy &pSourceHash,
- bool pSkipLoad, bool pDumpIR = false);
+ // 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, bool saveInfoFile, bool pDumpIR);
public:
RSCompilerDriver(bool pUseCompilerRT = true);
@@ -104,18 +108,20 @@
// all be const-methods. They're not now because the getAddress() in
// 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 *pRuntimePath,
- RSLinkRuntimeCallback pLinkRuntimeCallback = NULL,
+ bool build(BCCContext& pContext, const char* pCacheDir, const char* pResName,
+ const char* pBitcode, size_t pBitcodeSize, const char* commandLine,
+ const char* pRuntimePath, RSLinkRuntimeCallback pLinkRuntimeCallback = NULL,
bool pDumpIR = false);
// Returns true if script is successfully compiled.
bool buildForCompatLib(RSScript &pScript, const char *pOut, const char *pRuntimePath);
- static RSExecutable *loadScript(const char *pCacheDir, const char *pResName,
- const char *pBitcode, size_t pBitcodeSize,
- SymbolResolverProxy &pResolver);
+ // Tries to load the the compiled bit code at pCacheDir of the given name. It checks that
+ // the file has been compiled from the same bit code and with the same compile arguments as
+ // provided.
+ static RSExecutable* loadScript(const char* pCacheDir, const char* pResName, const char* pBitcode,
+ size_t pBitcodeSize, const char* expectedCompileCommandLine,
+ SymbolResolverProxy& pResolver);
};
} // end namespace bcc
diff --git a/include/bcc/Renderscript/RSInfo.h b/include/bcc/Renderscript/RSInfo.h
index e88b410..ae2bfcb 100644
--- a/include/bcc/Renderscript/RSInfo.h
+++ b/include/bcc/Renderscript/RSInfo.h
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include <string>
#include <utility>
#include "bcc/Support/Log.h"
@@ -48,7 +49,7 @@
#define RSINFO_MAGIC "\0rsinfo\n"
/* RS info file version, encoded in 4 bytes of ASCII */
-#define RSINFO_VERSION "005\0"
+#define RSINFO_VERSION "006\0"
struct __attribute__((packed)) ListHeader {
// The offset from the beginning of the file of data
@@ -74,9 +75,13 @@
uint32_t strPoolSize;
- // The SHA-1 checksum of the source file is stored as a string in the string pool.
+ // 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;
@@ -154,7 +159,10 @@
// executable file.
static android::String8 GetPath(const char *pFilename);
- bool CheckDependency(const char* pInputFilename, const DependencyHashTy& expectedSourceHash);
+ // 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:
@@ -162,7 +170,14 @@
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;
@@ -182,7 +197,9 @@
// Implemented in RSInfoExtractor.cpp.
static RSInfo *ExtractFromSource(const Source &pSource,
- const DependencyHashTy &sourceHash);
+ const DependencyHashTy &sourceHashToEmbed,
+ const char* compileCommandLineToEmbed,
+ const char* buildFingerprintToEmbed);
// Implemented in RSInfoReader.cpp.
static RSInfo *ReadFromFile(InputFile &pInput);
@@ -227,6 +244,9 @@
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/lib/Renderscript/RSCompilerDriver.cpp b/lib/Renderscript/RSCompilerDriver.cpp
index 5adc362..ebc0d8f 100644
--- a/lib/Renderscript/RSCompilerDriver.cpp
+++ b/lib/Renderscript/RSCompilerDriver.cpp
@@ -26,6 +26,7 @@
#include "bcc/Compiler.h"
#include "bcc/Config/Config.h"
#include "bcc/Renderscript/RSExecutable.h"
+#include "bcc/Renderscript/RSInfo.h"
#include "bcc/Renderscript/RSScript.h"
#include "bcc/Support/CompilerConfig.h"
#include "bcc/Source.h"
@@ -44,6 +45,17 @@
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(NULL), mCompiler(), mDebugContext(false),
mLinkRuntimeCallback(NULL), mEnableGlobalMerge(true) {
@@ -54,11 +66,11 @@
delete mConfig;
}
-RSExecutable *
-RSCompilerDriver::loadScript(const char *pCacheDir, const char *pResName,
- const char *pBitcode, size_t pBitcodeSize,
- SymbolResolverProxy &pResolver) {
- //android::StopWatch load_time("bcc: RSCompilerDriver::loadScript time");
+RSExecutable* RSCompilerDriver::loadScript(const char* pCacheDir, const char* pResName,
+ const char* pBitcode, size_t pBitcodeSize,
+ const char* expectedCompileCommandLine,
+ SymbolResolverProxy& pResolver) {
+ // android::StopWatch load_time("bcc: RSCompilerDriver::loadScript time");
if ((pCacheDir == NULL) || (pResName == NULL)) {
ALOGE("Missing pCacheDir and/or pResName");
return NULL;
@@ -70,9 +82,6 @@
return NULL;
}
- uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
- Sha1Util::GetSHA1DigestFromBuffer(bitcode_sha1, pBitcode, pBitcodeSize);
-
// {pCacheDir}/{pResName}.o
llvm::SmallString<80> output_path(pCacheDir);
llvm::sys::path::append(output_path, pResName);
@@ -114,7 +123,7 @@
return NULL;
}
- //===---------------------------------------------------------------------===//
+ //===---------------------------------------------------------------------===//
// Open and load the RS info file.
//===--------------------------------------------------------------------===//
InputFile info_file(info_path.string());
@@ -128,26 +137,37 @@
return NULL;
}
- // If the info file contains a different hash for the source than what we are
- // looking for, bail. The bit code found on disk is out of date and needs to
- // be recompiled first.
- if (!info->CheckDependency(output_path.c_str(), bitcode_sha1)) {
- delete object_file;
- delete info;
- return NULL;
+ //===---------------------------------------------------------------------===//
+ // Check that the info in the RS info file is consistent we what we want.
+ //===--------------------------------------------------------------------===//
+
+ uint8_t expectedSourceHash[SHA1_DIGEST_LENGTH];
+ Sha1Util::GetSHA1DigestFromBuffer(expectedSourceHash, pBitcode, pBitcodeSize);
+
+ std::string expectedBuildFingerprint = getBuildFingerPrint();
+
+ // If the info file contains different hash for the source than what we are
+ // looking for, bail. Do the same if the command line used when compiling or the
+ // build fingerprint of Android has changed. The compiled code found on disk is
+ // out of date and needs to be recompiled first.
+ if (!info->IsConsistent(output_path.c_str(), expectedSourceHash, expectedCompileCommandLine,
+ expectedBuildFingerprint.c_str())) {
+ delete object_file;
+ delete info;
+ return NULL;
}
//===--------------------------------------------------------------------===//
// Create the RSExecutable.
//===--------------------------------------------------------------------===//
- RSExecutable *result = RSExecutable::Create(*info, *object_file, pResolver);
- if (result == NULL) {
+ RSExecutable *executable = RSExecutable::Create(*info, *object_file, pResolver);
+ if (executable == NULL) {
delete object_file;
delete info;
return NULL;
}
- return result;
+ return executable;
}
#if defined(PROVIDE_ARM_CODEGEN)
@@ -195,14 +215,13 @@
return changed;
}
-Compiler::ErrorCode
-RSCompilerDriver::compileScript(RSScript &pScript,
- const char* pScriptName,
- const char *pOutputPath,
- const char *pRuntimePath,
- const RSInfo::DependencyHashTy &pSourceHash,
- bool pSkipLoad, bool pDumpIR) {
- //android::StopWatch compile_time("bcc: RSCompilerDriver::compileScript time");
+Compiler::ErrorCode RSCompilerDriver::compileScript(RSScript& pScript, const char* pScriptName,
+ const char* pOutputPath,
+ const char* pRuntimePath,
+ const RSInfo::DependencyHashTy& pSourceHash,
+ const char* compileCommandLineToEmbed,
+ bool saveInfoFile, bool pDumpIR) {
+ // android::StopWatch compile_time("bcc: RSCompilerDriver::compileScript time");
RSInfo *info = NULL;
//===--------------------------------------------------------------------===//
@@ -210,7 +229,8 @@
//===--------------------------------------------------------------------===//
// 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);
+ info = RSInfo::ExtractFromSource(pScript.getSource(), pSourceHash, compileCommandLineToEmbed,
+ getBuildFingerPrint().c_str());
if (info == NULL) {
return Compiler::kErrInvalidSource;
}
@@ -299,13 +319,7 @@
}
}
- // No need to produce an RSExecutable in this case.
- // TODO: Error handling in this case is nonexistent.
- if (pSkipLoad) {
- return Compiler::kSuccess;
- }
-
- {
+ if (saveInfoFile) {
android::String8 info_path = RSInfo::GetPath(pOutputPath);
OutputFile info_file(info_path.string(), FileBase::kTruncate);
@@ -337,6 +351,7 @@
const char *pResName,
const char *pBitcode,
size_t pBitcodeSize,
+ const char *commandLine,
const char *pRuntimePath,
RSLinkRuntimeCallback pLinkRuntimeCallback,
bool pDumpIR) {
@@ -380,48 +395,42 @@
return false;
}
- RSScript *script = new (std::nothrow) RSScript(*source);
- if (script == NULL) {
- ALOGE("Out of memory when create Script object for '%s'! (output: %s)",
- pResName, output_path.c_str());
- delete source;
- return false;
- }
+ RSScript script(*source);
if (pLinkRuntimeCallback) {
setLinkRuntimeCallback(pLinkRuntimeCallback);
}
- script->setLinkRuntimeCallback(getLinkRuntimeCallback());
+ script.setLinkRuntimeCallback(getLinkRuntimeCallback());
// Read information from bitcode wrapper.
bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
- script->setCompilerVersion(wrapper.getCompilerVersion());
- script->setOptimizationLevel(static_cast<RSScript::OptimizationLevel>(
- wrapper.getOptimizationLevel()));
+ script.setCompilerVersion(wrapper.getCompilerVersion());
+ script.setOptimizationLevel(static_cast<RSScript::OptimizationLevel>(
+ wrapper.getOptimizationLevel()));
//===--------------------------------------------------------------------===//
// Compile the script
//===--------------------------------------------------------------------===//
- Compiler::ErrorCode status = compileScript(*script, pResName,
+ Compiler::ErrorCode status = compileScript(script, pResName,
output_path.c_str(),
- pRuntimePath, bitcode_sha1, false,
- pDumpIR);
+ pRuntimePath, bitcode_sha1, commandLine,
+ true, pDumpIR);
- // Script is no longer used. Free it to get more memory.
- delete script;
-
- if (status != Compiler::kSuccess) {
- return false;
- }
-
- return true;
+ return status == Compiler::kSuccess;
}
bool RSCompilerDriver::buildForCompatLib(RSScript &pScript, const char *pOut,
const char *pRuntimePath) {
- uint8_t bitcode_sha1[SHA1_DIGEST_LENGTH];
- RSInfo *info = RSInfo::ExtractFromSource(pScript.getSource(), bitcode_sha1);
+ // 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 == NULL) {
return false;
}
@@ -431,8 +440,8 @@
// offline (host) compilation.
pScript.setEmbedInfo(true);
- Compiler::ErrorCode status = compileScript(pScript, pOut, pOut, pRuntimePath,
- bitcode_sha1, true);
+ Compiler::ErrorCode status = compileScript(pScript, pOut, pOut, pRuntimePath, bitcode_sha1,
+ compileCommandLineToEmbed, false, false);
if (status != Compiler::kSuccess) {
return false;
}
diff --git a/lib/Renderscript/RSInfo.cpp b/lib/Renderscript/RSInfo.cpp
index e8793e7..1578dc7 100644
--- a/lib/Renderscript/RSInfo.cpp
+++ b/lib/Renderscript/RSInfo.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#include "bcc/Renderscript/RSInfo.h"
#if !defined(_WIN32) /* TODO create a HAVE_DLFCN_H */
@@ -40,28 +40,51 @@
return result;
}
-#define PRINT_DEPENDENCY(PREFIX, X) \
- ALOGV("\t" PREFIX "SHA-1: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", \
- (X)[ 0], (X)[ 1], (X)[ 2], (X)[ 3], (X)[ 4], (X)[ 5], \
- (X)[ 6], (X)[ 7], (X)[ 8], (X)[ 9], (X)[10], (X)[11], \
- (X)[12], (X)[13], (X)[14], (X)[15], (X)[16], (X)[17], \
- (X)[18], (X)[19]);
+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;
+}
-bool RSInfo::CheckDependency(const char* pInputFilename,
- const DependencyHashTy& pExpectedSourceHash) {
- if (::memcmp(mSourceHash, pExpectedSourceHash, SHA1_DIGEST_LENGTH) != 0) {
+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);
- PRINT_DEPENDENCY("given - ", pExpectedSourceHash);
- PRINT_DEPENDENCY("cache - ", mSourceHash);
+ ALOGD("expected: %s", stringFromSourceHash(expectedSourceHash).c_str());
+ ALOGD("cached : %s", stringFromSourceHash(mSourceHash).c_str());
return false;
}
- // TODO Remove once done with cache fixes.
- // ALOGD("Cache %s is not dirty, the source it depends on has not changed:", pInputFilename);
- // PRINT_DEPENDENCY("given - ", pExpectedSourceHash);
- // PRINT_DEPENDENCY("cache - ", mSourceHash);
-
+ 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;
}
@@ -89,6 +112,8 @@
::memset(mStringPool, 0, mHeader.strPoolSize);
}
mSourceHash = NULL;
+ mCompileCommandLine = NULL;
+ mBuildFingerprint = NULL;
}
RSInfo::~RSInfo() {
@@ -129,11 +154,14 @@
ALOGV("\tString pool size: %u", mHeader.strPoolSize);
if (mSourceHash == NULL) {
- ALOGE("Source hash: NULL!");
+ ALOGV("Source hash: NULL!");
} else {
- PRINT_DEPENDENCY("Source hash: ", mSourceHash);
+ ALOGV("Source hash: %s", stringFromSourceHash(mSourceHash).c_str());
}
+ ALOGV("Compile Command Line: ", mCompileCommandLine ? mCompileCommandLine : "(NULL)");
+ ALOGV("mBuildFingerprint: ", mBuildFingerprint ? mBuildFingerprint : "(NULL)");
+
#define DUMP_LIST_HEADER(_name, _header) do { \
ALOGV(_name ":"); \
ALOGV("\toffset: %u", (_header).offset); \
diff --git a/lib/Renderscript/RSInfoExtractor.cpp b/lib/Renderscript/RSInfoExtractor.cpp
index 1684ed4..2ac6057 100644
--- a/lib/Renderscript/RSInfoExtractor.cpp
+++ b/lib/Renderscript/RSInfoExtractor.cpp
@@ -88,6 +88,7 @@
// 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()) {
@@ -107,9 +108,9 @@
} // end anonymous namespace
-RSInfo *RSInfo::ExtractFromSource(const Source &pSource,
- const DependencyHashTy &pSourceHashToEmbed)
-{
+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();
@@ -145,8 +146,10 @@
string_pool_size += getMetadataStringLength<1>(export_func);
string_pool_size += getMetadataStringLength<1>(export_foreach_name);
- // Reserve the space for the source hash.
+ // 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);
@@ -331,16 +334,24 @@
#undef FOR_EACH_NODE_IN
//===------------------------------------------------------------------===//
- // Record dependency information.
+ // 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, pSourceHashToEmbed, SHA1_DIGEST_LENGTH);
+ ::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);
}
//===--------------------------------------------------------------------===//
diff --git a/lib/Renderscript/RSInfoReader.cpp b/lib/Renderscript/RSInfoReader.cpp
index bf66b66..fc9ff2f 100644
--- a/lib/Renderscript/RSInfoReader.cpp
+++ b/lib/Renderscript/RSInfoReader.cpp
@@ -257,6 +257,18 @@
goto bail;
}
+ result->mCompileCommandLine = result->getStringFromPool(header->compileCommandLineIdx);
+ if (result->mCompileCommandLine == NULL) {
+ ALOGE("Invalid string index %d for compile command line.", header->compileCommandLineIdx);
+ goto bail;
+ }
+
+ result->mBuildFingerprint = result->getStringFromPool(header->buildFingerprintIdx);
+ if (result->mBuildFingerprint == NULL) {
+ 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;
diff --git a/tools/bcc/Main.cpp b/tools/bcc/Main.cpp
index 02860fe..beaf6c4 100644
--- a/tools/bcc/Main.cpp
+++ b/tools/bcc/Main.cpp
@@ -157,6 +157,7 @@
int main(int argc, char **argv) {
llvm::cl::SetVersionPrinter(BCCVersionPrinter);
llvm::cl::ParseCommandLineOptions(argc, argv);
+ std::string commandLine = bcc::getCommandLine(argc, argv);
init::Initialize();
BCCContext context;
@@ -193,9 +194,9 @@
rscdi(&RSCD);
}
- bool built = RSCD.build(context, OptOutputPath.c_str(),
- OptOutputFilename.c_str(), bitcode, bitcodeSize,
- OptBCLibFilename.c_str(), NULL, OptEmitLLVM);
+ bool built = RSCD.build(context, OptOutputPath.c_str(), OptOutputFilename.c_str(), bitcode,
+ bitcodeSize, commandLine.c_str(), OptBCLibFilename.c_str(), NULL,
+ OptEmitLLVM);
if (!built) {
return EXIT_FAILURE;