Switch to use RSCompilerDriver.
This commit is large. It does:
1. Clean-up RSScript. ScriptCached and ScriptCompiled are removed.
2. Switch to use CompilerConfig.
3. Switch to use RSInfo. MCCacheReader and MCCacheWriter are removed.
4. Update C API implementation of libbcc (i.e., bcc.cpp). Note that
it'll be completely removed once there's no clients relying on it.
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index f9877d5..8c78cd0 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -34,10 +34,10 @@
GDBJITRegistrar.cpp \
Initialization.cpp \
InputFile.cpp \
- MCCacheWriter.cpp \
- MCCacheReader.cpp \
ObjectLoader.cpp \
OutputFile.cpp \
+ RSCompiler.cpp \
+ RSCompilerDriver.cpp \
RSExecutable.cpp \
RSForEachExpand.cpp \
RSInfo.cpp \
@@ -47,8 +47,6 @@
RSScript.cpp \
BCCRuntimeStub.c \
Script.cpp \
- ScriptCached.cpp \
- ScriptCompiled.cpp \
Sha1Helper.cpp \
Source.cpp \
SymbolResolverProxy.cpp \
diff --git a/lib/ExecutionEngine/BCCContext.cpp b/lib/ExecutionEngine/BCCContext.cpp
index 892fd5a..62995ed 100644
--- a/lib/ExecutionEngine/BCCContext.cpp
+++ b/lib/ExecutionEngine/BCCContext.cpp
@@ -19,7 +19,6 @@
#include <new>
#include "BCCContextImpl.h"
-#include "Compiler.h"
#include "DebugHelper.h"
#include "Source.h"
@@ -42,10 +41,7 @@
GlobalContext = NULL;
}
-BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) {
- // Initialize the LLVM compiler infrastructure.
- Compiler::GlobalInitialization();
-}
+BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) { }
BCCContext::~BCCContext() {
delete mImpl;
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index 458d835..2348d56 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -16,656 +16,367 @@
#include "Compiler.h"
-#include "Config.h"
-#include <bcinfo/MetadataExtractor.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/CodeGen/RegAllocRegistry.h>
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Target/TargetMachine.h>
+#include <llvm/Transforms/IPO.h>
+#include <llvm/Transforms/Scalar.h>
-#if USE_DISASSEMBLER
-#include "Disassembler/Disassembler.h"
-#endif
-
-#include "BCCRuntimeSymbolResolver.h"
+#include "CompilerConfig.h"
#include "DebugHelper.h"
-#include "ScriptCompiled.h"
-#include "Sha1Helper.h"
-#include "CompilerOption.h"
-#include "SymbolResolverProxy.h"
-#include "SymbolResolvers.h"
+#include "OutputFile.h"
+#include "Script.h"
+#include "Source.h"
-#include "librsloader.h"
+using namespace bcc;
-#include "RSTransforms.h"
+const char *Compiler::GetErrorString(enum ErrorCode pErrCode) {
+ static const char *ErrorString[] = {
+ /* kSuccess */
+ "Successfully compiled.",
+ /* kInvalidConfigNoTarget */
+ "Invalid compiler config supplied (getTarget() returns NULL.) "
+ "(missing call to CompilerConfig::initialize()?)",
+ /* kErrCreateTargetMachine */
+ "Failed to create llvm::TargetMachine.",
+ /* kErrSwitchTargetMachine */
+ "Failed to switch llvm::TargetMachine.",
+ /* kErrNoTargetMachine */
+ "Failed to compile the script since there's no available TargetMachine."
+ " (missing call to Compiler::config()?)",
+ /* kErrTargetDataNoMemory */
+ "Out of memory when create TargetData during compilation.",
+ /* kErrMaterialization */
+ "Failed to materialize the module.",
+ /* kErrInvalidOutputFileState */
+ "Supplied output file was invalid (in the error state.)",
+ /* kErrPrepareOutput */
+ "Failed to prepare file for output.",
+ /* kPrepareCodeGenPass */
+ "Failed to construct pass list for code-generation.",
-#include "llvm/ADT/StringRef.h"
+ /* kErrHookBeforeAddLTOPasses */
+ "Error occurred during beforeAddLTOPasses() in subclass.",
+ /* kErrHookAfterAddLTOPasses */
+ "Error occurred during afterAddLTOPasses() in subclass.",
+ /* kErrHookBeforeExecuteLTOPasses */
+ "Error occurred during beforeExecuteLTOPasses() in subclass.",
+ /* kErrHookAfterExecuteLTOPasses */
+ "Error occurred during afterExecuteLTOPasses() in subclass.",
-#include "llvm/Analysis/Passes.h"
+ /* kErrHookBeforeAddCodeGenPasses */
+ "Error occurred during beforeAddCodeGenPasses() in subclass.",
+ /* kErrHookAfterAddCodeGenPasses */
+ "Error occurred during afterAddCodeGenPasses() in subclass.",
+ /* kErrHookBeforeExecuteCodeGenPasses */
+ "Error occurred during beforeExecuteCodeGenPasses() in subclass.",
+ /* kErrHookAfterExecuteCodeGenPasses */
+ "Error occurred during afterExecuteCodeGenPasses() in subclass.",
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/RegAllocRegistry.h"
-#include "llvm/CodeGen/SchedulerRegistry.h"
+ /* kMaxErrorCode */
+ "(Unknown error code)"
+ };
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/SubtargetFeature.h"
-
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/Scalar.h"
-
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include "llvm/Constants.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/Linker.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Module.h"
-#include "llvm/PassManager.h"
-#include "llvm/Type.h"
-#include "llvm/Value.h"
-
-#include <errno.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string.h>
-
-#include <algorithm>
-#include <iterator>
-#include <string>
-#include <vector>
-
-extern char* gDebugDumpDirectory;
-
-namespace bcc {
-
-//////////////////////////////////////////////////////////////////////////////
-// BCC Compiler Static Variables
-//////////////////////////////////////////////////////////////////////////////
-
-bool Compiler::GlobalInitialized = false;
-
-
-#if !defined(__HOST__)
- #define TARGET_TRIPLE_STRING DEFAULT_TARGET_TRIPLE_STRING
-#else
-// In host TARGET_TRIPLE_STRING is a variable to allow cross-compilation.
- #if defined(__cplusplus)
- extern "C" {
- #endif
- char *TARGET_TRIPLE_STRING = (char*)DEFAULT_TARGET_TRIPLE_STRING;
- #if defined(__cplusplus)
- };
- #endif
-#endif
-
-// Code generation optimization level for the compiler
-llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
-
-std::string Compiler::Triple;
-llvm::Triple::ArchType Compiler::ArchType;
-
-std::string Compiler::CPU;
-
-std::vector<std::string> Compiler::Features;
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Compiler
-//////////////////////////////////////////////////////////////////////////////
-
-void Compiler::GlobalInitialization() {
- if (GlobalInitialized) {
- return;
+ if (pErrCode > kMaxErrorCode) {
+ pErrCode = kMaxErrorCode;
}
-#if defined(PROVIDE_ARM_CODEGEN)
- LLVMInitializeARMAsmPrinter();
- LLVMInitializeARMTargetMC();
- LLVMInitializeARMTargetInfo();
- LLVMInitializeARMTarget();
-#endif
-
-#if defined(PROVIDE_MIPS_CODEGEN)
- LLVMInitializeMipsAsmPrinter();
- LLVMInitializeMipsTargetMC();
- LLVMInitializeMipsTargetInfo();
- LLVMInitializeMipsTarget();
-#endif
-
-#if defined(PROVIDE_X86_CODEGEN)
- LLVMInitializeX86AsmPrinter();
- LLVMInitializeX86TargetMC();
- LLVMInitializeX86TargetInfo();
- LLVMInitializeX86Target();
-#endif
-
-#if USE_DISASSEMBLER
- InitializeDisassembler();
-#endif
-
- // if (!llvm::llvm_is_multithreaded())
- // llvm::llvm_start_multithreaded();
-
- // Set Triple, CPU and Features here
- Triple = TARGET_TRIPLE_STRING;
-
- // Determine ArchType
-#if defined(__HOST__)
- {
- std::string Err;
- llvm::Target const *Target = llvm::TargetRegistry::lookupTarget(Triple, Err);
- if (Target != NULL) {
- ArchType = llvm::Triple::getArchTypeForLLVMName(Target->getName());
- } else {
- ArchType = llvm::Triple::UnknownArch;
- ALOGE("%s", Err.c_str());
- }
- }
-#elif defined(DEFAULT_ARM_CODEGEN)
- ArchType = llvm::Triple::arm;
-#elif defined(DEFAULT_MIPS_CODEGEN)
- ArchType = llvm::Triple::mipsel;
-#elif defined(DEFAULT_X86_CODEGEN)
- ArchType = llvm::Triple::x86;
-#elif defined(DEFAULT_X86_64_CODEGEN)
- ArchType = llvm::Triple::x86_64;
-#else
- ArchType = llvm::Triple::UnknownArch;
-#endif
-
- if ((ArchType == llvm::Triple::arm) || (ArchType == llvm::Triple::thumb)) {
-# if defined(ARCH_ARM_HAVE_VFP)
- Features.push_back("+vfp3");
-# if !defined(ARCH_ARM_HAVE_VFP_D32)
- Features.push_back("+d16");
-# endif
-# endif
-
-# if defined(ARCH_ARM_HAVE_NEON)
- Features.push_back("+neon");
- Features.push_back("+neonfp");
-# else
- Features.push_back("-neon");
- Features.push_back("-neonfp");
-# endif
-
-// FIXME(all): Turn NEON back on after debugging the rebase.
-# if 1 || defined(DISABLE_ARCH_ARM_HAVE_NEON)
- Features.push_back("-neon");
- Features.push_back("-neonfp");
-# endif
- }
-
- // Register the scheduler
- llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
-
- // Read in SHA1 checksum of libbcc and libRS.
- readSHA1(sha1LibBCC_SHA1, sizeof(sha1LibBCC_SHA1), pathLibBCC_SHA1);
-
- calcFileSHA1(sha1LibRS, pathLibRS);
-
- GlobalInitialized = true;
+ return ErrorString[ static_cast<size_t>(pErrCode) ];
}
-
-void Compiler::LLVMErrorHandler(void *UserData, const std::string &Message) {
- std::string *Error = static_cast<std::string*>(UserData);
- Error->assign(Message);
- ALOGE("%s", Message.c_str());
- exit(1);
-}
-
-
-Compiler::Compiler(ScriptCompiled *result)
- : mpResult(result),
- mRSExecutable(NULL),
- mpSymbolLookupFn(NULL),
- mpSymbolLookupContext(NULL),
- mModule(NULL) {
- llvm::remove_fatal_error_handler();
- llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
+//===----------------------------------------------------------------------===//
+// Instance Methods
+//===----------------------------------------------------------------------===//
+Compiler::Compiler() : mTarget(NULL), mEnableLTO(true) {
return;
}
-int Compiler::readModule(llvm::Module &pModule) {
- mModule = &pModule;
- if (pModule.getMaterializer() != NULL) {
- // A module with non-null materializer means that it is a lazy-load module.
- // Materialize it now via invoking MaterializeAllPermanently(). This
- // function returns false when the materialization is successful.
- if (pModule.MaterializeAllPermanently(&mError)) {
- setError("Failed to materialize the module `" +
- pModule.getModuleIdentifier() + "'! (" + mError + ")");
- mModule = NULL;
- }
+Compiler::Compiler(const CompilerConfig &pConfig) : mTarget(NULL),
+ mEnableLTO(true) {
+ const std::string &triple = pConfig.getTriple();
+
+ enum ErrorCode err = config(pConfig);
+ if (err != kSuccess) {
+ ALOGE("%s (%s, features: %s)", GetErrorString(err),
+ triple.c_str(), pConfig.getFeatureString().c_str());
+ return;
}
- return hasError();
+
+ return;
}
-int Compiler::compile(const CompilerOption &option) {
- llvm::Target const *Target = NULL;
- llvm::TargetData *TD = NULL;
- llvm::TargetMachine *TM = NULL;
-
- std::string FeaturesStr;
-
- if (mModule == NULL) // No module was loaded
- return 0;
-
- bcinfo::MetadataExtractor ME(mModule);
- ME.extract();
-
- size_t VarCount = ME.getExportVarCount();
- size_t FuncCount = ME.getExportFuncCount();
- size_t ForEachSigCount = ME.getExportForEachSignatureCount();
- size_t ObjectSlotCount = ME.getObjectSlotCount();
- size_t PragmaCount = ME.getPragmaCount();
-
- std::vector<std::string> &VarNameList = mpResult->mExportVarsName;
- std::vector<std::string> &FuncNameList = mpResult->mExportFuncsName;
- std::vector<std::string> &ForEachExpandList = mpResult->mExportForEachName;
- RSInfo::ExportForeachFuncListTy ForEachFuncList;
- std::vector<const char*> ExportSymbols;
-
- // Defaults to maximum optimization level from MetadataExtractor.
- uint32_t OptimizationLevel = ME.getOptimizationLevel();
-
- if (OptimizationLevel == 0) {
- CodeGenOptLevel = llvm::CodeGenOpt::None;
- } else if (OptimizationLevel == 1) {
- CodeGenOptLevel = llvm::CodeGenOpt::Less;
- } else if (OptimizationLevel == 2) {
- CodeGenOptLevel = llvm::CodeGenOpt::Default;
- } else if (OptimizationLevel == 3) {
- CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
+enum Compiler::ErrorCode Compiler::config(const CompilerConfig &pConfig) {
+ if (pConfig.getTarget() == NULL) {
+ return kInvalidConfigNoTarget;
}
- // not the best place for this, but we need to set the register allocation
- // policy after we read the optimization_level metadata from the bitcode
+ llvm::TargetMachine *new_target =
+ (pConfig.getTarget())->createTargetMachine(pConfig.getTriple(),
+ pConfig.getCPU(),
+ pConfig.getFeatureString(),
+ pConfig.getTargetOptions(),
+ pConfig.getRelocationModel(),
+ pConfig.getCodeModel(),
+ pConfig.getOptimizationLevel());
- // Register allocation policy:
+ if (new_target == NULL) {
+ return ((mTarget != NULL) ? kErrSwitchTargetMachine :
+ kErrCreateTargetMachine);
+ }
+
+ // Replace the old TargetMachine.
+ delete mTarget;
+ mTarget = new_target;
+
+ // Adjust register allocation policy according to the optimization level.
// createFastRegisterAllocator: fast but bad quality
// createLinearScanRegisterAllocator: not so fast but good quality
- llvm::RegisterRegAlloc::setDefault
- ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
- llvm::createFastRegisterAllocator :
- llvm::createGreedyRegisterAllocator);
-
- // Find LLVM Target
- Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
- if (hasError())
- goto on_bcc_compile_error;
-
-#if defined(ARCH_ARM_HAVE_NEON)
- // Full-precision means we have to disable NEON
- if (ME.getRSFloatPrecision() == bcinfo::RS_FP_Full) {
- Features.push_back("-neon");
- Features.push_back("-neonfp");
- }
-#endif
-
- if (!CPU.empty() || !Features.empty()) {
- llvm::SubtargetFeatures F;
-
- for (std::vector<std::string>::const_iterator
- I = Features.begin(), E = Features.end(); I != E; I++) {
- F.AddFeature(*I);
- }
-
- FeaturesStr = F.getString();
+ if ((pConfig.getOptimizationLevel() == llvm::CodeGenOpt::None)) {
+ llvm::RegisterRegAlloc::setDefault(llvm::createFastRegisterAllocator);
+ } else {
+ llvm::RegisterRegAlloc::setDefault(llvm::createGreedyRegisterAllocator);
}
- // Create LLVM Target Machine
- TM = Target->createTargetMachine(Triple, CPU, FeaturesStr,
- option.TargetOpt,
- option.RelocModelOpt,
- option.CodeModelOpt);
+ // Relax all machine instructions.
+ mTarget->setMCRelaxAll(true);
- if (TM == NULL) {
- setError("Failed to create target machine implementation for the"
- " specified triple '" + Triple + "'");
- goto on_bcc_compile_error;
- }
-
- // Get target data from Module
- TD = new llvm::TargetData(mModule);
-
- // Read pragma information from MetadataExtractor
- if (PragmaCount) {
- ScriptCompiled::PragmaList &PragmaPairs = mpResult->mPragmas;
- const char **PragmaKeys = ME.getPragmaKeyList();
- const char **PragmaValues = ME.getPragmaValueList();
- for (size_t i = 0; i < PragmaCount; i++) {
- PragmaPairs.push_back(std::make_pair(PragmaKeys[i], PragmaValues[i]));
- }
- }
-
- if (VarCount) {
- const char **VarNames = ME.getExportVarNameList();
- for (size_t i = 0; i < VarCount; i++) {
- VarNameList.push_back(VarNames[i]);
- ExportSymbols.push_back(VarNames[i]);
- }
- }
-
- if (FuncCount) {
- const char **FuncNames = ME.getExportFuncNameList();
- for (size_t i = 0; i < FuncCount; i++) {
- FuncNameList.push_back(FuncNames[i]);
- ExportSymbols.push_back(FuncNames[i]);
- }
- }
-
- if (ForEachSigCount) {
- const char **ForEachNames = ME.getExportForEachNameList();
- const uint32_t *ForEachSigs = ME.getExportForEachSignatureList();
- for (size_t i = 0; i < ForEachSigCount; i++) {
- ForEachFuncList.push_back(std::make_pair(ForEachNames[i],
- ForEachSigs[i]));
- ForEachExpandList.push_back(std::string(ForEachNames[i]) + ".expand");
- }
-
- // Need to wait until ForEachExpandList is fully populated to fill in
- // exported symbols.
- for (size_t i = 0; i < ForEachSigCount; i++) {
- ExportSymbols.push_back(ForEachExpandList[i].c_str());
- }
- }
-
- if (ObjectSlotCount) {
- ScriptCompiled::ObjectSlotList &objectSlotList = mpResult->mObjectSlots;
- const uint32_t *ObjectSlots = ME.getObjectSlotList();
- for (size_t i = 0; i < ObjectSlotCount; i++) {
- objectSlotList.push_back(ObjectSlots[i]);
- }
- }
-
- runInternalPasses(ForEachFuncList);
-
- // Perform link-time optimization if we have multiple modules
- if (option.RunLTO) {
- runLTO(new llvm::TargetData(*TD), ExportSymbols, CodeGenOptLevel);
- }
-
- // Perform code generation
- if (runMCCodeGen(new llvm::TargetData(*TD), TM) != 0) {
- goto on_bcc_compile_error;
- }
-
- if (!option.LoadAfterCompile)
- return 0;
-
- // Load the ELF Object
- {
- BCCRuntimeSymbolResolver BCCRuntimesResolver;
- LookupFunctionSymbolResolver<void*> RSSymbolResolver(mpSymbolLookupFn,
- mpSymbolLookupContext);
-
- SymbolResolverProxy Resolver;
- Resolver.chainResolver(BCCRuntimesResolver);
- Resolver.chainResolver(RSSymbolResolver);
-
- mRSExecutable =
- rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(),
- mEmittedELFExecutable.size(),
- SymbolResolverProxy::LookupFunction, &Resolver);
- }
-
- if (!mRSExecutable) {
- setError("Fail to load emitted ELF relocatable file");
- goto on_bcc_compile_error;
- }
-
- rsloaderUpdateSectionHeaders(mRSExecutable,
- (unsigned char*) mEmittedELFExecutable.begin());
-
- // Once the ELF object has been loaded, populate the various slots for RS
- // with the appropriate relocated addresses.
- if (VarCount) {
- ScriptCompiled::ExportVarList &VarList = mpResult->mExportVars;
- for (size_t i = 0; i < VarCount; i++) {
- VarList.push_back(rsloaderGetSymbolAddress(mRSExecutable,
- VarNameList[i].c_str()));
- }
- }
-
- if (FuncCount) {
- ScriptCompiled::ExportFuncList &FuncList = mpResult->mExportFuncs;
- for (size_t i = 0; i < FuncCount; i++) {
- FuncList.push_back(rsloaderGetSymbolAddress(mRSExecutable,
- FuncNameList[i].c_str()));
- }
- }
-
- if (ForEachSigCount) {
- ScriptCompiled::ExportForEachList &ForEachList = mpResult->mExportForEach;
- for (size_t i = 0; i < ForEachSigCount; i++) {
- ForEachList.push_back(rsloaderGetSymbolAddress(mRSExecutable,
- ForEachExpandList[i].c_str()));
- }
- }
-
-#if DEBUG_MC_DISASSEMBLER
- {
- // Get MC codegen emitted function name list
- size_t func_list_size = rsloaderGetFuncCount(mRSExecutable);
- std::vector<char const *> func_list(func_list_size, NULL);
- rsloaderGetFuncNameList(mRSExecutable, func_list_size, &*func_list.begin());
-
- // Disassemble each function
- for (size_t i = 0; i < func_list_size; ++i) {
- void *func = rsloaderGetSymbolAddress(mRSExecutable, func_list[i]);
- if (func) {
- size_t size = rsloaderGetSymbolSize(mRSExecutable, func_list[i]);
- Disassemble(DEBUG_MC_DISASSEMBLER_FILE,
- Target, TM, func_list[i], (unsigned char const *)func, size);
- }
- }
- }
-#endif
-
-on_bcc_compile_error:
- // ALOGE("on_bcc_compiler_error");
- if (TD) {
- delete TD;
- }
-
- if (TM) {
- delete TM;
- }
-
- if (mError.empty()) {
- return 0;
- }
-
- // ALOGE(getErrorMessage());
- return 1;
+ return kSuccess;
}
+Compiler::~Compiler() {
+ delete mTarget;
+}
-int Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM) {
- // Decorate mEmittedELFExecutable with formatted ostream
- llvm::raw_svector_ostream OutSVOS(mEmittedELFExecutable);
+enum Compiler::ErrorCode Compiler::runLTO(Script &pScript) {
+ llvm::TargetData *target_data = NULL;
- // Relax all machine instructions
- TM->setMCRelaxAll(/* RelaxAll= */ true);
+ // Pass manager for link-time optimization
+ llvm::PassManager lto_passes;
- // Create MC code generation pass manager
- llvm::PassManager MCCodeGenPasses;
-
- // Add TargetData to MC code generation pass manager
- MCCodeGenPasses.add(TD);
-
- // Add MC code generation passes to pass manager
- llvm::MCContext *Ctx = NULL;
- if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS, false)) {
- setError("Fail to add passes to emit file");
- return 1;
+ // Prepare TargetData target data from Module
+ target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData());
+ if (target_data == NULL) {
+ return kErrTargetDataNoMemory;
}
- MCCodeGenPasses.run(*mModule);
- OutSVOS.flush();
- return 0;
-}
+ // Add TargetData to the pass manager.
+ lto_passes.add(target_data);
-int Compiler::runInternalPasses(RSInfo::ExportForeachFuncListTy pForEachFuncs) {
- llvm::PassManager BCCPasses;
-
- // Expand ForEach on CPU path to reduce launch overhead.
- BCCPasses.add(createRSForEachExpandPass(pForEachFuncs));
-
- BCCPasses.run(*mModule);
-
- return 0;
-}
-
-int Compiler::runLTO(llvm::TargetData *TD,
- std::vector<const char*>& ExportSymbols,
- llvm::CodeGenOpt::Level OptimizationLevel) {
- // Note: ExportSymbols is a workaround for getting all exported variable,
- // function, and kernel names.
- // We should refine it soon.
-
- // TODO(logan): Remove this after we have finished the
- // bccMarkExternalSymbol API.
-
- // root(), init(), and .rs.dtor() are born to be exported
- ExportSymbols.push_back("root");
- ExportSymbols.push_back("init");
- ExportSymbols.push_back(".rs.dtor");
-
- // User-defined exporting symbols
- std::vector<char const *> const &UserDefinedExternalSymbols =
- mpResult->getUserDefinedExternalSymbols();
-
- std::copy(UserDefinedExternalSymbols.begin(),
- UserDefinedExternalSymbols.end(),
- std::back_inserter(ExportSymbols));
-
- llvm::PassManager LTOPasses;
-
- // Add TargetData to LTO passes
- LTOPasses.add(TD);
+ // Invokde "beforeAddLTOPasses" before adding the first pass.
+ if (!beforeAddLTOPasses(pScript, lto_passes)) {
+ return kErrHookBeforeAddLTOPasses;
+ }
// We now create passes list performing LTO. These are copied from
- // (including comments) llvm::createStandardLTOPasses().
- // Only a subset of these LTO passes are enabled in optimization level 0
- // as they interfere with interactive debugging.
- // FIXME: figure out which passes (if any) makes sense for levels 1 and 2
-
- if (OptimizationLevel != llvm::CodeGenOpt::None) {
- // Internalize all other symbols not listed in ExportSymbols
- LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
-
+ // (including comments) llvm::PassManagerBuilder::populateLTOPassManager().
+ // Only a subset of these LTO passes are enabled in optimization level 0 as
+ // they interfere with interactive debugging.
+ //
+ // FIXME: Figure out which passes (if any) makes sense for levels 1 and 2.
+ //if ( != llvm::CodeGenOpt::None) {
+ if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) {
+ lto_passes.add(llvm::createGlobalOptimizerPass());
+ lto_passes.add(llvm::createConstantMergePass());
+ } else {
// Propagate constants at call sites into the functions they call. This
// opens opportunities for globalopt (and inlining) by substituting
// function pointers passed as arguments to direct uses of functions.
- LTOPasses.add(llvm::createIPSCCPPass());
+ lto_passes.add(llvm::createIPSCCPPass());
// Now that we internalized some globals, see if we can hack on them!
- LTOPasses.add(llvm::createGlobalOptimizerPass());
+ lto_passes.add(llvm::createGlobalOptimizerPass());
// Linking modules together can lead to duplicated global constants, only
// keep one copy of each constant...
- LTOPasses.add(llvm::createConstantMergePass());
+ lto_passes.add(llvm::createConstantMergePass());
// Remove unused arguments from functions...
- LTOPasses.add(llvm::createDeadArgEliminationPass());
+ lto_passes.add(llvm::createDeadArgEliminationPass());
// Reduce the code after globalopt and ipsccp. Both can open up
// significant simplification opportunities, and both can propagate
// functions through function pointers. When this happens, we often have
// to resolve varargs calls, etc, so let instcombine do this.
- LTOPasses.add(llvm::createInstructionCombiningPass());
+ lto_passes.add(llvm::createInstructionCombiningPass());
// Inline small functions
- LTOPasses.add(llvm::createFunctionInliningPass());
+ lto_passes.add(llvm::createFunctionInliningPass());
// Remove dead EH info.
- LTOPasses.add(llvm::createPruneEHPass());
+ lto_passes.add(llvm::createPruneEHPass());
// Internalize the globals again after inlining
- LTOPasses.add(llvm::createGlobalOptimizerPass());
+ lto_passes.add(llvm::createGlobalOptimizerPass());
// Remove dead functions.
- LTOPasses.add(llvm::createGlobalDCEPass());
+ lto_passes.add(llvm::createGlobalDCEPass());
// If we didn't decide to inline a function, check to see if we can
// transform it to pass arguments by value instead of by reference.
- LTOPasses.add(llvm::createArgumentPromotionPass());
+ lto_passes.add(llvm::createArgumentPromotionPass());
// The IPO passes may leave cruft around. Clean up after them.
- LTOPasses.add(llvm::createInstructionCombiningPass());
- LTOPasses.add(llvm::createJumpThreadingPass());
+ lto_passes.add(llvm::createInstructionCombiningPass());
+ lto_passes.add(llvm::createJumpThreadingPass());
// Break up allocas
- LTOPasses.add(llvm::createScalarReplAggregatesPass());
+ lto_passes.add(llvm::createScalarReplAggregatesPass());
// Run a few AA driven optimizations here and now, to cleanup the code.
- LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
- LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
+ lto_passes.add(llvm::createFunctionAttrsPass()); // Add nocapture.
+ lto_passes.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
// Hoist loop invariants.
- LTOPasses.add(llvm::createLICMPass());
+ lto_passes.add(llvm::createLICMPass());
// Remove redundancies.
- LTOPasses.add(llvm::createGVNPass());
+ lto_passes.add(llvm::createGVNPass());
// Remove dead memcpys.
- LTOPasses.add(llvm::createMemCpyOptPass());
+ lto_passes.add(llvm::createMemCpyOptPass());
// Nuke dead stores.
- LTOPasses.add(llvm::createDeadStoreEliminationPass());
+ lto_passes.add(llvm::createDeadStoreEliminationPass());
// Cleanup and simplify the code after the scalar optimizations.
- LTOPasses.add(llvm::createInstructionCombiningPass());
+ lto_passes.add(llvm::createInstructionCombiningPass());
- LTOPasses.add(llvm::createJumpThreadingPass());
+ lto_passes.add(llvm::createJumpThreadingPass());
// Delete basic blocks, which optimization passes may have killed.
- LTOPasses.add(llvm::createCFGSimplificationPass());
+ lto_passes.add(llvm::createCFGSimplificationPass());
// Now that we have optimized the program, discard unreachable functions.
- LTOPasses.add(llvm::createGlobalDCEPass());
-
- } else {
- LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
- LTOPasses.add(llvm::createGlobalOptimizerPass());
- LTOPasses.add(llvm::createConstantMergePass());
+ lto_passes.add(llvm::createGlobalDCEPass());
}
- LTOPasses.run(*mModule);
-
-#if ANDROID_ENGINEERING_BUILD
- if (0 != gDebugDumpDirectory) {
- std::string errs;
- std::string Filename(gDebugDumpDirectory);
- Filename += "/post-lto-module.ll";
- llvm::raw_fd_ostream FS(Filename.c_str(), errs);
- mModule->print(FS, 0);
- FS.close();
+ // Invokde "afterAddLTOPasses" after pass manager finished its
+ // construction.
+ if (!afterAddLTOPasses(pScript, lto_passes)) {
+ return kErrHookAfterAddLTOPasses;
}
-#endif
- return 0;
+ // Invokde "beforeExecuteLTOPasses" before executing the passes.
+ if (!beforeExecuteLTOPasses(pScript, lto_passes)) {
+ return kErrHookBeforeExecuteLTOPasses;
+ }
+
+ lto_passes.run(pScript.getSource().getModule());
+
+ // Invokde "afterExecuteLTOPasses" before returning.
+ if (!afterExecuteLTOPasses(pScript)) {
+ return kErrHookAfterExecuteLTOPasses;
+ }
+
+ return kSuccess;
}
+enum Compiler::ErrorCode Compiler::runCodeGen(Script &pScript,
+ llvm::raw_ostream &pResult) {
+ llvm::TargetData *target_data;
+ llvm::MCContext *mc_context = NULL;
-void *Compiler::getSymbolAddress(char const *name) {
- return rsloaderGetSymbolAddress(mRSExecutable, name);
+ // Create pass manager for MC code generation.
+ llvm::PassManager codegen_passes;
+
+ // Prepare TargetData target data from Module
+ target_data = new (std::nothrow) llvm::TargetData(*mTarget->getTargetData());
+ if (target_data == NULL) {
+ return kErrTargetDataNoMemory;
+ }
+
+ // Add TargetData to the pass manager.
+ codegen_passes.add(target_data);
+
+ // Invokde "beforeAddCodeGenPasses" before adding the first pass.
+ if (!beforeAddCodeGenPasses(pScript, codegen_passes)) {
+ return kErrHookBeforeAddCodeGenPasses;
+ }
+
+ // Add passes to the pass manager to emit machine code through MC layer.
+ if (mTarget->addPassesToEmitMC(codegen_passes, mc_context, pResult,
+ /* DisableVerify */false)) {
+ return kPrepareCodeGenPass;
+ }
+
+ // Invokde "afterAddCodeGenPasses" after pass manager finished its
+ // construction.
+ if (!afterAddCodeGenPasses(pScript, codegen_passes)) {
+ return kErrHookAfterAddCodeGenPasses;
+ }
+
+ // Invokde "beforeExecuteCodeGenPasses" before executing the passes.
+ if (!beforeExecuteCodeGenPasses(pScript, codegen_passes)) {
+ return kErrHookBeforeExecuteCodeGenPasses;
+ }
+
+ // Execute the pass.
+ codegen_passes.run(pScript.getSource().getModule());
+
+ // Invokde "afterExecuteCodeGenPasses" before returning.
+ if (!afterExecuteCodeGenPasses(pScript)) {
+ return kErrHookAfterExecuteCodeGenPasses;
+ }
+
+ return kSuccess;
}
-Compiler::~Compiler() {
- rsloaderDisposeExec(mRSExecutable);
+enum Compiler::ErrorCode Compiler::compile(Script &pScript,
+ llvm::raw_ostream &pResult) {
+ llvm::Module &module = pScript.getSource().getModule();
+ enum ErrorCode err;
- // llvm::llvm_shutdown();
+ if (mTarget == NULL) {
+ return kErrNoTargetMachine;
+ }
+
+ // Materialize the bitcode module.
+ if (module.getMaterializer() != NULL) {
+ std::string error;
+ // A module with non-null materializer means that it is a lazy-load module.
+ // Materialize it now via invoking MaterializeAllPermanently(). This
+ // function returns false when the materialization is successful.
+ if (module.MaterializeAllPermanently(&error)) {
+ ALOGE("Failed to materialize the module `%s'! (%s)",
+ module.getModuleIdentifier().c_str(), error.c_str());
+ return kErrMaterialization;
+ }
+ }
+
+ if (mEnableLTO && ((err = runLTO(pScript)) != kSuccess)) {
+ return err;
+ }
+
+ if ((err = runCodeGen(pScript, pResult)) != kSuccess) {
+ return err;
+ }
+
+ return kSuccess;
}
+enum Compiler::ErrorCode Compiler::compile(Script &pScript,
+ OutputFile &pResult) {
+ // Check the state of the specified output file.
+ if (pResult.hasError()) {
+ return kErrInvalidOutputFileState;
+ }
-} // namespace bcc
+ // Open the output file decorated in llvm::raw_ostream.
+ llvm::raw_ostream *out = pResult.dup();
+ if (out == NULL) {
+ return kErrPrepareOutput;
+ }
+
+ // Delegate the request.
+ enum Compiler::ErrorCode err = compile(pScript, *out);
+
+ // Close the output before return.
+ delete out;
+
+ return err;
+}
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index f0e75d1..5e37925 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -14,153 +14,130 @@
* limitations under the License.
*/
-#ifndef BCC_COMPILER_H
-#define BCC_COMPILER_H
-
-#include <bcc/bcc.h>
-
-#include <Config.h>
-
-#include "librsloader.h"
-
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Target/TargetMachine.h"
-
-#include <stddef.h>
-
-#include <list>
-#include <string>
-#include <vector>
-#include <utility>
-
-#include "RSInfo.h"
-
+#ifndef BCC_EXECUTION_ENGINE_COMPILER_H
+#define BCC_EXECUTION_ENGINE_COMPILER_H
namespace llvm {
- class Module;
- class NamedMDNode;
- class TargetData;
-}
+class raw_ostream;
+class PassManager;
+class TargetData;
+class TargetMachine;
+
+} // end namespace llvm
namespace bcc {
- class ScriptCompiled;
- struct CompilerOption;
- class Compiler {
- private:
- //////////////////////////////////////////////////////////////////////////
- // The variable section below (e.g., Triple, CodeGenOptLevel)
- // is initialized in GlobalInitialization()
- //
- static bool GlobalInitialized;
+class CompilerConfig;
+class OutputFile;
+class Script;
- // If given, this will be the name of the target triple to compile for.
- // If not given, the initial values defined in this file will be used.
- static std::string Triple;
- static llvm::Triple::ArchType ArchType;
+//===----------------------------------------------------------------------===//
+// Design of Compiler
+//===----------------------------------------------------------------------===//
+// 1. A compiler instance can be constructed provided an "initial config."
+// 2. A compiler can later be re-configured using config().
+// 3. Once config() is invoked, it'll re-create TargetMachine instance (i.e.,
+// mTarget) according to the configuration supplied. TargetMachine instance
+// is *shared* across the different calls to compile() before the next call
+// to config().
+// 4. Once a compiler instance is created, you can use the compile() service
+// to compile the file over and over again. Each call uses TargetMachine
+// instance to construct the compilation passes.
+class Compiler {
+public:
+ enum ErrorCode {
+ kSuccess,
- static llvm::CodeGenOpt::Level CodeGenOptLevel;
+ kInvalidConfigNoTarget,
+ kErrCreateTargetMachine,
+ kErrSwitchTargetMachine,
+ kErrNoTargetMachine,
+ kErrTargetDataNoMemory,
+ kErrMaterialization,
+ kErrInvalidOutputFileState,
+ kErrPrepareOutput,
+ kPrepareCodeGenPass,
- // End of section of GlobalInitializing variables
- /////////////////////////////////////////////////////////////////////////
- // If given, the name of the target CPU to generate code for.
- static std::string CPU;
+ kErrHookBeforeAddLTOPasses,
+ kErrHookAfterAddLTOPasses,
+ kErrHookBeforeExecuteLTOPasses,
+ kErrHookAfterExecuteLTOPasses,
- // The list of target specific features to enable or disable -- this should
- // be a list of strings starting with '+' (enable) or '-' (disable).
- static std::vector<std::string> Features;
+ kErrHookBeforeAddCodeGenPasses,
+ kErrHookAfterAddCodeGenPasses,
+ kErrHookBeforeExecuteCodeGenPasses,
+ kErrHookAfterExecuteCodeGenPasses,
- static void LLVMErrorHandler(void *UserData, const std::string &Message);
+ kMaxErrorCode,
+ };
- friend class CodeEmitter;
- friend class CodeMemoryManager;
+ static const char *GetErrorString(enum ErrorCode pErrCode);
- private:
- ScriptCompiled *mpResult;
+private:
+ llvm::TargetMachine *mTarget;
+ // LTO is enabled by default.
+ bool mEnableLTO;
- std::string mError;
+ enum ErrorCode runLTO(Script &pScript);
+ enum ErrorCode runCodeGen(Script &pScript, llvm::raw_ostream &pResult);
- // Compilation buffer for MC
- llvm::SmallVector<char, 1024> mEmittedELFExecutable;
+public:
+ Compiler();
+ Compiler(const CompilerConfig &pConfig);
- // Loaded and relocated executable
- RSExecRef mRSExecutable;
+ enum ErrorCode config(const CompilerConfig &pConfig);
- BCCSymbolLookupFn mpSymbolLookupFn;
- void *mpSymbolLookupContext;
+ // Compile a script and output the result to a LLVM stream.
+ enum ErrorCode compile(Script &pScript, llvm::raw_ostream &pResult);
- llvm::Module *mModule;
+ // Compile a script and output the result to a file.
+ enum ErrorCode compile(Script &pScript, OutputFile &pResult);
- public:
- Compiler(ScriptCompiled *result);
+ void enableLTO(bool pEnable = true)
+ { mEnableLTO = pEnable; }
- static void GlobalInitialization();
+ virtual ~Compiler();
- static std::string const &getTargetTriple() {
- return Triple;
- }
+protected:
+ //===--------------------------------------------------------------------===//
+ // Plugin callbacks for sub-class.
+ //===--------------------------------------------------------------------===//
+ // Called before adding first pass to code-generation passes.
+ virtual bool beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
+ { return true; }
- static llvm::Triple::ArchType getTargetArchType() {
- return ArchType;
- }
+ // Called after adding last pass to code-generation passes.
+ virtual bool afterAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
+ { return true; }
- void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
- mpSymbolLookupFn = pFn;
- mpSymbolLookupContext = pContext;
- }
+ // Called before executing code-generation passes.
+ virtual bool beforeExecuteLTOPasses(Script &pScript,
+ llvm::PassManager &pPM)
+ { return true; }
- void *getSymbolAddress(char const *name);
+ // Called after executing code-generation passes.
+ virtual bool afterExecuteLTOPasses(Script &pScript)
+ { return true; }
- const llvm::SmallVector<char, 1024> &getELF() const {
- return mEmittedELFExecutable;
- }
+ // Called before adding first pass to code-generation passes.
+ virtual bool beforeAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
+ { return true; }
- int readModule(llvm::Module &pModule);
+ // Called after adding last pass to code-generation passes.
+ virtual bool afterAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
+ { return true; }
- int compile(const CompilerOption &option);
+ // Called before executing code-generation passes.
+ virtual bool beforeExecuteCodeGenPasses(Script &pScript,
+ llvm::PassManager &pPM)
+ { return true; }
- char const *getErrorMessage() {
- return mError.c_str();
- }
+ // Called after executing code-generation passes.
+ virtual bool afterExecuteCodeGenPasses(Script &pScript)
+ { return true; }
+};
- const llvm::Module *getModule() const {
- return mModule;
- }
+} // end namespace bcc
- ~Compiler();
-
- private:
-
- int runCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
- llvm::NamedMDNode const *ExportVarMetadata,
- llvm::NamedMDNode const *ExportFuncMetadata);
-
- int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM);
-
- int runInternalPasses(RSInfo::ExportForeachFuncListTy pForEachFuncs);
-
- int runLTO(llvm::TargetData *TD,
- std::vector<const char*>& ExportSymbols,
- llvm::CodeGenOpt::Level OptimizationLevel);
-
- bool hasError() const {
- return !mError.empty();
- }
-
- void setError(const char *Error) {
- mError.assign(Error); // Copying
- }
-
- void setError(const std::string &Error) {
- mError = Error;
- }
-
- }; // End of class Compiler
-
-} // namespace bcc
-
-#endif // BCC_COMPILER_H
+#endif // BCC_EXECUTION_ENGINE_COMPILER_H
diff --git a/lib/ExecutionEngine/CompilerOption.h b/lib/ExecutionEngine/CompilerOption.h
deleted file mode 100644
index f7c1e50..0000000
--- a/lib/ExecutionEngine/CompilerOption.h
+++ /dev/null
@@ -1,102 +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_COMPILER_OPTION_H
-#define BCC_COMPILER_OPTION_H
-
-#include "Config.h"
-#include "Compiler.h"
-
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Support/CodeGen.h"
-
-namespace bcc {
-
-class CompilerOption {
- public:
- // Constructor setup "default configuration". The "default configuration"
- // here means the configuration for running RenderScript (more specifically,
- // one can declare a CompilerOption object (call default constructor) and then
- // pass to the Compiler::compiler() without any modification for RenderScript,
- // see Script::prepareExecutable(...)).
- //
- // Must be invoked after calling Compiler::GlobalInitialization() at least once.
- //
- CompilerOption() {
- //-- Setup options to llvm::TargetMachine --//
-
- //-- Setup Frame Pointer Elimination Optimization --//
-#if defined(__HOST__)
- // Disable frame pointer elimination optimization for X86_64 and X86
- if ((Compiler::getTargetArchType() == llvm::Triple::x86_64) ||
- (Compiler::getTargetArchType() == llvm::Triple::x86)) {
- TargetOpt.NoFramePointerElim = true;
- } else {
- TargetOpt.NoFramePointerElim = false;
- }
-#elif defined(DEFAULT_X86_64_CODEGEN)
- TargetOpt.NoFramePointerElim = true;
-#elif defined(DEFAULT_X86_CODEGEN)
- TargetOpt.NoFramePointerElim = true;
-#else
- TargetOpt.NoFramePointerElim = false;
-#endif
-
- // Use hardfloat ABI
- //
- // TODO(all): Need to detect the CPU capability and decide whether to use
- // softfp. To use softfp, change following 2 lines to
- //
- // options.FloatABIType = llvm::FloatABI::Soft;
- // options.UseSoftFloat = true;
- TargetOpt.FloatABIType = llvm::FloatABI::Soft;
- TargetOpt.UseSoftFloat = false;
-
- //-- Setup relocation model --//
- RelocModelOpt = llvm::Reloc::Static;
-
- //-- Setup code model --//
-#if defined(__HOST__)
- // Data address in X86_64 architecture may reside in a far-away place
- if (Compiler::getTargetArchType() == llvm::Triple::x86_64) {
- CodeModelOpt = llvm::CodeModel::Medium;
- } else {
- CodeModelOpt = llvm::CodeModel::Small;
- }
-#elif defined(DEFAULT_X86_64_CODEGEN)
- CodeModelOpt = llvm::CodeModel::Medium;
-#else
- CodeModelOpt = llvm::CodeModel::Small;
-#endif
-
- //-- Run LTO passes --//
- RunLTO = true;
-
- //-- Load the result object after successful compilation --//
- LoadAfterCompile = true;
- }
-
- llvm::TargetOptions TargetOpt;
- llvm::CodeModel::Model CodeModelOpt;
- llvm::Reloc::Model RelocModelOpt;
- bool RunLTO;
- bool LoadAfterCompile;
-
-};
-
-} // namespace bcc
-
-#endif // BCC_COMPILER_OPTION_H
diff --git a/lib/ExecutionEngine/MCCacheReader.cpp b/lib/ExecutionEngine/MCCacheReader.cpp
deleted file mode 100644
index dc4ba92..0000000
--- a/lib/ExecutionEngine/MCCacheReader.cpp
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "MCCacheReader.h"
-
-#include "BCCRuntimeSymbolResolver.h"
-#include "DebugHelper.h"
-#include "InputFile.h"
-#include "ScriptCached.h"
-#include "SymbolResolverProxy.h"
-#include "SymbolResolvers.h"
-
-#include <bcc/bcc_mccache.h>
-
-#include <llvm/ADT/OwningPtr.h>
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <utility>
-#include <vector>
-
-#include <new>
-
-#include <stdlib.h>
-#include <string.h>
-
-using namespace std;
-
-namespace bcc {
-
-MCCacheReader::~MCCacheReader() {
- if (mpHeader) { free(mpHeader); }
- if (mpCachedDependTable) { free(mpCachedDependTable); }
- if (mpPragmaList) { free(mpPragmaList); }
- if (mpVarNameList) { free(mpVarNameList); }
- if (mpFuncNameList) { free(mpFuncNameList); }
-}
-
-ScriptCached *MCCacheReader::readCacheFile(InputFile &objFile,
- InputFile &infoFile,
- Script *S) {
- bool result = checkCacheFile(objFile, infoFile, S)
- && readPragmaList()
- && readObjectSlotList()
- && readObjFile()
- && readVarNameList()
- && readFuncNameList()
- && readForEachNameList()
- //&& relocate()
- ;
-
- return result ? mpResult.take() : NULL;
-}
-
-bool MCCacheReader::checkCacheFile(InputFile &objFile,
- InputFile &infoFile,
- Script *S) {
- // Check file handle
- if (objFile.hasError() || infoFile.hasError()) {
- return false;
- }
-
- mObjFile = &objFile;
- mInfoFile = &infoFile;
-
- // Allocate ScriptCached object
- mpResult.reset(new (nothrow) ScriptCached(S));
-
- if (!mpResult) {
- ALOGE("Unable to allocate ScriptCached object.\n");
- return false;
- }
-
- bool result = checkFileSize()
- && readHeader()
- && checkHeader()
- && checkMachineIntType()
- && checkSectionOffsetAndSize()
- && readStringPool()
- && checkStringPool()
- && readDependencyTable()
- && checkDependency()
- ;
-
- return result;
-}
-
-
-bool MCCacheReader::checkFileSize() {
- struct stat stfile;
- if (::stat(mInfoFile->getName().c_str(), &stfile) < 0) {
- ALOGE("Unable to stat cache file.\n");
- return false;
- }
-
- mInfoFileSize = stfile.st_size;
-
- if (mInfoFileSize < (off_t)sizeof(MCO_Header)) {
- ALOGE("Cache file is too small to be correct.\n");
- return false;
- }
-
- return true;
-}
-
-
-bool MCCacheReader::readHeader() {
- if (mInfoFile->seek(0) != 0) {
- ALOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
- return false;
- }
-
- mpHeader = (MCO_Header *)malloc(sizeof(MCO_Header));
- if (!mpHeader) {
- ALOGE("Unable to allocate for cache header.\n");
- return false;
- }
-
- if (mInfoFile->read(reinterpret_cast<char *>(mpHeader), sizeof(MCO_Header)) !=
- (ssize_t)sizeof(MCO_Header)) {
- ALOGE("Unable to read cache header.\n");
- return false;
- }
-
- // Dirty hack for libRS.
- // TODO(all): This should be removed in the future.
- if (mpHeader->libRS_threadable) {
- mpResult->mLibRSThreadable = true;
- }
-
- return true;
-}
-
-
-bool MCCacheReader::checkHeader() {
- if (memcmp(mpHeader->magic, MCO_MAGIC, 4) != 0) {
- ALOGE("Bad magic word\n");
- return false;
- }
-
- if (memcmp(mpHeader->version, MCO_VERSION, 4) != 0) {
- mpHeader->version[4 - 1] = '\0'; // ensure c-style string terminated
- ALOGI("Cache file format version mismatch: now %s cached %s\n",
- MCO_VERSION, mpHeader->version);
- return false;
- }
- return true;
-}
-
-
-bool MCCacheReader::checkMachineIntType() {
- uint32_t number = 0x00000001;
-
- bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
- if ((isLittleEndian && mpHeader->endianness != 'e') ||
- (!isLittleEndian && mpHeader->endianness != 'E')) {
- ALOGE("Machine endianness mismatch.\n");
- return false;
- }
-
- if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
- (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
- (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
- ALOGE("Machine integer size mismatch.\n");
- return false;
- }
-
- return true;
-}
-
-
-bool MCCacheReader::checkSectionOffsetAndSize() {
-#define CHECK_SECTION_OFFSET(NAME) \
- do { \
- off_t offset = mpHeader-> NAME##_offset; \
- off_t size = (off_t)mpHeader-> NAME##_size; \
- \
- if (mInfoFileSize < offset || mInfoFileSize < offset + size) { \
- ALOGE(#NAME " section overflow.\n"); \
- return false; \
- } \
- \
- if (offset % sizeof(int) != 0) { \
- ALOGE(#NAME " offset must aligned to %d.\n", (int)sizeof(int)); \
- return false; \
- } \
- \
- if (size < static_cast<off_t>(sizeof(size_t))) { \
- ALOGE(#NAME " size is too small to be correct.\n"); \
- return false; \
- } \
- } while (0)
-
- CHECK_SECTION_OFFSET(str_pool);
- CHECK_SECTION_OFFSET(depend_tab);
- //CHECK_SECTION_OFFSET(reloc_tab);
- CHECK_SECTION_OFFSET(pragma_list);
-
-#undef CHECK_SECTION_OFFSET
-
- return true;
-}
-
-
-#define CACHE_READER_READ_SECTION(TYPE, AUTO_MANAGED_HOLDER, NAME) \
- TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size); \
- \
- if (!NAME##_raw) { \
- ALOGE("Unable to allocate for " #NAME "\n"); \
- return false; \
- } \
- \
- /* We have to ensure that some one will deallocate NAME##_raw */ \
- AUTO_MANAGED_HOLDER = NAME##_raw; \
- \
- if (mInfoFile->seek(mpHeader->NAME##_offset) == -1) { \
- ALOGE("Unable to seek to " #NAME " section\n"); \
- return false; \
- } \
- \
- if (mInfoFile->read(reinterpret_cast<char *>(NAME##_raw), \
- mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
- { \
- ALOGE("Unable to read " #NAME ".\n"); \
- return false; \
- }
-
-
-bool MCCacheReader::readStringPool() {
- CACHE_READER_READ_SECTION(MCO_StringPool,
- mpResult->mpStringPoolRaw, str_pool);
-
- char *str_base = reinterpret_cast<char *>(str_pool_raw);
-
- vector<char const *> &pool = mpResult->mStringPool;
- for (size_t i = 0; i < str_pool_raw->count; ++i) {
- char *str = str_base + str_pool_raw->list[i].offset;
- pool.push_back(str);
- }
-
- return true;
-}
-
-
-bool MCCacheReader::checkStringPool() {
- MCO_StringPool *poolR = mpResult->mpStringPoolRaw;
- vector<char const *> &pool = mpResult->mStringPool;
-
- // Ensure that every c-style string is ended with '\0'
- for (size_t i = 0; i < poolR->count; ++i) {
- if (pool[i][poolR->list[i].length] != '\0') {
- ALOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
- return false;
- }
- }
-
- return true;
-}
-
-
-bool MCCacheReader::readDependencyTable() {
- CACHE_READER_READ_SECTION(MCO_DependencyTable, mpCachedDependTable,
- depend_tab);
- return true;
-}
-
-
-bool MCCacheReader::checkDependency() {
- if (mDependencies.size() != mpCachedDependTable->count) {
- ALOGE("Dependencies count mismatch. (%lu vs %lu)\n",
- (unsigned long)mDependencies.size(),
- (unsigned long)mpCachedDependTable->count);
- return false;
- }
-
- vector<char const *> &strPool = mpResult->mStringPool;
- map<string, unsigned char const *>::iterator dep;
-
- dep = mDependencies.begin();
- for (size_t i = 0; i < mpCachedDependTable->count; ++i, ++dep) {
- string const &depName = dep->first;
- unsigned char const *depSHA1 = dep->second;
-
- MCO_Dependency *depCached =&mpCachedDependTable->table[i];
- char const *depCachedName = strPool[depCached->res_name_strp_index];
- //uint32_t depCachedType = depCached->res_type;
- unsigned char const *depCachedSHA1 = depCached->sha1;
-
- if (depName != depCachedName) {
- ALOGE("Cache dependency name mismatch:\n");
- ALOGE(" given: %s\n", depName.c_str());
- ALOGE(" cached: %s\n", depCachedName);
-
- return false;
- }
-
- if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
- ALOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
-
-#define PRINT_SHA1(PREFIX, X, POSTFIX) \
- ALOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
- 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]);
-
- PRINT_SHA1(" given: ", depSHA1, "\n");
- PRINT_SHA1(" cached: ", depCachedSHA1, "\n");
-
-#undef PRINT_SHA1
-
- return false;
- }
- }
-
- return true;
-}
-
-bool MCCacheReader::readVarNameList() {
- CACHE_READER_READ_SECTION(MCO_String_Ptr, mpVarNameList, export_var_name_list);
- vector<char const *> const &strPool = mpResult->mStringPool;
-
- mpResult->mpExportVars = (MCO_ExportVarList*)
- malloc(sizeof(size_t) +
- sizeof(void*) * export_var_name_list_raw->count);
- if (!mpResult->mpExportVars) {
- ALOGE("Unable to allocate for mpExportVars\n");
- return false;
- }
- mpResult->mpExportVars->count = export_var_name_list_raw->count;
-
- for (size_t i = 0; i < export_var_name_list_raw->count; ++i) {
- mpResult->mpExportVars->cached_addr_list[i] =
- rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_var_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MC_REFLECT
- ALOGD("Get symbol address: %s -> %p",
- strPool[export_var_name_list_raw->strp_indexs[i]], mpResult->mpExportVars->cached_addr_list[i]);
-#endif
- }
- return true;
-}
-
-bool MCCacheReader::readFuncNameList() {
- CACHE_READER_READ_SECTION(MCO_String_Ptr, mpFuncNameList, export_func_name_list);
- vector<char const *> const &strPool = mpResult->mStringPool;
-
- mpResult->mpExportFuncs = (MCO_ExportFuncList*)
- malloc(sizeof(size_t) +
- sizeof(void*) * export_func_name_list_raw->count);
- if (!mpResult->mpExportFuncs) {
- ALOGE("Unable to allocate for mpExportFuncs\n");
- return false;
- }
- mpResult->mpExportFuncs->count = export_func_name_list_raw->count;
-
- for (size_t i = 0; i < export_func_name_list_raw->count; ++i) {
- mpResult->mpExportFuncs->cached_addr_list[i] =
- rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_func_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MC_REFLECT
- ALOGD("Get function address: %s -> %p",
- strPool[export_func_name_list_raw->strp_indexs[i]], mpResult->mpExportFuncs->cached_addr_list[i]);
-#endif
- }
- return true;
-}
-
-bool MCCacheReader::readForEachNameList() {
- CACHE_READER_READ_SECTION(MCO_String_Ptr, mpForEachNameList, export_foreach_name_list);
- vector<char const *> const &strPool = mpResult->mStringPool;
-
- mpResult->mpExportForEach = (MCO_ExportForEachList*)
- malloc(sizeof(size_t) +
- sizeof(void*) * export_foreach_name_list_raw->count);
- if (!mpResult->mpExportForEach) {
- ALOGE("Unable to allocate for mpExportForEach\n");
- return false;
- }
- mpResult->mpExportForEach->count = export_foreach_name_list_raw->count;
-
- for (size_t i = 0; i < export_foreach_name_list_raw->count; ++i) {
- mpResult->mpExportForEach->cached_addr_list[i] =
- rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_foreach_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MC_REFLECT
- ALOGE("Get foreach function address: %s -> %p",
- strPool[export_foreach_name_list_raw->strp_indexs[i]], mpResult->mpExportForEach->cached_addr_list[i]);
-#endif
- }
- return true;
-}
-
-bool MCCacheReader::readPragmaList() {
- CACHE_READER_READ_SECTION(MCO_PragmaList, mpPragmaList, pragma_list);
-
- vector<char const *> const &strPool = mpResult->mStringPool;
- ScriptCached::PragmaList &pragmas = mpResult->mPragmas;
-
- for (size_t i = 0; i < pragma_list_raw->count; ++i) {
- MCO_Pragma *pragma = &pragma_list_raw->list[i];
- pragmas.push_back(make_pair(strPool[pragma->key_strp_index],
- strPool[pragma->value_strp_index]));
- }
-
- return true;
-}
-
-
-bool MCCacheReader::readObjectSlotList() {
- CACHE_READER_READ_SECTION(MCO_ObjectSlotList,
- mpResult->mpObjectSlotList, object_slot_list);
- return true;
-}
-
-bool MCCacheReader::readObjFile() {
- if (mpResult->mCachedELFExecutable.size() != 0) {
- ALOGE("Attempted to read cached object into a non-empty script");
- return false;
- }
- char readBuffer[1024];
- int readSize;
- while ((readSize = mObjFile->read(readBuffer, 1024)) > 0) {
- mpResult->mCachedELFExecutable.append(readBuffer, readBuffer + readSize);
- }
- if (readSize != 0) {
- ALOGE("Read file Error");
- return false;
- }
- ALOGD("Read object file size %d", (int)mpResult->mCachedELFExecutable.size());
-
- BCCRuntimeSymbolResolver bccRuntimesResolver;
- LookupFunctionSymbolResolver<void *> rsSymbolResolver(mpSymbolLookupFn,
- mpSymbolLookupContext);
-
- SymbolResolverProxy resolver;
- resolver.chainResolver(bccRuntimesResolver);
- resolver.chainResolver(rsSymbolResolver);
-
- mpResult->mRSExecutable =
- rsloaderCreateExec((unsigned char *)&*(mpResult->mCachedELFExecutable.begin()),
- mpResult->mCachedELFExecutable.size(),
- SymbolResolverProxy::LookupFunction, &resolver);
-
- // Point ELF section headers to location of executable code, otherwise
- // execution through GDB stops unexpectedly as GDB translates breakpoints
- // in JITted code incorrectly (and complains about being unable to insert
- // breakpoint at an invalid address)
- rsloaderUpdateSectionHeaders(mpResult->mRSExecutable,
- (unsigned char*) mpResult->mCachedELFExecutable.begin());
-
- return true;
-}
-
-#undef CACHE_READER_READ_SECTION
-
-bool MCCacheReader::readRelocationTable() {
- // TODO(logan): Not finished.
- return true;
-}
-
-
-bool MCCacheReader::relocate() {
- return true;
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/MCCacheReader.h b/lib/ExecutionEngine/MCCacheReader.h
deleted file mode 100644
index e2d10c5..0000000
--- a/lib/ExecutionEngine/MCCacheReader.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_MCCACHEREADER_H
-#define BCC_MCCACHEREADER_H
-
-#include "ScriptCached.h"
-
-#include <llvm/ADT/OwningPtr.h>
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include <stddef.h>
-#include <stdint.h>
-
-struct MCO_Header;
-
-namespace bcc {
- class Script;
- class InputFile;
-
- class MCCacheReader {
- private:
- InputFile *mObjFile, *mInfoFile;
- off_t mInfoFileSize;
-
- MCO_Header *mpHeader;
- MCO_DependencyTable *mpCachedDependTable;
- MCO_PragmaList *mpPragmaList;
- MCO_FuncTable *mpFuncTable;
-
- MCO_String_Ptr *mpVarNameList;
- MCO_String_Ptr *mpFuncNameList;
- MCO_String_Ptr *mpForEachNameList;
-
- llvm::OwningPtr<ScriptCached> mpResult;
-
- std::map<std::string, unsigned char const *> mDependencies;
-
- bool mIsContextSlotNotAvail;
-
- BCCSymbolLookupFn mpSymbolLookupFn;
- void *mpSymbolLookupContext;
-
- public:
- MCCacheReader()
- : mObjFile(NULL), mInfoFile(NULL), mInfoFileSize(0), mpHeader(NULL),
- mpCachedDependTable(NULL), mpPragmaList(NULL),
- mpVarNameList(NULL), mpFuncNameList(NULL), mpForEachNameList(NULL),
- mIsContextSlotNotAvail(false) {
- }
-
- ~MCCacheReader();
-
- void addDependency(std::string const &resName,
- unsigned char const *sha1) {
- mDependencies.insert(std::make_pair(resName, sha1));
- }
-
- ScriptCached *readCacheFile(InputFile &objFile, InputFile &infoFile, Script *s);
- bool checkCacheFile(InputFile &objFile, InputFile &infoFile, Script *S);
-
- bool isContextSlotNotAvail() const {
- return mIsContextSlotNotAvail;
- }
-
- void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
- mpSymbolLookupFn = pFn;
- mpSymbolLookupContext = pContext;
- }
-
- private:
- bool readHeader();
- bool readStringPool();
- bool readDependencyTable();
- bool readPragmaList();
- bool readObjectSlotList();
- bool readObjFile();
- bool readRelocationTable();
-
- bool readVarNameList();
- bool readFuncNameList();
- bool readForEachNameList();
-
- bool checkFileSize();
- bool checkHeader();
- bool checkMachineIntType();
- bool checkSectionOffsetAndSize();
- bool checkStringPool();
- bool checkDependency();
- bool checkContext();
-
- bool relocate();
- };
-
-} // namespace bcc
-
-#endif // BCC_MCCACHEREADER_H
diff --git a/lib/ExecutionEngine/MCCacheWriter.cpp b/lib/ExecutionEngine/MCCacheWriter.cpp
deleted file mode 100644
index c667c19..0000000
--- a/lib/ExecutionEngine/MCCacheWriter.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "MCCacheWriter.h"
-
-#include "DebugHelper.h"
-#include "OutputFile.h"
-#include "RSScript.h"
-
-#include <map>
-#include <string>
-#include <vector>
-#include <utility>
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-using namespace std;
-
-namespace bcc {
-
-MCCacheWriter::~MCCacheWriter() {
-#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
-
- CHECK_AND_FREE(mpHeaderSection);
- CHECK_AND_FREE(mpStringPoolSection);
- CHECK_AND_FREE(mpDependencyTableSection);
- CHECK_AND_FREE(mpPragmaListSection);
- CHECK_AND_FREE(mpObjectSlotSection);
- CHECK_AND_FREE(mpExportVarNameListSection);
- CHECK_AND_FREE(mpExportFuncNameListSection);
-
-#undef CHECK_AND_FREE
-}
-
-bool MCCacheWriter::writeCacheFile(OutputFile &objFile, OutputFile &infoFile,
- RSScript *S, uint32_t libRS_threadable) {
- if (objFile.hasError() || infoFile.hasError()) {
- return false;
- }
-
- mObjFile = &objFile;
- mInfoFile = &infoFile;
- mpOwner = S;
-
- bool result = prepareHeader(libRS_threadable)
- && prepareDependencyTable()
- && preparePragmaList()
- && prepareExportVarNameList()
- && prepareExportFuncNameList()
- && prepareExportForEachNameList()
- && prepareStringPool()
- && prepareObjectSlotList()
- && calcSectionOffset()
- && writeAll()
- ;
-
- return result;
-}
-
-
-bool MCCacheWriter::prepareHeader(uint32_t libRS_threadable) {
- MCO_Header *header = (MCO_Header *)malloc(sizeof(MCO_Header));
-
- if (!header) {
- ALOGE("Unable to allocate for header.\n");
- return false;
- }
-
- mpHeaderSection = header;
-
- // Initialize
- memset(header, '\0', sizeof(MCO_Header));
-
- // Magic word and version
- memcpy(header->magic, MCO_MAGIC, 4);
- memcpy(header->version, MCO_VERSION, 4);
-
- // Machine Integer Type
- uint32_t number = 0x00000001;
- header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
- header->sizeof_off_t = sizeof(off_t);
- header->sizeof_size_t = sizeof(size_t);
- header->sizeof_ptr_t = sizeof(void *);
-
- // libRS is threadable dirty hack
- // TODO: This should be removed in the future
- header->libRS_threadable = libRS_threadable;
-
- return true;
-}
-
-
-bool MCCacheWriter::prepareDependencyTable() {
- size_t tableSize = sizeof(MCO_DependencyTable) +
- sizeof(MCO_Dependency) * mDependencies.size();
-
- MCO_DependencyTable *tab = (MCO_DependencyTable *)malloc(tableSize);
-
- if (!tab) {
- ALOGE("Unable to allocate for dependency table section.\n");
- return false;
- }
-
- mpDependencyTableSection = tab;
- mpHeaderSection->depend_tab_size = tableSize;
-
- tab->count = mDependencies.size();
-
- size_t i = 0;
- for (map<string, unsigned char const *>::iterator
- I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
- MCO_Dependency *dep = &tab->table[i];
-
- dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
- memcpy(dep->sha1, I->second, 20);
- }
-
- return true;
-}
-
-bool MCCacheWriter::preparePragmaList() {
- size_t pragmaCount = mpOwner->getPragmaCount();
-
- size_t listSize = sizeof(MCO_PragmaList) +
- sizeof(MCO_Pragma) * pragmaCount;
-
- MCO_PragmaList *list = (MCO_PragmaList *)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for pragma list\n");
- return false;
- }
-
- mpPragmaListSection = list;
- mpHeaderSection->pragma_list_size = listSize;
-
- list->count = pragmaCount;
-
- vector<char const *> keyList(pragmaCount);
- vector<char const *> valueList(pragmaCount);
- mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
-
- for (size_t i = 0; i < pragmaCount; ++i) {
- char const *key = keyList[i];
- char const *value = valueList[i];
-
- size_t keyLen = strlen(key);
- size_t valueLen = strlen(value);
-
- MCO_Pragma *pragma = &list->list[i];
- pragma->key_strp_index = addString(key, keyLen);
- pragma->value_strp_index = addString(value, valueLen);
- }
-
- return true;
-}
-
-bool MCCacheWriter::prepareStringPool() {
- // Calculate string pool size
- size_t size = sizeof(MCO_StringPool) +
- sizeof(MCO_String) * mStringPool.size();
-
- off_t strOffset = size;
-
- for (size_t i = 0; i < mStringPool.size(); ++i) {
- size += mStringPool[i].second + 1;
- }
-
- // Create string pool
- MCO_StringPool *pool = (MCO_StringPool *)malloc(size);
-
- if (!pool) {
- ALOGE("Unable to allocate string pool.\n");
- return false;
- }
-
- mpStringPoolSection = pool;
- mpHeaderSection->str_pool_size = size;
-
- pool->count = mStringPool.size();
-
- char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
-
- for (size_t i = 0; i < mStringPool.size(); ++i) {
- MCO_String *str = &pool->list[i];
-
- str->length = mStringPool[i].second;
- str->offset = strOffset;
- memcpy(strPtr, mStringPool[i].first, str->length);
-
- strPtr += str->length;
- *strPtr++ = '\0';
-
- strOffset += str->length + 1;
- }
-
- return true;
-}
-
-
-bool MCCacheWriter::prepareExportVarNameList() {
- size_t varCount = mpOwner->getExportVarCount();
- size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * varCount;
-
- MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for export variable name list\n");
- return false;
- }
-
- mpExportVarNameListSection = list;
- mpHeaderSection->export_var_name_list_size = listSize;
-
- list->count = static_cast<size_t>(varCount);
-
- mpOwner->getExportVarNameList(varNameList);
- for (size_t i = 0; i < varCount; ++i) {
- list->strp_indexs[i] = addString(varNameList[i].c_str(), varNameList[i].length());
- }
- return true;
-}
-
-
-bool MCCacheWriter::prepareExportFuncNameList() {
- size_t funcCount = mpOwner->getExportFuncCount();
- size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * funcCount;
-
- MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for export function name list\n");
- return false;
- }
-
- mpExportFuncNameListSection = list;
- mpHeaderSection->export_func_name_list_size = listSize;
-
- list->count = static_cast<size_t>(funcCount);
-
- mpOwner->getExportFuncNameList(funcNameList);
- for (size_t i = 0; i < funcCount; ++i) {
- list->strp_indexs[i] = addString(funcNameList[i].c_str(), funcNameList[i].length());
- }
- return true;
-}
-
-
-bool MCCacheWriter::prepareExportForEachNameList() {
- size_t forEachCount = mpOwner->getExportForEachCount();
- size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * forEachCount;
-
- MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for export forEach name list\n");
- return false;
- }
-
- mpExportForEachNameListSection = list;
- mpHeaderSection->export_foreach_name_list_size = listSize;
-
- list->count = static_cast<size_t>(forEachCount);
-
- mpOwner->getExportForEachNameList(forEachNameList);
- for (size_t i = 0; i < forEachCount; ++i) {
- list->strp_indexs[i] = addString(forEachNameList[i].c_str(), forEachNameList[i].length());
- }
- return true;
-}
-
-
-bool MCCacheWriter::prepareObjectSlotList() {
- size_t objectSlotCount = mpOwner->getObjectSlotCount();
-
- size_t listSize = sizeof(MCO_ObjectSlotList) +
- sizeof(uint32_t) * objectSlotCount;
-
- MCO_ObjectSlotList *list = (MCO_ObjectSlotList *)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for object slot list\n");
- return false;
- }
-
- mpObjectSlotSection = list;
- mpHeaderSection->object_slot_list_size = listSize;
-
- list->count = objectSlotCount;
-
- mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
- return true;
-}
-
-
-bool MCCacheWriter::calcSectionOffset() {
- size_t offset = sizeof(MCO_Header);
-
-#define OFFSET_INCREASE(NAME) \
- do { \
- /* Align to a word */ \
- size_t rem = offset % sizeof(int); \
- if (rem > 0) { \
- offset += sizeof(int) - rem; \
- } \
- \
- /* Save the offset and increase it */ \
- mpHeaderSection->NAME##_offset = offset; \
- offset += mpHeaderSection->NAME##_size; \
- } while (0)
-
- OFFSET_INCREASE(str_pool);
- OFFSET_INCREASE(depend_tab);
- OFFSET_INCREASE(pragma_list);
- OFFSET_INCREASE(func_table);
- OFFSET_INCREASE(object_slot_list);
- OFFSET_INCREASE(export_var_name_list);
- OFFSET_INCREASE(export_func_name_list);
- OFFSET_INCREASE(export_foreach_name_list);
-
-#undef OFFSET_INCREASE
-
- return true;
-}
-
-
-bool MCCacheWriter::writeAll() {
-#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION) \
- do { \
- if (mInfoFile->seek(OFFSET) == -1) { \
- ALOGE("Unable to seek to " #NAME " section for writing.\n"); \
- return false; \
- } \
- \
- if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) != \
- static_cast<ssize_t>(SIZE)) { \
- ALOGE("Unable to write " #NAME " section to cache file.\n"); \
- return false; \
- } \
- } while (0)
-
-#define WRITE_SECTION_SIMPLE(NAME, SECTION) \
- WRITE_SECTION(NAME, \
- mpHeaderSection->NAME##_offset, \
- mpHeaderSection->NAME##_size, \
- SECTION)
-
- WRITE_SECTION(header, 0, sizeof(MCO_Header), mpHeaderSection);
-
- WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
- WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
- WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
- WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
-
- WRITE_SECTION_SIMPLE(export_var_name_list, mpExportVarNameListSection);
- WRITE_SECTION_SIMPLE(export_func_name_list, mpExportFuncNameListSection);
- WRITE_SECTION_SIMPLE(export_foreach_name_list, mpExportForEachNameListSection);
-
-#undef WRITE_SECTION_SIMPLE
-#undef WRITE_SECTION
-
- if (static_cast<size_t>(mObjFile->write(mpOwner->getELF(),
- mpOwner->getELFSize()))
- != mpOwner->getELFSize()) {
- ALOGE("Unable to write ELF to cache file.\n");
- return false;
- }
-
- return true;
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/MCCacheWriter.h b/lib/ExecutionEngine/MCCacheWriter.h
deleted file mode 100644
index 47f1e40..0000000
--- a/lib/ExecutionEngine/MCCacheWriter.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_MCCACHEWRITER_H
-#define BCC_MCCACHEWRITER_H
-
-#include <bcc/bcc_mccache.h>
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace bcc {
- class OutputFile;
- class RSScript;
-
- class MCCacheWriter {
- private:
- RSScript *mpOwner;
-
- OutputFile *mObjFile, *mInfoFile;
-
- std::vector<std::pair<char const *, size_t> > mStringPool;
-
- std::map<std::string, unsigned char const *> mDependencies;
-
- MCO_Header *mpHeaderSection;
- MCO_StringPool *mpStringPoolSection;
- MCO_DependencyTable *mpDependencyTableSection;
- MCO_PragmaList *mpPragmaListSection;
- MCO_ObjectSlotList *mpObjectSlotSection;
-
- MCO_String_Ptr *mpExportVarNameListSection;
- MCO_String_Ptr *mpExportFuncNameListSection;
- MCO_String_Ptr *mpExportForEachNameListSection;
-
- std::vector<std::string> varNameList;
- std::vector<std::string> funcNameList;
- std::vector<std::string> forEachNameList;
-
- public:
- MCCacheWriter()
- : mpHeaderSection(NULL), mpStringPoolSection(NULL),
- mpDependencyTableSection(NULL), mpPragmaListSection(NULL),
- mpObjectSlotSection(NULL) {
- }
-
- ~MCCacheWriter();
-
- bool writeCacheFile(OutputFile &objFile, OutputFile &infoFile,
- RSScript *S, uint32_t libRS_threadable);
-
- void addDependency(std::string const &resName,
- unsigned char const *sha1) {
- mDependencies.insert(std::make_pair(resName, sha1));
- }
-
- private:
- bool prepareHeader(uint32_t libRS_threadable);
- bool prepareStringPool();
- bool prepareDependencyTable();
- bool prepareRelocationTable();
- bool preparePragmaList();
- bool prepareObjectSlotList();
-
- bool prepareExportVarNameList();
- bool prepareExportFuncNameList();
- bool prepareExportForEachNameList();
-
- bool writeAll();
-
- bool calcSectionOffset();
-
- size_t addString(char const *str, size_t size) {
- mStringPool.push_back(std::make_pair(str, size));
- return mStringPool.size() - 1;
- }
-
- };
-
-} // namespace bcc
-
-#endif // BCC_MCCACHEWRITER_H
diff --git a/lib/ExecutionEngine/RSCompiler.cpp b/lib/ExecutionEngine/RSCompiler.cpp
new file mode 100644
index 0000000..37e13bb
--- /dev/null
+++ b/lib/ExecutionEngine/RSCompiler.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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 "RSCompiler.h"
+
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Transforms/IPO.h>
+
+#include "DebugHelper.h"
+#include "RSExecutable.h"
+#include "RSInfo.h"
+#include "RSScript.h"
+#include "RSTransforms.h"
+#include "Source.h"
+
+using namespace bcc;
+
+bool RSCompiler::beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM) {
+ // Add a pass to internalize the symbols that don't need to have global
+ // visibility.
+ RSScript &script = static_cast<RSScript &>(pScript);
+ const RSInfo *info = script.getInfo();
+
+ // The vector contains the symbols that should not be internalized.
+ std::vector<const char *> export_symbols;
+
+ // Special RS functions should always be global symbols.
+ const char **special_functions = RSExecutable::SpecialFunctionNames;
+ while (*special_functions != NULL) {
+ export_symbols.push_back(*special_functions);
+ special_functions++;
+ }
+
+ // Visibility of symbols appeared in rs_export_var and rs_export_func should
+ // also be preserved.
+ const RSInfo::ExportVarNameListTy &export_vars = info->getExportVarNames();
+ const RSInfo::ExportFuncNameListTy &export_funcs = info->getExportFuncNames();
+
+ for (RSInfo::ExportVarNameListTy::const_iterator
+ export_var_iter = export_vars.begin(),
+ export_var_end = export_vars.end();
+ export_var_iter != export_var_end; export_var_iter++) {
+ export_symbols.push_back(*export_var_iter);
+ }
+
+ for (RSInfo::ExportFuncNameListTy::const_iterator
+ export_func_iter = export_funcs.begin(),
+ export_func_end = export_funcs.end();
+ export_func_iter != export_func_end; export_func_iter++) {
+ export_symbols.push_back(*export_func_iter);
+ }
+
+ // Expanded foreach functions should not be internalized, too.
+ const RSInfo::ExportForeachFuncListTy &export_foreach_func =
+ info->getExportForeachFuncs();
+ std::vector<std::string> expanded_foreach_funcs;
+ for (RSInfo::ExportForeachFuncListTy::const_iterator
+ foreach_func_iter = export_foreach_func.begin(),
+ foreach_func_end = export_foreach_func.end();
+ foreach_func_iter != foreach_func_end; foreach_func_iter++) {
+ std::string name(foreach_func_iter->first);
+ expanded_foreach_funcs.push_back(name.append(".expand"));
+ export_symbols.push_back(expanded_foreach_funcs.back().c_str());
+ }
+
+ pPM.add(llvm::createInternalizePass(export_symbols));
+
+ return true;
+}
+
+bool RSCompiler::beforeExecuteLTOPasses(Script &pScript,
+ llvm::PassManager &pPM) {
+ // Execute a pass to expand foreach-able functions
+ llvm::PassManager rs_passes;
+
+ // Script passed to RSCompiler must be a RSScript.
+ RSScript &script = static_cast<RSScript &>(pScript);
+ const RSInfo *info = script.getInfo();
+ llvm::Module &module = script.getSource().getModule();
+
+ if (info == NULL) {
+ ALOGE("Missing RSInfo in RSScript to run the pass for foreach expansion on "
+ "%s!", module.getModuleIdentifier().c_str());
+ return false;
+ }
+
+ // Expand ForEach on CPU path to reduce launch overhead.
+ rs_passes.add(createRSForEachExpandPass(info->getExportForeachFuncs()));
+
+ // Execute the pass.
+ rs_passes.run(module);
+
+ return true;
+}
diff --git a/lib/ExecutionEngine/RSCompiler.h b/lib/ExecutionEngine/RSCompiler.h
new file mode 100644
index 0000000..227727b
--- /dev/null
+++ b/lib/ExecutionEngine/RSCompiler.h
@@ -0,0 +1,32 @@
+/*
+ * 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_EXECUTION_ENGINE_RS_COMPILER_H
+#define BCC_EXECUTION_ENGINE_RS_COMPILER_H
+
+#include "Compiler.h"
+
+namespace bcc {
+
+class RSCompiler : public Compiler {
+private:
+ virtual bool beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM);
+ virtual bool beforeExecuteLTOPasses(Script &pScript, llvm::PassManager &pPM);
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_RS_COMPILER_H
diff --git a/lib/ExecutionEngine/RSScript.cpp b/lib/ExecutionEngine/RSScript.cpp
index 2ca97a5..7ec84d9 100644
--- a/lib/ExecutionEngine/RSScript.cpp
+++ b/lib/ExecutionEngine/RSScript.cpp
@@ -14,47 +14,15 @@
* limitations under the License.
*/
-#include "Script.h"
+#include "RSScript.h"
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <new>
#include <cstring>
#include <llvm/ADT/STLExtras.h>
-#include <cutils/properties.h>
-
-#include "Config.h"
-
-#include "MCCacheReader.h"
-#include "MCCacheWriter.h"
-#include "CompilerOption.h"
-
#include "DebugHelper.h"
-#include "FileMutex.h"
-#include "GDBJITRegistrar.h"
-#include "InputFile.h"
-#include "OutputFile.h"
-#include "ScriptCompiled.h"
-#include "ScriptCached.h"
-#include "Sha1Helper.h"
-#include "Source.h"
-namespace {
-
-bool getBooleanProp(const char *str) {
- char buf[PROPERTY_VALUE_MAX];
- property_get(str, buf, "0");
- return strcmp(buf, "0") != 0;
-}
-
-} // namespace anonymous
-
-namespace bcc {
+using namespace bcc;
RSScript::SourceDependency::SourceDependency(const std::string &pSourceName,
const uint8_t *pSHA1)
@@ -64,44 +32,18 @@
}
RSScript::RSScript(Source &pSource)
- : Script(pSource),
- mpExtSymbolLookupFn(NULL),
- mpExtSymbolLookupFnContext(NULL) {
- resetState();
- return;
-}
+ : Script(pSource), mInfo(NULL), mCompilerVersion(0),
+ mOptimizationLevel(kOptLvl3) { }
RSScript::~RSScript() {
- switch (mStatus) {
- case ScriptStatus::Compiled:
- delete mCompiled;
- break;
-
- case ScriptStatus::Cached:
- delete mCached;
- break;
-
- default:
- break;
- }
llvm::DeleteContainerPointers(mSourceDependencies);
}
-void RSScript::resetState() {
- mErrorCode = BCC_NO_ERROR;
- mStatus = ScriptStatus::Unknown;
- mObjectType = ScriptObject::Unknown;
- mIsContextSlotNotAvail = false;
- // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be assign
- // to NULL during state resetting.
- //mpExtSymbolLookupFn = NULL;
- //mpExtSymbolLookupFnContext = NULL;
- llvm::DeleteContainerPointers(mSourceDependencies);
- return;
-}
-
bool RSScript::doReset() {
- resetState();
+ mInfo = NULL;
+ mCompilerVersion = 0;
+ mOptimizationLevel = kOptLvl3;
+ llvm::DeleteContainerPointers(mSourceDependencies);
return true;
}
@@ -118,653 +60,3 @@
mSourceDependencies.push_back(source_dep);
return true;
}
-
-int RSScript::prepareRelocatable(char const *objPath,
- llvm::Reloc::Model RelocModel,
- unsigned long flags) {
- CompilerOption option;
- option.RelocModelOpt = RelocModel;
- option.LoadAfterCompile = false;
-
- int status = internalCompile(option);
- if (status != 0) {
- ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
- return status;
- }
-
- OutputFile objFile(objPath);
- if (objFile.hasError()) {
- ALOGE("Failed to open %s for write. (%s)", objPath,
- objFile.getErrorMessage().c_str());
- return 1;
- }
-
- if (static_cast<size_t>(objFile.write(getELF(),
- getELFSize())) != getELFSize()) {
- objFile.close();
- ::unlink(objPath);
- ALOGE("Unable to write ELF to file %s.\n", objPath);
- return false;
- }
-
- mObjectType = ScriptObject::Relocatable;
-
- return 0;
-}
-
-
-int RSScript::prepareSharedObject(char const *objPath,
- char const *dsoPath,
- unsigned long flags) {
- // TODO: Support cached shared object.
- return 1;
-}
-
-
-int RSScript::prepareExecutable(char const *cacheDir,
- char const *cacheName,
- unsigned long flags) {
- if (mStatus != ScriptStatus::Unknown) {
- mErrorCode = BCC_INVALID_OPERATION;
- ALOGE("Invalid operation: %s\n", __func__);
- return 1;
- }
-
- int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
-
- if (status != 0) {
- CompilerOption option;
- status = internalCompile(option);
-
- if (status != 0) {
- ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
- return status;
- }
-
- status = writeCache();
- if (status != 0) {
- ALOGE("Failed to write the cache for %s\n", cacheName);
- return status;
- }
- }
-
- // FIXME: Registration can be conditional on the presence of debug metadata
- registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
-
- mObjectType = ScriptObject::Executable;
-
- return status;
-}
-
-int RSScript::internalLoadCache(char const *cacheDir, char const *cacheName,
- bool checkOnly) {
- if ((cacheDir == NULL) || (cacheName == NULL)) {
- return 1;
- }
-
- // Set cache file Name
- mCacheName = cacheName;
-
- // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
- mCacheDir = cacheDir;
- if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
- mCacheDir.push_back('/');
- }
-
- if (!isCacheable()) {
- return 1;
- }
-
- std::string objPath = getCachedObjectPath();
- std::string infoPath = getCacheInfoPath();
-
- // Locks for reading object file and info file.
- FileMutex<FileBase::kReadLock> objFileMutex(objPath);
- FileMutex<FileBase::kReadLock> infoFileMutex(infoPath);
-
- // Aquire read lock for object file.
- if (objFileMutex.hasError() || !objFileMutex.lock()) {
- ALOGE("Unable to acquire the lock for %s! (%s)", objPath.c_str(),
- objFileMutex.getErrorMessage().c_str());
- return 1;
- }
-
- // Aquire read lock for info file.
- if (infoFileMutex.hasError() || !infoFileMutex.lock()) {
- ALOGE("Unable to acquire the lock for %s! (%s)", infoPath.c_str(),
- infoFileMutex.getErrorMessage().c_str());
- return 1;
- }
-
- // Open the object file and info file
- InputFile objFile(objPath);
- InputFile infoFile(infoPath);
-
- if (objFile.hasError()) {
- ALOGE("Unable to open %s for reading! (%s)", objPath.c_str(),
- objFile.getErrorMessage().c_str());
- return 1;
- }
-
- if (infoFile.hasError()) {
- ALOGE("Unable to open %s for reading! (%s)", infoPath.c_str(),
- infoFile.getErrorMessage().c_str());
- return 1;
- }
-
- MCCacheReader reader;
-
- // Register symbol lookup function
- if (mpExtSymbolLookupFn) {
- reader.registerSymbolCallback(mpExtSymbolLookupFn,
- mpExtSymbolLookupFnContext);
- }
-
- // Dependencies
- reader.addDependency(pathLibBCC_SHA1, sha1LibBCC_SHA1);
- reader.addDependency(pathLibRS, sha1LibRS);
-
- for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
- const SourceDependency *source_dep = mSourceDependencies[i];
- reader.addDependency(source_dep->getSourceName(),
- source_dep->getSHA1Checksum());
- }
-
- if (checkOnly)
- return !reader.checkCacheFile(objFile, infoFile, this);
-
- // Read cache file
- ScriptCached *cached = reader.readCacheFile(objFile, infoFile, this);
-
- if (!cached) {
- mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
- return 1;
- }
-
- mCached = cached;
- mStatus = ScriptStatus::Cached;
-
- // Dirty hack for libRS.
- // TODO(all): This dirty hack should be removed in the future.
- if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
- mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
- }
-
- return 0;
-}
-
-int RSScript::internalCompile(const CompilerOption &option) {
- // Create the ScriptCompiled object
- mCompiled = new (std::nothrow) ScriptCompiled(this);
-
- if (!mCompiled) {
- mErrorCode = BCC_OUT_OF_MEMORY;
- ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
- return 1;
- }
-
- mStatus = ScriptStatus::Compiled;
-
- // Register symbol lookup function
- if (mpExtSymbolLookupFn) {
- mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
- mpExtSymbolLookupFnContext);
- }
-
- // Set the main source module
- if (mCompiled->readModule(getSource().getModule()) != 0) {
- ALOGE("Unable to read source module\n");
- return 1;
- }
-
- // Compile and JIT the code
- if (mCompiled->compile(option) != 0) {
- ALOGE("Unable to compile.\n");
- return 1;
- }
-
- return 0;
-}
-
-int RSScript::writeCache() {
- // Not compiled script or encountered error during the compilation.
- if ((mStatus != ScriptStatus::Compiled) ||
- (getCompilerErrorMessage() == NULL))
- return 1;
-
- // Note: If we re-compile the script because the cached context slot not
- // available, then we don't have to write the cache.
-
- // Note: If the address of the context is not in the context slot, then
- // we don't have to cache it.
-
- if (isCacheable()) {
- std::string objPath = getCachedObjectPath();
- std::string infoPath = getCacheInfoPath();
-
- // Locks for writing object file and info file.
- FileMutex<FileBase::kWriteLock> objFileMutex(objPath);
- FileMutex<FileBase::kWriteLock> infoFileMutex(infoPath);
-
- // Aquire write lock for object file.
- if (objFileMutex.hasError() || !objFileMutex.lock()) {
- ALOGE("Unable to acquire the lock for %s! (%s)", objPath.c_str(),
- objFileMutex.getErrorMessage().c_str());
- return 1;
- }
-
- // Aquire write lock for info file.
- if (infoFileMutex.hasError() || !infoFileMutex.lock()) {
- ALOGE("Unable to acquire the lock for %s! (%s)", infoPath.c_str(),
- infoFileMutex.getErrorMessage().c_str());
- return 1;
- }
-
- // Open the object file and info file
- OutputFile objFile(objPath);
- OutputFile infoFile(infoPath);
-
- if (objFile.hasError()) {
- ALOGE("Unable to open %s for writing! (%s)", objPath.c_str(),
- objFile.getErrorMessage().c_str());
- return 1;
- }
-
- if (infoFile.hasError()) {
- ALOGE("Unable to open %s for writing! (%s)", infoPath.c_str(),
- infoFile.getErrorMessage().c_str());
- return 1;
- }
-
- MCCacheWriter writer;
-
-#ifdef TARGET_BUILD
- // Dependencies
- writer.addDependency(pathLibBCC_SHA1, sha1LibBCC_SHA1);
- writer.addDependency(pathLibRS, sha1LibRS);
-#endif
-
- for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
- const SourceDependency *source_dep = mSourceDependencies[i];
- writer.addDependency(source_dep->getSourceName(),
- source_dep->getSHA1Checksum());
- }
-
-
- // libRS is threadable dirty hack
- // TODO: This should be removed in the future
- uint32_t libRS_threadable = 0;
- if (mpExtSymbolLookupFn) {
- libRS_threadable =
- (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
- "__isThreadable");
- }
-
- if (!writer.writeCacheFile(objFile, infoFile, this, libRS_threadable)) {
- // Erase the file contents.
- objFile.truncate();
- infoFile.truncate();
-
- // Close the file such that we can removed it from the filesystem.
- objFile.close();
- infoFile.close();
-
- if (::unlink(objPath.c_str()) != 0) {
- ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
- objPath.c_str(), ::strerror(errno));
- }
-
- if (::unlink(infoPath.c_str()) != 0) {
- ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
- infoPath.c_str(), ::strerror(errno));
- }
- }
- } // isCacheable()
-
- return 0;
-}
-
-char const *RSScript::getCompilerErrorMessage() {
- if (mStatus != ScriptStatus::Compiled) {
- mErrorCode = BCC_INVALID_OPERATION;
- return NULL;
- }
-
- return mCompiled->getCompilerErrorMessage();
-}
-
-
-void *RSScript::lookup(const char *name) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->lookup(name);
- }
-
- case ScriptStatus::Cached: {
- return mCached->lookup(name);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- return NULL;
- }
- }
-}
-
-
-size_t RSScript::getExportVarCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportVarCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getExportVarCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getExportFuncCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportFuncCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getExportFuncCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getExportForEachCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportForEachCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getExportForEachCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getPragmaCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getPragmaCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getPragmaCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getFuncCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getFuncCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getFuncCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getObjectSlotCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getObjectSlotCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getObjectSlotCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-void RSScript::getExportVarList(size_t varListSize, void **varList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getExportVarList(varListSize, varList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportVarNameList(std::vector<std::string> &varList) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportVarNameList(varList);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-void RSScript::getExportFuncList(size_t funcListSize, void **funcList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getExportFuncList(funcListSize, funcList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportFuncNameList(std::vector<std::string> &funcList) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportFuncNameList(funcList);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportForEachList(size_t funcListSize, void **funcList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getExportForEachList(funcListSize, funcList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportForEachNameList(std::vector<std::string> &forEachList) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportForEachNameList(forEachList);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getPragmaList(size_t pragmaListSize,
- char const **keyList,
- char const **valueList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-void RSScript::getFuncInfoList(size_t funcInfoListSize,
- FuncInfo *funcInfoList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-void RSScript::getObjectSlotList(size_t objectSlotListSize,
- uint32_t *objectSlotList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-int RSScript::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
- mpExtSymbolLookupFn = pFn;
- mpExtSymbolLookupFnContext = pContext;
-
- if (mStatus != ScriptStatus::Unknown) {
- mErrorCode = BCC_INVALID_OPERATION;
- ALOGE("Invalid operation: %s\n", __func__);
- return 1;
- }
- return 0;
-}
-
-bool RSScript::isCacheable() const {
- if (getBooleanProp("debug.bcc.nocache")) {
- // Android system environment property: Disables the cache mechanism by
- // setting "debug.bcc.nocache". So we will not load the cache file any
- // way.
- return false;
- }
-
- if (mCacheDir.empty() || mCacheName.empty()) {
- // The application developer has not specified the cachePath, so
- // we don't know where to open the cache file.
- return false;
- }
-
- return true;
-}
-
-size_t RSScript::getELFSize() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getELFSize();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getELFSize();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-const char *RSScript::getELF() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getELF();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getELF();
- }
-
- default: {
- return NULL;
- }
- }
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/RSScript.h b/lib/ExecutionEngine/RSScript.h
index 4fc1f90..1ae9c9d 100644
--- a/lib/ExecutionEngine/RSScript.h
+++ b/lib/ExecutionEngine/RSScript.h
@@ -17,237 +17,94 @@
#ifndef BCC_EXECUTION_ENGINE_RS_SCRIPT_H
#define BCC_EXECUTION_ENGINE_RS_SCRIPT_H
-#include <vector>
#include <string>
-#include <stdint.h>
-#include <stddef.h>
-
#include <llvm/ADT/SmallVector.h>
#include <llvm/Support/CodeGen.h>
-#include <bcc/bcc.h>
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
#include "Script.h"
-namespace llvm {
- class Module;
- class GDBJITRegistrar;
-}
-
namespace bcc {
- class RSInfo;
- class ScriptCompiled;
- class ScriptCached;
- class Source;
- struct CompilerOption;
- namespace ScriptStatus {
- enum StatusType {
- Unknown,
- Compiled,
- Cached
- };
- }
+class RSInfo;
+class Source;
- namespace ScriptObject {
- enum ObjectType {
- Unknown,
- Relocatable,
- SharedObject,
- Executable,
- };
- }
-
- class RSScript : public Script {
- public:
- class SourceDependency {
- private:
- std::string mSourceName;
- uint8_t mSHA1[20];
-
- public:
- SourceDependency(const std::string &pSourceName,
- const uint8_t *pSHA1);
-
- inline const std::string &getSourceName() const
- { return mSourceName; }
-
- inline const uint8_t *getSHA1Checksum() const
- { return mSHA1; }
- };
- typedef llvm::SmallVectorImpl<SourceDependency *> SourceDependencyListTy;
-
+class RSScript : public Script {
+public:
+ class SourceDependency {
private:
- int mErrorCode;
-
- ScriptStatus::StatusType mStatus;
- // The type of the object behind this script after compilation. For
- // example, after returning from a successful call to prepareRelocatable(),
- // the value of mObjectType will be ScriptObject::Relocatable.
- ScriptObject::ObjectType mObjectType;
-
- union {
- ScriptCompiled *mCompiled;
- ScriptCached *mCached;
- };
-
- std::string mCacheDir;
- std::string mCacheName;
-
- inline std::string getCachedObjectPath() const {
- return std::string(mCacheDir + mCacheName + ".o");
- }
-
- inline std::string getCacheInfoPath() const {
- return getCachedObjectPath().append(".info");
- }
-
- bool mIsContextSlotNotAvail;
-
- llvm::SmallVector<SourceDependency *, 4> mSourceDependencies;
-
- const RSInfo *mInfo;
-
- // External Function List
- std::vector<char const *> mUserDefinedExternalSymbols;
-
- // Register Symbol Lookup Function
- BCCSymbolLookupFn mpExtSymbolLookupFn;
- void *mpExtSymbolLookupFnContext;
-
- // This will be invoked when the containing source has been reset.
- virtual bool doReset();
-
- // Reset the state of this script object
- void resetState();
+ std::string mSourceName;
+ uint8_t mSHA1[20];
public:
- RSScript(Source &pSource);
+ SourceDependency(const std::string &pSourceName,
+ const uint8_t *pSHA1);
- ~RSScript();
+ inline const std::string &getSourceName() const
+ { return mSourceName; }
- // Add dependency information for this script given the source named
- // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
- // false on error.
- bool addSourceDependency(const std::string &pSourceName,
- const uint8_t *pSHA1);
+ inline const uint8_t *getSHA1Checksum() const
+ { return mSHA1; }
+ };
+ typedef llvm::SmallVectorImpl<SourceDependency *> SourceDependencyListTy;
- const SourceDependencyListTy &getSourceDependencies() const
- { return mSourceDependencies; }
-
- // Set the associated RSInfo of the script.
- void setInfo(const RSInfo *pInfo)
- { mInfo = pInfo; }
-
- const RSInfo *getInfo() const
- { return mInfo; }
-
- void markExternalSymbol(char const *name) {
- mUserDefinedExternalSymbols.push_back(name);
- }
-
- std::vector<char const *> const &getUserDefinedExternalSymbols() const {
- return mUserDefinedExternalSymbols;
- }
-
- int prepareExecutable(char const *cacheDir,
- char const *cacheName,
- unsigned long flags);
- int writeCache();
-
- /*
- * Link the given bitcodes in mSource to shared object (.so).
- *
- * Currently, it requires one to provide the relocatable object files with
- * given bitcodes to output a shared object.
- *
- * The usage of this function is flexible. You can have a relocatable object
- * compiled before and pass it in objPath to generate shared object. If the
- * objPath is NULL, we'll invoke prepareRelocatable() to get .o first (if
- * you haven't done that yet) and then link the output relocatable object
- * file to .so in dsoPath.
- *
- * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
- *
- */
- int prepareSharedObject(char const *objPath,
- char const *dsoPath,
- unsigned long flags);
-
- int prepareRelocatable(char const *objPath,
- llvm::Reloc::Model RelocModel,
- unsigned long flags);
-
- char const *getCompilerErrorMessage();
-
- void *lookup(const char *name);
-
- size_t getExportVarCount() const;
-
- size_t getExportFuncCount() const;
-
- size_t getExportForEachCount() const;
-
- size_t getPragmaCount() const;
-
- size_t getFuncCount() const;
-
- size_t getObjectSlotCount() const;
-
- void getExportVarList(size_t size, void **list);
-
- void getExportFuncList(size_t size, void **list);
-
- void getExportForEachList(size_t size, void **list);
-
- void getExportVarNameList(std::vector<std::string> &list);
-
- void getExportFuncNameList(std::vector<std::string> &list);
-
- void getExportForEachNameList(std::vector<std::string> &list);
-
- void getPragmaList(size_t size,
- char const **keyList,
- char const **valueList);
-
- void getFuncInfoList(size_t size, FuncInfo *list);
-
- void getObjectSlotList(size_t size, uint32_t *list);
-
- size_t getELFSize() const;
-
- const char *getELF() const;
-
- int registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext);
-
- bool isCacheable() const;
-
- void setError(int error) {
- if (mErrorCode == BCC_NO_ERROR && error != BCC_NO_ERROR) {
- mErrorCode = error;
- }
- }
-
- int getError() {
- int result = mErrorCode;
- mErrorCode = BCC_NO_ERROR;
- return result;
- }
-
- private:
- //
- // It returns 0 if there's a cache hit.
- //
- // Side effect: it will set mCacheDir, mCacheName.
- int internalLoadCache(char const *cacheDir, char const *cacheName,
- bool checkOnly);
-
- int internalCompile(const CompilerOption&);
+ // This is one-one mapping with the llvm::CodeGenOpt::Level in
+ // llvm/Support/CodeGen.h. Therefore, value of this type can safely cast
+ // to llvm::CodeGenOpt::Level. This makes RSScript LLVM-free.
+ enum OptimizationLevel {
+ kOptLvl0, // -O0
+ kOptLvl1, // -O1
+ kOptLvl2, // -O2, -Os
+ kOptLvl3 // -O3
};
-} // namespace bcc
+private:
+ llvm::SmallVector<SourceDependency *, 4> mSourceDependencies;
+
+ const RSInfo *mInfo;
+
+ unsigned mCompilerVersion;
+
+ OptimizationLevel mOptimizationLevel;
+
+private:
+ // This will be invoked when the containing source has been reset.
+ virtual bool doReset();
+
+public:
+ RSScript(Source &pSource);
+
+ // Add dependency information for this script given the source named
+ // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
+ // false on error.
+ bool addSourceDependency(const std::string &pSourceName,
+ const uint8_t *pSHA1);
+
+ const SourceDependencyListTy &getSourceDependencies() const
+ { return mSourceDependencies; }
+
+ // Set the associated RSInfo of the script.
+ void setInfo(const RSInfo *pInfo)
+ { mInfo = pInfo; }
+
+ const RSInfo *getInfo() const
+ { return mInfo; }
+
+ void setCompilerVersion(unsigned pCompilerVersion)
+ { mCompilerVersion = pCompilerVersion; }
+
+ unsigned getCompilerVersion() const
+ { return mCompilerVersion; }
+
+ void setOptimizationLevel(OptimizationLevel pOptimizationLevel)
+ { mOptimizationLevel = pOptimizationLevel; }
+
+ OptimizationLevel getOptimizationLevel() const
+ { return mOptimizationLevel; }
+
+ ~RSScript();
+};
+
+} // end namespace bcc
#endif // BCC_EXECUTION_ENGINE_RS_SCRIPT_H
diff --git a/lib/ExecutionEngine/ScriptCached.cpp b/lib/ExecutionEngine/ScriptCached.cpp
deleted file mode 100644
index bbfac2b..0000000
--- a/lib/ExecutionEngine/ScriptCached.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Config.h"
-
-#include "ScriptCached.h"
-
-#include "DebugHelper.h"
-
-#include <stdlib.h>
-
-namespace bcc {
-
-ScriptCached::~ScriptCached() {
- // Deallocate string pool, exported var list, exported func list
- if (mpStringPoolRaw) { free(mpStringPoolRaw); }
- if (mpExportVars) { free(mpExportVars); }
- if (mpExportFuncs) { free(mpExportFuncs); }
- if (mpExportForEach) { free(mpExportForEach); }
- if (mpObjectSlotList) { free(mpObjectSlotList); }
-}
-
-void ScriptCached::getExportVarList(size_t varListSize, void **varList) {
- if (varList) {
- size_t varCount = getExportVarCount();
-
- if (varCount > varListSize) {
- varCount = varListSize;
- }
-
- memcpy(varList, mpExportVars->cached_addr_list, sizeof(void *) * varCount);
- }
-}
-
-
-void ScriptCached::getExportFuncList(size_t funcListSize, void **funcList) {
- if (funcList) {
- size_t funcCount = getExportFuncCount();
-
- if (funcCount > funcListSize) {
- funcCount = funcListSize;
- }
-
- memcpy(funcList, mpExportFuncs->cached_addr_list,
- sizeof(void *) * funcCount);
- }
-}
-
-
-void ScriptCached::getExportForEachList(size_t forEachListSize,
- void **forEachList) {
- if (forEachList) {
- size_t forEachCount = getExportForEachCount();
-
- if (forEachCount > forEachListSize) {
- forEachCount = forEachListSize;
- }
-
- memcpy(forEachList, mpExportForEach->cached_addr_list,
- sizeof(void *) * forEachCount);
- }
-}
-
-
-void ScriptCached::getPragmaList(size_t pragmaListSize,
- char const **keyList,
- char const **valueList) {
- size_t pragmaCount = getPragmaCount();
-
- if (pragmaCount > pragmaListSize) {
- pragmaCount = pragmaListSize;
- }
-
- if (keyList) {
- for (size_t i = 0; i < pragmaCount; ++i) {
- *keyList++ = mPragmas[i].first;
- }
- }
-
- if (valueList) {
- for (size_t i = 0; i < pragmaCount; ++i) {
- *valueList++ = mPragmas[i].second;
- }
- }
-}
-
-
-void ScriptCached::getObjectSlotList(size_t objectSlotListSize,
- uint32_t *objectSlotList) {
- if (objectSlotList) {
- size_t objectSlotCount = getObjectSlotCount();
-
- if (objectSlotCount > objectSlotListSize) {
- objectSlotCount = objectSlotListSize;
- }
-
- memcpy(objectSlotList, mpObjectSlotList->object_slot_list,
- sizeof(uint32_t) * objectSlotCount);
- }
-}
-
-
-void *ScriptCached::lookup(const char *name) {
- return rsloaderGetSymbolAddress(mRSExecutable, name);
-}
-
-void ScriptCached::getFuncInfoList(size_t funcInfoListSize,
- FuncInfo *funcInfoList) {
- if (funcInfoList) {
- size_t funcCount = getFuncCount();
-
- if (funcCount > funcInfoListSize) {
- funcCount = funcInfoListSize;
- }
-
- FuncInfo *info = funcInfoList;
- for (FuncTable::const_iterator
- I = mFunctions.begin(), E = mFunctions.end();
- I != E && funcCount > 0; ++I, ++info, --funcCount) {
- info->name = I->first.c_str();
- info->addr = I->second.first;
- info->size = I->second.second;
- }
- }
-}
-
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/ScriptCached.h b/lib/ExecutionEngine/ScriptCached.h
deleted file mode 100644
index e24a714..0000000
--- a/lib/ExecutionEngine/ScriptCached.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_SCRIPTCACHED_H
-#define BCC_SCRIPTCACHED_H
-
-#include "Config.h"
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "librsloader.h"
-
-#include <llvm/ADT/SmallVector.h>
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <stddef.h>
-
-namespace llvm {
- class Module;
-}
-
-namespace bcc {
- class Script;
-
- class ScriptCached {
- friend class CacheReader;
- friend class MCCacheReader;
-
- private:
- enum { SMALL_VECTOR_QUICKN = 16 };
-
- typedef llvm::SmallVector<std::pair<char const *, char const *>,
- SMALL_VECTOR_QUICKN> PragmaList;
-
- typedef std::map<std::string, std::pair<void *, size_t> > FuncTable;
-
- private:
- Script *mpOwner;
-
- MCO_ExportVarList *mpExportVars;
- MCO_ExportFuncList *mpExportFuncs;
- MCO_ExportForEachList *mpExportForEach;
- PragmaList mPragmas;
- MCO_ObjectSlotList *mpObjectSlotList;
-
- FuncTable mFunctions;
-
- RSExecRef mRSExecutable;
- llvm::SmallVector<char, 1024> mCachedELFExecutable;
-
- MCO_StringPool *mpStringPoolRaw;
- std::vector<char const *> mStringPool;
-
- bool mLibRSThreadable;
-
- public:
- ScriptCached(Script *owner)
- : mpOwner(owner),
- mpExportVars(NULL),
- mpExportFuncs(NULL),
- mpExportForEach(NULL),
- mpObjectSlotList(NULL),
- mpStringPoolRaw(NULL),
- mLibRSThreadable(false) {
- }
-
- ~ScriptCached();
-
- void *lookup(const char *name);
-
-
- size_t getExportVarCount() const {
- return mpExportVars->count;
- }
-
- size_t getExportFuncCount() const {
- return mpExportFuncs->count;
- }
-
- size_t getExportForEachCount() const {
- return mpExportForEach->count;
- }
-
- size_t getPragmaCount() const {
- return mPragmas.size();
- }
-
- size_t getFuncCount() const {
- return mFunctions.size();
- }
-
- size_t getObjectSlotCount() const {
- return mpObjectSlotList->count;
- }
-
- void getExportVarList(size_t varListSize, void **varList);
-
- void getExportFuncList(size_t funcListSize, void **funcList);
-
- void getExportForEachList(size_t forEachListSize, void **forEachList);
-
- void getPragmaList(size_t pragmaListSize,
- char const **keyList,
- char const **valueList);
-
- void getFuncInfoList(size_t funcInfoListSize, FuncInfo *funcNameList);
-
- void getObjectSlotList(size_t objectSlotListSize,
- uint32_t *objectSlotList);
-
- const char *getELF() const {
- return &*mCachedELFExecutable.begin();
- }
-
- size_t getELFSize() const {
- return mCachedELFExecutable.size();
- }
-
- // Dirty hack for libRS.
- // TODO(all): This should be removed in the future.
- bool isLibRSThreadable() const {
- return mLibRSThreadable;
- }
-
-#if 0
- void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
- mCompiler.registerSymbolCallback(pFn, pContext);
- }
-#endif
- };
-
-} // namespace bcc
-
-#endif // BCC_SCRIPTCACHED_H
diff --git a/lib/ExecutionEngine/ScriptCompiled.cpp b/lib/ExecutionEngine/ScriptCompiled.cpp
deleted file mode 100644
index 4f2bb1b..0000000
--- a/lib/ExecutionEngine/ScriptCompiled.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ScriptCompiled.h"
-
-#include "bcc_internal.h"
-#include "DebugHelper.h"
-
-namespace bcc {
-
-ScriptCompiled::~ScriptCompiled() {
-}
-
-void ScriptCompiled::getExportVarList(size_t varListSize, void **varList) {
- if (varList) {
- size_t varCount = getExportVarCount();
-
- if (varCount > varListSize) {
- varCount = varListSize;
- }
-
- for (ExportVarList::const_iterator
- I = mExportVars.begin(), E = mExportVars.end();
- I != E && varCount > 0; ++I, --varCount) {
- *varList++ = *I;
- }
- }
-}
-
-void ScriptCompiled::getExportVarNameList(std::vector<std::string> &varList) {
- varList = mExportVarsName;
-}
-
-
-void ScriptCompiled::getExportFuncNameList(std::vector<std::string> &funcList) {
- funcList = mExportFuncsName;
-}
-
-
-void ScriptCompiled::getExportForEachNameList(std::vector<std::string> &forEachList) {
- forEachList = mExportForEachName;
-}
-
-
-void ScriptCompiled::getExportFuncList(size_t funcListSize, void **funcList) {
- if (funcList) {
- size_t funcCount = getExportFuncCount();
-
- if (funcCount > funcListSize) {
- funcCount = funcListSize;
- }
-
- for (ExportFuncList::const_iterator
- I = mExportFuncs.begin(), E = mExportFuncs.end();
- I != E && funcCount > 0; ++I, --funcCount) {
- *funcList++ = *I;
- }
- }
-}
-
-
-void ScriptCompiled::getExportForEachList(size_t forEachListSize,
- void **forEachList) {
- if (forEachList) {
- size_t forEachCount = getExportForEachCount();
-
- if (forEachCount > forEachListSize) {
- forEachCount = forEachListSize;
- }
-
- for (ExportForEachList::const_iterator
- I = mExportForEach.begin(), E = mExportForEach.end();
- I != E && forEachCount > 0; ++I, --forEachCount) {
- *forEachList++ = *I;
- }
- }
-}
-
-
-void ScriptCompiled::getPragmaList(size_t pragmaListSize,
- char const **keyList,
- char const **valueList) {
- size_t pragmaCount = getPragmaCount();
-
- if (pragmaCount > pragmaListSize) {
- pragmaCount = pragmaListSize;
- }
-
- for (PragmaList::const_iterator
- I = mPragmas.begin(), E = mPragmas.end();
- I != E && pragmaCount > 0; ++I, --pragmaCount) {
- if (keyList) { *keyList++ = I->first.c_str(); }
- if (valueList) { *valueList++ = I->second.c_str(); }
- }
-}
-
-
-void *ScriptCompiled::lookup(const char *name) {
- return mCompiler.getSymbolAddress(name);
-}
-
-
-void ScriptCompiled::getFuncInfoList(size_t funcInfoListSize,
- FuncInfo *funcInfoList) {
- if (funcInfoList) {
- size_t funcCount = getFuncCount();
-
- if (funcCount > funcInfoListSize) {
- funcCount = funcInfoListSize;
- }
-
- FuncInfo *info = funcInfoList;
- for (FuncInfoMap::const_iterator
- I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
- I != E && funcCount > 0; ++I, ++info, --funcCount) {
- info->name = I->first.c_str();
- info->addr = I->second->addr;
- info->size = I->second->size;
- }
- }
-}
-
-void ScriptCompiled::getObjectSlotList(size_t objectSlotListSize,
- uint32_t *objectSlotList) {
- if (objectSlotList) {
- size_t objectSlotCount = getObjectSlotCount();
-
- if (objectSlotCount > objectSlotListSize) {
- objectSlotCount = objectSlotListSize;
- }
-
- for (ObjectSlotList::const_iterator
- I = mObjectSlots.begin(), E = mObjectSlots.end();
- I != E && objectSlotCount > 0; ++I, --objectSlotCount) {
- *objectSlotList++ = *I;
- }
- }
-
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
deleted file mode 100644
index e96dbe2..0000000
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_SCRIPTCOMPILED_H
-#define BCC_SCRIPTCOMPILED_H
-
-#include <list>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <bcc/bcc.h>
-
-#include "Compiler.h"
-#include "RSScript.h"
-
-namespace llvm {
- class Module;
-}
-
-namespace bcc {
- struct CompilerOption;
-
- class ScriptCompiled {
- friend class Compiler;
- friend class CodeEmitter;
-
- private:
- typedef std::list<std::pair<std::string, std::string> > PragmaList;
- typedef std::list<void*> ExportVarList;
- typedef std::list<void*> ExportFuncList;
- typedef std::list<void*> ExportForEachList;
- typedef std::map<std::string, FuncInfo *> FuncInfoMap;
- typedef std::list<uint32_t> ObjectSlotList;
-
- private:
- RSScript *mpOwner;
-
- Compiler mCompiler;
-
- ExportVarList mExportVars;
-
- std::vector<std::string> mExportVarsName;
- std::vector<std::string> mExportFuncsName;
- std::vector<std::string> mExportForEachName;
-
- ExportFuncList mExportFuncs;
- ExportForEachList mExportForEach;
- PragmaList mPragmas;
- ObjectSlotList mObjectSlots;
-
- FuncInfoMap mEmittedFunctions;
-
- public:
- ScriptCompiled(RSScript *owner)
- : mpOwner(owner), mCompiler(this)
- {
- }
-
- ~ScriptCompiled();
-
- int readModule(llvm::Module &pModule) {
- return mCompiler.readModule(pModule);
- }
-
- int compile(const CompilerOption &option) {
- return mCompiler.compile(option);
- }
-
- char const *getCompilerErrorMessage() {
- return mCompiler.getErrorMessage();
- }
-
- void *lookup(const char *name);
-
- size_t getExportVarCount() const {
- return mExportVars.size();
- }
-
- size_t getExportFuncCount() const {
- return mExportFuncs.size();
- }
-
- size_t getExportForEachCount() const {
- return mExportForEach.size();
- }
-
- size_t getPragmaCount() const {
- return mPragmas.size();
- }
-
- size_t getFuncCount() const {
- return mEmittedFunctions.size();
- }
-
- size_t getObjectSlotCount() const {
- return mObjectSlots.size();
- }
-
- void getExportVarList(size_t varListSize, void **varList);
-
- void getExportFuncList(size_t funcListSize, void **funcList);
-
- void getExportForEachList(size_t forEachListSize, void **forEachList);
-
- void getExportVarNameList(std::vector<std::string> &varList);
-
- void getExportFuncNameList(std::vector<std::string> &funcList);
-
- void getExportForEachNameList(std::vector<std::string> &forEachList);
-
- void getPragmaList(size_t pragmaListSize,
- char const **keyList,
- char const **valueList);
-
- void getFuncInfoList(size_t funcInfoListSize,
- FuncInfo *funcInfoList);
-
- void getObjectSlotList(size_t objectSlotListSize,
- uint32_t *objectSlotList);
-
- std::vector<char const *> const & getUserDefinedExternalSymbols() const {
- return mpOwner->getUserDefinedExternalSymbols();
- }
-
- const char *getELF() const {
- return &*mCompiler.getELF().begin();
- }
-
- size_t getELFSize() const {
- return mCompiler.getELF().size();
- }
-
- void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
- mCompiler.registerSymbolCallback(pFn, pContext);
- }
- };
-
-} // namespace bcc
-
-#endif // BCC_SCRIPTCOMPILED_H
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index 6baa3e0..b830ec2 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -19,22 +19,20 @@
#include <bcc/bcc.h>
-#include <string>
+#include <llvm/Support/CodeGen.h>
#include <utils/StopWatch.h>
-#include "Config.h"
-
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "BCCContext.h"
-#include "Compiler.h"
#include "DebugHelper.h"
+#include "Initialization.h"
+#include "RSExecutable.h"
#include "RSScript.h"
#include "Sha1Helper.h"
#include "Source.h"
+#include "bcc_internal.h"
+#include <bcinfo/BitcodeWrapper.h>
+
using namespace bcc;
namespace llvm {
@@ -54,21 +52,24 @@
extern "C" BCCScriptRef bccCreateScript() {
BCC_FUNC_LOGGER();
bccPrintBuildStamp();
- // FIXME: This is a workaround for this API: use global BCC context and
- // create an empty source to create a Script object.
- BCCContext *context = BCCContext::GetOrCreateGlobalContext();
- if (context == NULL) {
- return NULL;
+ init::Initialize();
+ RSScriptContext *rsctx = new (std::nothrow) RSScriptContext();
+ if (rsctx != NULL) {
+ rsctx->script = NULL;
+ rsctx->result = NULL;
}
-
- Source *source = Source::CreateEmpty(*context, "empty");
- return wrap(new RSScript(*source));
+ return wrap(rsctx);
}
extern "C" void bccDisposeScript(BCCScriptRef script) {
BCC_FUNC_LOGGER();
- delete unwrap(script);
+ RSScriptContext *rsctx = unwrap(script);
+ if (rsctx != NULL) {
+ delete rsctx->script;
+ delete rsctx->result;
+ }
+ delete rsctx;
}
@@ -76,16 +77,18 @@
BCCSymbolLookupFn pFn,
void *pContext) {
BCC_FUNC_LOGGER();
- return unwrap(script)->registerSymbolCallback(pFn, pContext);
+ unwrap(script)->driver.setRSRuntimeLookupFunction(pFn);
+ unwrap(script)->driver.setRSRuntimeLookupContext(pContext);
+ return BCC_NO_ERROR;
}
extern "C" int bccGetError(BCCScriptRef script) {
BCC_FUNC_LOGGER();
- return unwrap(script)->getError();
+ return BCC_DEPRECATED_API;
}
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(RSScriptContext *pCtx,
char const *pName,
char const *pBitcode,
size_t pBitcodeSize,
@@ -100,76 +103,119 @@
ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
}
- BCCContext *context = BCCContext::GetOrCreateGlobalContext();
- if (context == NULL) {
- return false;
- }
-
- Source *source = Source::CreateFromBuffer(*context, pName,
+ Source *source = Source::CreateFromBuffer(pCtx->context, pName,
pBitcode, pBitcodeSize);
if (source == NULL) {
return false;
}
+ if (pCtx->script == NULL) {
+ pCtx->script = new (std::nothrow) RSScript(*source);
+ if (pCtx->script == NULL) {
+ ALOGE("Out of memory during script creation.");
+ return false;
+ }
+ } else {
+ bool result;
+ if (pIsLink) {
+ result = pCtx->script->mergeSource(*source);
+ } else {
+ result = pCtx->script->reset(*source);
+ }
+ if (!result) {
+ return false;
+ } else {
+ bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
+ pCtx->script->setCompilerVersion(wrapper.getCompilerVersion());
+ pCtx->script->setOptimizationLevel(
+ static_cast<RSScript::OptimizationLevel>(
+ wrapper.getOptimizationLevel()));
+ }
+ }
+
if (need_dependency_check) {
uint8_t sha1[20];
calcSHA1(sha1, pBitcode, pBitcodeSize);
- if (!pScript->addSourceDependency(pName, sha1)) {
+ if (!pCtx->script->addSourceDependency(pName, sha1)) {
return false;
}
}
- return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+ return true;
}
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(RSScriptContext *pCtx,
llvm::Module *pModule,
bool pIsLink) {
- if (pModule == NULL)
- return false;
-
- BCCContext *context = BCCContext::GetOrCreateGlobalContext();
- if (context == NULL) {
- return false;
- }
-
if (pModule == NULL) {
ALOGE("Cannot add null module to script!");
return false;
}
- Source *source = Source::CreateFromModule(*context, *pModule, true);
+ Source *source = Source::CreateFromModule(pCtx->context, *pModule, true);
if (source == NULL) {
return false;
}
- return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+ if (pCtx->script == NULL) {
+ pCtx->script = new (std::nothrow) RSScript(*source);
+ if (pCtx->script == NULL) {
+ ALOGE("Out of memory during script creation.");
+ return false;
+ }
+ } else {
+ bool result;
+ if (pIsLink) {
+ result = pCtx->script->mergeSource(*source);
+ } else {
+ result = pCtx->script->reset(*source);
+ }
+ if (!result) {
+ return false;
+ }
+ }
+
+ return true;
}
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(RSScriptContext *pCtx,
char const *pPath,
unsigned long pFlags,
bool pIsLink) {
bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
- BCCContext *context = BCCContext::GetOrCreateGlobalContext();
- if (context == NULL) {
+
+ Source *source = Source::CreateFromFile(pCtx->context, pPath);
+ if (source == NULL) {
return false;
}
- Source *source = Source::CreateFromFile(*context, pPath);
- if (source == NULL) {
- return false;
+ if (pCtx->script == NULL) {
+ pCtx->script = new (std::nothrow) RSScript(*source);
+ if (pCtx->script == NULL) {
+ ALOGE("Out of memory during script creation.");
+ return false;
+ }
+ } else {
+ bool result;
+ if (pIsLink) {
+ result = pCtx->script->mergeSource(*source);
+ } else {
+ result = pCtx->script->reset(*source);
+ }
+ if (!result) {
+ return false;
+ }
}
if (need_dependency_check) {
uint8_t sha1[20];
calcFileSHA1(sha1, pPath);
- if (!pScript->addSourceDependency(pPath, sha1)) {
+ if (!pCtx->script->addSourceDependency(pPath, sha1)) {
return false;
}
}
- return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+ return true;
}
extern "C" int bccReadBC(BCCScriptRef script,
@@ -226,7 +272,7 @@
extern "C" void bccMarkExternalSymbol(BCCScriptRef script, char const *name) {
BCC_FUNC_LOGGER();
- unwrap(script)->markExternalSymbol(name);
+ return /* BCC_DEPRECATED_API */;
}
@@ -235,32 +281,7 @@
bccRelocModelEnum RelocModel,
unsigned long flags) {
BCC_FUNC_LOGGER();
- llvm::Reloc::Model RM;
-
- switch (RelocModel) {
- case bccRelocDefault: {
- RM = llvm::Reloc::Default;
- break;
- }
- case bccRelocStatic: {
- RM = llvm::Reloc::Static;
- break;
- }
- case bccRelocPIC: {
- RM = llvm::Reloc::PIC_;
- break;
- }
- case bccRelocDynamicNoPIC: {
- RM = llvm::Reloc::DynamicNoPIC;
- break;
- }
- default: {
- ALOGE("Unrecognized relocation model for bccPrepareObject!");
- return BCC_INVALID_VALUE;
- }
- }
-
- return unwrap(script)->prepareRelocatable(objPath, RM, flags);
+ return BCC_DEPRECATED_API;
}
@@ -269,7 +290,7 @@
char const *dsoPath,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->prepareSharedObject(objPath, dsoPath, flags);
+ return BCC_DEPRECATED_API;
}
@@ -281,14 +302,41 @@
android::StopWatch compileTimer("bcc: PrepareExecutable time");
- return unwrap(script)->prepareExecutable(cacheDir, cacheName, flags);
+ RSScriptContext *rsctx = unwrap(script);
+
+ if (rsctx->script == NULL) {
+ return 1;
+ }
+
+ // Construct the output path.
+ std::string output_path(cacheDir);
+ if (!output_path.empty() && (*output_path.rbegin() != '/')) {
+ output_path.append(1, '/');
+ }
+ output_path.append(cacheName);
+ output_path.append(".o");
+
+ // Make sure the result container is clean.
+ if (rsctx->result != NULL) {
+ delete rsctx->result;
+ rsctx->result = NULL;
+ }
+
+ rsctx->result = rsctx->driver.build(*rsctx->script, output_path);
+
+ return (rsctx->result == NULL);
}
extern "C" void *bccGetFuncAddr(BCCScriptRef script, char const *funcname) {
BCC_FUNC_LOGGER();
- void *addr = unwrap(script)->lookup(funcname);
+ RSScriptContext *rsctx = unwrap(script);
+
+ void *addr = NULL;
+ if (rsctx->result != NULL) {
+ addr = rsctx->result->getSymbolAddress(funcname);
+ }
#if DEBUG_BCC_REFLECT
ALOGD("Function Address: %s --> %p\n", funcname, addr);
@@ -303,19 +351,27 @@
void **varList) {
BCC_FUNC_LOGGER();
- if (varList) {
- unwrap(script)->getExportVarList(varListSize, varList);
-
-#if DEBUG_BCC_REFLECT
- size_t count = unwrap(script)->getExportVarCount();
- ALOGD("ExportVarCount = %lu\n", (unsigned long)count);
+ const RSScriptContext *rsctx = unwrap(script);
+ if (varList && rsctx->result) {
+ const android::Vector<void *> &export_var_addrs =
+ rsctx->result->getExportVarAddrs();
+ size_t count = export_var_addrs.size();
if (count > varListSize) {
count = varListSize;
}
for (size_t i = 0; i < count; ++i) {
- ALOGD("ExportVarList[%lu] = %p\n", (unsigned long)i, varList[i]);
+ varList[i] = export_var_addrs[i];
+ }
+
+#if DEBUG_BCC_REFLECT
+ ALOGD("ExportVarCount = %lu\n",
+ static_cast<unsigned long>(export_var_addrs.size()));
+
+ for (size_t i = 0; i < count; ++i) {
+ ALOGD("ExportVarList[%lu] = %p\n", static_cast<unsigned long>(i),
+ varList[i]);
}
#endif
}
@@ -327,19 +383,27 @@
void **funcList) {
BCC_FUNC_LOGGER();
- if (funcList) {
- unwrap(script)->getExportFuncList(funcListSize, funcList);
-
-#if DEBUG_BCC_REFLECT
- size_t count = unwrap(script)->getExportFuncCount();
- ALOGD("ExportFuncCount = %lu\n", (unsigned long)count);
+ const RSScriptContext *rsctx = unwrap(script);
+ if (funcList && rsctx->result) {
+ const android::Vector<void *> &export_func_addrs =
+ rsctx->result->getExportFuncAddrs();
+ size_t count = export_func_addrs.size();
if (count > funcListSize) {
count = funcListSize;
}
for (size_t i = 0; i < count; ++i) {
- ALOGD("ExportFuncList[%lu] = %p\n", (unsigned long)i, funcList[i]);
+ funcList[i] = export_func_addrs[i];
+ }
+
+#if DEBUG_BCC_REFLECT
+ ALOGD("ExportFuncCount = %lu\n",
+ static_cast<unsigned long>(export_var_addrs.size()));
+
+ for (size_t i = 0; i < count; ++i) {
+ ALOGD("ExportFuncList[%lu] = %p\n", static_cast<unsigned long>(i),
+ varList[i]);
}
#endif
}
@@ -351,19 +415,27 @@
void **forEachList) {
BCC_FUNC_LOGGER();
- if (forEachList) {
- unwrap(script)->getExportForEachList(forEachListSize, forEachList);
-
-#if DEBUG_BCC_REFLECT
- size_t count = unwrap(script)->getExportForEachCount();
- ALOGD("ExportForEachCount = %lu\n", (unsigned long)count);
+ const RSScriptContext *rsctx = unwrap(script);
+ if (forEachList && rsctx->result) {
+ const android::Vector<void *> &export_foreach_func_addrs =
+ rsctx->result->getExportForeachFuncAddrs();
+ size_t count = export_foreach_func_addrs.size();
if (count > forEachListSize) {
count = forEachListSize;
}
for (size_t i = 0; i < count; ++i) {
- ALOGD("ExportForEachList[%lu] = %p\n", (unsigned long)i, forEachList[i]);
+ forEachList[i] = export_foreach_func_addrs[i];
+ }
+
+#if DEBUG_BCC_REFLECT
+ ALOGD("ExportForEachCount = %lu\n",
+ static_cast<unsigned long>(export_foreach_func_addrs.size()));
+
+ for (size_t i = 0; i < count; ++i) {
+ ALOGD("ExportForEachList[%lu] = %p\n", static_cast<unsigned long>(i),
+ forEachList[i]);
}
#endif
}
diff --git a/lib/ExecutionEngine/bcc_internal.h b/lib/ExecutionEngine/bcc_internal.h
index 553034c..c003d6c 100644
--- a/lib/ExecutionEngine/bcc_internal.h
+++ b/lib/ExecutionEngine/bcc_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,9 @@
#include <bcc/bcc.h>
+#include "BCCContext.h"
+#include "RSCompilerDriver.h"
+
#if defined(__cplusplus)
#define BCC_OPAQUE_TYPE_CONVERSION(TRANSPARENT_TYPE, OPAQUE_TYPE) \
@@ -35,17 +38,23 @@
}
namespace bcc {
- class RSScript;
- /* Function information struct */
- struct FuncInfo {
- char const *name;
- void *addr;
- size_t size;
- };
+class RSScript;
+class RSExecutable;
- BCC_OPAQUE_TYPE_CONVERSION(bcc::RSScript *, BCCScriptRef);
- BCC_OPAQUE_TYPE_CONVERSION(llvm::Module *, LLVMModuleRef);
+struct RSScriptContext {
+ // The context required in libbcc.
+ BCCContext context;
+ // The compiler driver
+ RSCompilerDriver driver;
+ // The script hold the source which is about to compile.
+ RSScript *script;
+ // The compilation result.
+ RSExecutable *result;
+};
+
+BCC_OPAQUE_TYPE_CONVERSION(bcc::RSScriptContext *, BCCScriptRef);
+BCC_OPAQUE_TYPE_CONVERSION(llvm::Module *, LLVMModuleRef);
} // namespace bcc