Add bccReadFile, bccLinkFile.
diff --git a/lib/bcc/Compiler.cpp b/lib/bcc/Compiler.cpp
index c8d9eb4..b00aaa4 100644
--- a/lib/bcc/Compiler.cpp
+++ b/lib/bcc/Compiler.cpp
@@ -241,69 +241,24 @@
return;
}
-// Compiler::readBC
-// Parameters:
-//
-int Compiler::readBC(const char *bitcode, size_t bitcodeSize) {
- llvm::OwningPtr<llvm::MemoryBuffer> MEM;
- if (bitcode == NULL || bitcodeSize <= 0)
- return 1;
+llvm::Module *Compiler::parseBitcodeFile(llvm::MemoryBuffer *MEM) {
+ llvm::Module *result = llvm::ParseBitcodeFile(MEM, *mContext, &mError);
- // Package input to object MemoryBuffer
- MEM.reset(llvm::MemoryBuffer::getMemBuffer(
- llvm::StringRef(bitcode, bitcodeSize)));
-
- if (MEM.get() == NULL) {
- setError("Error reading input program bitcode into memory");
- return hasError();
+ if (!result) {
+ LOGE("Unable to ParseBitcodeFile: %s\n", mError.c_str());
+ return NULL;
}
- // Read the input Bitcode as a Module
- mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
- MEM.reset();
- return hasError();
+ return result;
}
-// bitcodeSize == 1: Link against file
-// bitcodeSize > 1: Link against buffer
-int Compiler::linkBC(const char *bitcode, size_t bitcodeSize) {
- llvm::OwningPtr<llvm::MemoryBuffer> MEM;
-
- if (bitcodeSize == 1) { // link against file
- } else if (bitcode == NULL || bitcodeSize <= 0) {
- LOGE("Invalid bitcode for linkBC\n");
- return 1;
- }
-
- if (mModule == NULL) {
- setError("No module presents for linking");
+int Compiler::linkModule(llvm::Module *moduleWith) {
+ if (llvm::Linker::LinkModules(mModule, moduleWith, &mError) != 0) {
return hasError();
}
-#if 1
- MEM.reset(llvm::MemoryBuffer::getFile("/system/lib/libclcore.bc"));
-
-#else
- MEM.reset(llvm::MemoryBuffer::getMemBuffer(
- llvm::StringRef(bitcode, bitcodeSize)));
-#endif
-
- if (MEM.get() == NULL) {
- setError("Error reading input library bitcode into memory");
- return hasError();
- }
-
- llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
- *mContext,
- &mError));
- if (Lib.get() == NULL)
- return hasError();
-
- if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
- return hasError();
-
// Everything for linking should be settled down here with no error occurs
mHasLinked = true;
return hasError();
diff --git a/lib/bcc/Compiler.h b/lib/bcc/Compiler.h
index abfbc3d..a22c329 100644
--- a/lib/bcc/Compiler.h
+++ b/lib/bcc/Compiler.h
@@ -37,6 +37,7 @@
namespace llvm {
class LLVMContext;
class Module;
+ class MemoryBuffer;
}
@@ -110,14 +111,14 @@
CodeEmitter *createCodeEmitter();
+ llvm::Module *parseBitcodeFile(llvm::MemoryBuffer *MEM);
+
int readModule(llvm::Module *module) {
mModule = module;
return hasError();
}
- int readBC(const char *bitcode, size_t bitcodeSize);
-
- int linkBC(const char *bitcode, size_t bitcodeSize);
+ int linkModule(llvm::Module *module);
int compile();
diff --git a/lib/bcc/Script.cpp b/lib/bcc/Script.cpp
index 23fe9cf..b6ed5d8 100644
--- a/lib/bcc/Script.cpp
+++ b/lib/bcc/Script.cpp
@@ -28,8 +28,11 @@
#include "ScriptCompiled.h"
#include "ScriptCached.h"
#include "Sha1Helper.h"
+#include "SourceInfo.h"
#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <new>
#include <string.h>
@@ -63,52 +66,101 @@
default:
break;
}
+
+ for (size_t i = 0; i < 2; ++i) {
+ delete mSourceList[i];
+ }
}
-int Script::readBC(char const *resName,
- const char *bitcode,
- size_t bitcodeSize,
- unsigned long flags) {
+int Script::addSourceBC(size_t idx,
+ char const *resName,
+ const char *bitcode,
+ size_t bitcodeSize,
+ unsigned long flags) {
if (mStatus != ScriptStatus::Unknown) {
mErrorCode = BCC_INVALID_OPERATION;
- LOGE("Invalid operation: %s\n", __func__);
+ LOGE("Bad operation: Adding source after bccPrepareExecutable\n");
return 1;
}
- sourceBC = bitcode;
- sourceResName = resName;
- sourceSize = bitcodeSize;
+ if (!bitcode) {
+ mErrorCode = BCC_INVALID_VALUE;
+ LOGE("Invalid argument: bitcode = NULL\n");
+ return 1;
+ }
+
+ mSourceList[idx] = SourceInfo::createFromBuffer(resName,
+ bitcode, bitcodeSize,
+ flags);
+
+ if (!mSourceList[idx]) {
+ mErrorCode = BCC_OUT_OF_MEMORY;
+ LOGE("Out of memory while adding source bitcode\n");
+ return 1;
+ }
+
return 0;
}
-int Script::readModule(char const *resName,
- llvm::Module *module,
- unsigned long flags) {
+int Script::addSourceModule(size_t idx,
+ llvm::Module *module,
+ unsigned long flags) {
if (mStatus != ScriptStatus::Unknown) {
mErrorCode = BCC_INVALID_OPERATION;
- LOGE("Invalid operation: %s\n", __func__);
+ LOGE("Bad operation: Adding source after bccPrepareExecutable\n");
return 1;
}
- sourceModule = module;
+ if (!module) {
+ mErrorCode = BCC_INVALID_VALUE;
+ LOGE("Invalid argument: module = NULL\n");
+ return 1;
+ }
+
+ mSourceList[idx] = SourceInfo::createFromModule(module, flags);
+
+ if (!mSourceList[idx]) {
+ mErrorCode = BCC_OUT_OF_MEMORY;
+ LOGE("Out of memory when add source module\n");
+ return 1;
+ }
+
return 0;
}
-int Script::linkBC(char const *resName,
- const char *bitcode,
- size_t bitcodeSize,
- unsigned long flags) {
+int Script::addSourceFile(size_t idx,
+ char const *path,
+ unsigned long flags) {
if (mStatus != ScriptStatus::Unknown) {
mErrorCode = BCC_INVALID_OPERATION;
- LOGE("Invalid operation: %s\n", __func__);
+ LOGE("Bad operation: Adding source after bccPrepareExecutable\n");
return 1;
}
- libraryBC = bitcode;
- librarySize = bitcodeSize;
+ if (!path) {
+ mErrorCode = BCC_INVALID_VALUE;
+ LOGE("Invalid argument: path = NULL\n");
+ return 1;
+ }
+
+ struct stat sb;
+ if (stat(path, &sb) != 0) {
+ mErrorCode = BCC_INVALID_VALUE;
+ LOGE("File not found: %s\n", path);
+ return 1;
+ }
+
+ mSourceList[idx] = SourceInfo::createFromFile(path, flags);
+
+ if (!mSourceList[idx]) {
+ mErrorCode = BCC_OUT_OF_MEMORY;
+ LOGE("Out of memory while adding source file\n");
+ return 1;
+ }
+
return 0;
}
@@ -147,16 +199,6 @@
return 1;
}
- // If we are going to use the cache file. We have to calculate sha1sum
- // first (no matter we can open the file now or not.)
- if (sourceBC) {
- calcSHA1(sourceSHA1, sourceBC, sourceSize);
- }
-
- //if (libraryBC) {
- // calcSHA1(librarySHA1, libraryBC, librarySize);
- //}
-
FileHandle file;
if (file.open(mCachePath, OpenMode::Read) < 0) {
@@ -173,14 +215,12 @@
reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
- if (sourceBC) {
- reader.addDependency(BCC_APK_RESOURCE, sourceResName, sourceSHA1);
+ for (size_t i = 0; i < 2; ++i) {
+ if (mSourceList[i]) {
+ mSourceList[i]->introDependency(reader);
+ }
}
- //if (libraryBC) {
- // reader.addDependency(BCC_APK_RESOURCE, libraryResName, librarySHA1);
- //}
-
// Read cache file
ScriptCached *cached = reader.readCacheFile(&file, this);
if (!cached) {
@@ -220,29 +260,31 @@
mpExtSymbolLookupFnContext);
}
- // Setup the source bitcode / module
- if (sourceBC) {
- if (mCompiled->readBC(sourceResName, sourceBC, sourceSize, 0) != 0) {
- LOGE("Unable to readBC, bitcode=%p, size=%lu\n",
- sourceBC, (unsigned long)sourceSize);
+ // Parse Bitcode File (if necessary)
+ for (size_t i = 0; i < 2; ++i) {
+ if (mSourceList[i] && mSourceList[i]->prepareModule(mCompiled) != 0) {
+ LOGE("Unable to parse bitcode for source[%lu]\n", (unsigned long)i);
return 1;
}
- LOGI("Load sourceBC\n");
- } else if (sourceModule) {
- if (mCompiled->readModule(NULL, sourceModule, 0) != 0) {
- return 1;
- }
- LOGI("Load sourceModule\n");
+ }
+
+ // Set the main source module
+ if (!mSourceList[0] || !mSourceList[0]->getModule()) {
+ LOGE("Source bitcode is not setted.\n");
+ return 1;
+ }
+
+ if (mCompiled->readModule(mSourceList[0]->takeModule()) != 0) {
+ LOGE("Unable to read source module\n");
+ return 1;
}
// Link the source module with the library module
- if (librarySize == 1 /* link against file */ ||
- libraryBC /* link against buffer */) {
- if (mCompiled->linkBC(NULL, libraryBC, librarySize, 0) != 0) {
+ if (mSourceList[1]) {
+ if (mCompiled->linkModule(mSourceList[1]->takeModule()) != 0) {
+ LOGE("Unable to link library module\n");
return 1;
}
-
- LOGI("Load Library\n");
}
// Compile and JIT the code
@@ -281,8 +323,8 @@
#endif
writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
- if (sourceBC) {
- writer.addDependency(BCC_APK_RESOURCE, sourceResName, sourceSHA1);
+ for (size_t i = 0; i < 2; ++i) {
+ mSourceList[i]->introDependency(writer);
}
// libRS is threadable dirty hack
diff --git a/lib/bcc/Script.h b/lib/bcc/Script.h
index a8f8c4e..dc115da 100644
--- a/lib/bcc/Script.h
+++ b/lib/bcc/Script.h
@@ -31,6 +31,7 @@
namespace bcc {
class ScriptCompiled;
class ScriptCached;
+ class SourceInfo;
namespace ScriptStatus {
enum StatusType {
@@ -59,18 +60,11 @@
bool mIsContextSlotNotAvail;
- // ReadBC
- char const *sourceBC;
- char const *sourceResName;
- unsigned char sourceSHA1[20];
- size_t sourceSize;
-
- // ReadModule
- llvm::Module *sourceModule;
-
- // LinkBC
- char const *libraryBC;
- size_t librarySize;
+ // Source List
+ SourceInfo *mSourceList[2];
+ // Note: mSourceList[0] (main source)
+ // Note: mSourceList[1] (library source)
+ // TODO(logan): Generalize this, use vector or SmallVector instead!
// Register Symbol Lookup Function
BCCSymbolLookupFn mpExtSymbolLookupFn;
@@ -79,27 +73,28 @@
public:
Script() : mErrorCode(BCC_NO_ERROR), mStatus(ScriptStatus::Unknown),
mCachePath(NULL), mIsContextSlotNotAvail(false),
- sourceBC(NULL), sourceResName(NULL), sourceSize(0),
- sourceModule(NULL), libraryBC(NULL), librarySize(0),
mpExtSymbolLookupFn(NULL), mpExtSymbolLookupFnContext(NULL) {
Compiler::GlobalInitialization();
+
+ mSourceList[0] = NULL;
+ mSourceList[1] = NULL;
}
~Script();
- int readBC(char const *resName,
- const char *bitcode,
- size_t bitcodeSize,
- unsigned long flags);
+ int addSourceBC(size_t idx,
+ char const *resName,
+ const char *bitcode,
+ size_t bitcodeSize,
+ unsigned long flags);
- int readModule(char const *resName,
- llvm::Module *module,
- unsigned long flags);
+ int addSourceModule(size_t idx,
+ llvm::Module *module,
+ unsigned long flags);
- int linkBC(char const *resName,
- const char *bitcode,
- size_t bitcodeSize,
- unsigned long flags);
+ int addSourceFile(size_t idx,
+ char const *path,
+ unsigned long flags);
int prepareExecutable(char const *cachePath, unsigned long flags);
diff --git a/lib/bcc/ScriptCompiled.h b/lib/bcc/ScriptCompiled.h
index 0e5c9fc..d2c7773 100644
--- a/lib/bcc/ScriptCompiled.h
+++ b/lib/bcc/ScriptCompiled.h
@@ -66,24 +66,16 @@
~ScriptCompiled();
- int readBC(char const *resName,
- char const *bitcode,
- size_t bitcodeSize,
- unsigned long flags) {
- return mCompiler.readBC(bitcode, bitcodeSize);
+ llvm::Module *parseBitcodeFile(llvm::MemoryBuffer *MEM) {
+ return mCompiler.parseBitcodeFile(MEM);
}
- int readModule(char const *resName,
- llvm::Module *module,
- unsigned long flags) {
+ int readModule(llvm::Module *module) {
return mCompiler.readModule(module);
}
- int linkBC(char const *resName,
- char const *bitcode,
- size_t bitcodeSize,
- unsigned long flags) {
- return mCompiler.linkBC(bitcode, bitcodeSize);
+ int linkModule(llvm::Module *module) {
+ return mCompiler.linkModule(module);
}
int compile() {
diff --git a/lib/bcc/SourceInfo.cpp b/lib/bcc/SourceInfo.cpp
new file mode 100644
index 0000000..fb63cf4
--- /dev/null
+++ b/lib/bcc/SourceInfo.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2010, 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_TAG "bcc"
+#include <cutils/log.h>
+
+#include "SourceInfo.h"
+
+#if USE_CACHE
+#include "CacheReader.h"
+#include "CacheWriter.h"
+#endif
+
+#include "ScriptCompiled.h"
+#include "Sha1Helper.h"
+
+#include <bcc/bcc.h>
+#include <bcc/bcc_cache.h>
+
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/MemoryBuffer.h>
+
+#include <stddef.h>
+#include <string.h>
+
+namespace bcc {
+
+
+SourceInfo *SourceInfo::createFromBuffer(char const *resName,
+ char const *bitcode,
+ size_t bitcodeSize,
+ unsigned long flags) {
+ SourceInfo *result = new SourceInfo();
+
+ if (!result) {
+ return NULL;
+ }
+
+ result->type = SourceKind::Buffer;
+ result->buffer.resName = resName;
+ result->buffer.bitcode = bitcode;
+ result->buffer.bitcodeSize = bitcodeSize;
+ result->flags = flags;
+
+#if USE_CACHE
+ if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) {
+ result->flags |= BCC_SKIP_DEP_SHA1;
+
+ LOGW("It is required to give resName for sha1 dependency check.\n");
+ LOGW("Sha1sum dependency check will be skipped.\n");
+ LOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
+ }
+
+ if (result->flags & BCC_SKIP_DEP_SHA1) {
+ memset(result->sha1, '\0', 20);
+ } else {
+ calcSHA1(result->sha1, bitcode, bitcodeSize);
+ }
+#endif
+
+ return result;
+}
+
+
+SourceInfo *SourceInfo::createFromFile(char const *path,
+ unsigned long flags) {
+ SourceInfo *result = new SourceInfo();
+
+ if (!result) {
+ return NULL;
+ }
+
+ result->type = SourceKind::File;
+ result->file.path = path;
+ result->flags = flags;
+
+#if USE_CACHE
+ memset(result->sha1, '\0', 20);
+
+ if (!(result->flags & BCC_SKIP_DEP_SHA1)) {
+ calcFileSHA1(result->sha1, path);
+ }
+#endif
+
+ return result;
+}
+
+
+SourceInfo *SourceInfo::createFromModule(llvm::Module *module,
+ unsigned long flags) {
+ SourceInfo *result = new SourceInfo();
+
+ if (!result) {
+ return NULL;
+ }
+
+ result->type = SourceKind::Module;
+ result->module.reset(module);
+ result->flags = flags;
+
+#if USE_CACHE
+ if (! (flags & BCC_SKIP_DEP_SHA1)) {
+ result->flags |= BCC_SKIP_DEP_SHA1;
+
+ LOGW("Unable to calculate sha1sum for llvm::Module.\n");
+ LOGW("Sha1sum dependency check will be skipped.\n");
+ LOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
+ }
+
+ memset(result->sha1, '\0', 20);
+#endif
+
+ return result;
+}
+
+
+int SourceInfo::prepareModule(ScriptCompiled *SC) {
+ switch (type) {
+ case SourceKind::Buffer:
+ {
+ llvm::OwningPtr<llvm::MemoryBuffer> MEM(
+ llvm::MemoryBuffer::getMemBuffer(
+ llvm::StringRef(buffer.bitcode, buffer.bitcodeSize)));
+
+ if (!MEM.get()) {
+ LOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
+ buffer.bitcode, (unsigned long)buffer.bitcodeSize);
+ return 1;
+ }
+
+ module.reset(SC->parseBitcodeFile(MEM.get()));
+ }
+ break;
+
+ case SourceKind::File:
+ {
+ llvm::OwningPtr<llvm::MemoryBuffer> MEM(
+ llvm::MemoryBuffer::getFile(file.path));
+
+ if (!MEM.get()) {
+ LOGE("Unable to MemoryBuffer::getFile(path=%s)\n", file.path);
+ return 1;
+ }
+
+ module.reset(SC->parseBitcodeFile(MEM.get()));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return (module.get()) ? 0 : 1;
+}
+
+
+#if USE_CACHE
+template <typename T> void SourceInfo::introDependency(T &checker) {
+ if (flags & BCC_SKIP_DEP_SHA1) {
+ return;
+ }
+
+ switch (type) {
+ case SourceKind::Buffer:
+ checker.addDependency(BCC_APK_RESOURCE, buffer.resName, sha1);
+ break;
+
+ case SourceKind::File:
+ checker.addDependency(BCC_FILE_RESOURCE, file.path, sha1);
+ break;
+
+ default:
+ break;
+ }
+}
+
+template void SourceInfo::introDependency<CacheReader>(CacheReader &);
+template void SourceInfo::introDependency<CacheWriter>(CacheWriter &);
+#endif // USE_CACHE
+
+
+} // namespace bcc
diff --git a/lib/bcc/SourceInfo.h b/lib/bcc/SourceInfo.h
new file mode 100644
index 0000000..b6a4c54
--- /dev/null
+++ b/lib/bcc/SourceInfo.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2010, 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_SOURCEINFO_H
+#define BCC_SOURCEINFO_H
+
+#include "Config.h"
+
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/Module.h>
+
+#include <stddef.h>
+
+namespace bcc {
+ class ScriptCompiled;
+
+ namespace SourceKind {
+ enum SourceType {
+ File,
+ Buffer,
+ Module,
+ };
+ }
+
+ class SourceInfo {
+ private:
+ SourceKind::SourceType type;
+
+ llvm::OwningPtr<llvm::Module> module;
+ // Note: module should not be a part of union. Since, we are going to
+ // use module to store the pointer to parsed bitcode.
+
+ union {
+ struct {
+ char const *resName;
+ char const *bitcode;
+ size_t bitcodeSize;
+ } buffer;
+
+ struct {
+ char const *path;
+ } file;
+ };
+
+ unsigned long flags;
+
+#if USE_CACHE
+ unsigned char sha1[20];
+#endif
+
+ private:
+ SourceInfo() { }
+
+ public:
+ static SourceInfo *createFromBuffer(char const *resName,
+ char const *bitcode,
+ size_t bitcodeSize,
+ unsigned long flags);
+
+ static SourceInfo *createFromFile(char const *path,
+ unsigned long flags);
+
+ static SourceInfo *createFromModule(llvm::Module *module,
+ unsigned long flags);
+
+ llvm::Module *takeModule() {
+ return module.take();
+ }
+
+ llvm::Module *getModule() const {
+ return module.get();
+ }
+
+ int prepareModule(ScriptCompiled *);
+
+#if USE_CACHE
+ template <typename T> void introDependency(T &checker);
+#endif
+ };
+
+
+} // namespace bcc
+
+#endif // BCC_SOURCEINFO_H
diff --git a/lib/bcc/bcc.cpp b/lib/bcc/bcc.cpp
index d98c0f8..e6972fe 100644
--- a/lib/bcc/bcc.cpp
+++ b/lib/bcc/bcc.cpp
@@ -83,23 +83,30 @@
return unwrap(script)->getError();
}
-
extern "C" int bccReadBC(BCCScriptRef script,
char const *resName,
char const *bitcode,
size_t bitcodeSize,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->readBC(resName, bitcode, bitcodeSize, flags);
+ return unwrap(script)->addSourceBC(0, resName, bitcode, bitcodeSize, flags);
}
extern "C" int bccReadModule(BCCScriptRef script,
- char const *resName,
+ char const *resName /* deprecated */,
LLVMModuleRef module,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->readModule(resName, unwrap(module), flags);
+ return unwrap(script)->addSourceModule(0, unwrap(module), flags);
+}
+
+
+extern "C" int bccReadFile(BCCScriptRef script,
+ char const *path,
+ unsigned long flags) {
+ BCC_FUNC_LOGGER();
+ return unwrap(script)->addSourceFile(0, path, flags);
}
@@ -109,7 +116,15 @@
size_t bitcodeSize,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->linkBC(resName, bitcode, bitcodeSize, flags);
+ return unwrap(script)->addSourceBC(1, resName, bitcode, bitcodeSize, flags);
+}
+
+
+extern "C" int bccLinkFile(BCCScriptRef script,
+ char const *path,
+ unsigned long flags) {
+ BCC_FUNC_LOGGER();
+ return unwrap(script)->addSourceFile(1, path, flags);
}