am ca1904d4: am 1957e34d: Merge "Add missed compiler support function for "/" and "%""
* commit 'ca1904d414062a381350f9081089f32ff12b7006':
Add missed compiler support function for "/" and "%"
diff --git a/Config.h b/Config.h
index b1ea833..c1f4133 100644
--- a/Config.h
+++ b/Config.h
@@ -1,7 +1,9 @@
#ifndef BCC_CONFIG_H
#define BCC_CONFIG_H
+#ifdef HAVE_BCC_CONFIG_MK_H
#include "ConfigFromMk.h"
+#endif
//---------------------------------------------------------------------------
// Configuration for Disassembler
diff --git a/bcinfo/MetadataExtractor.cpp b/bcinfo/MetadataExtractor.cpp
index 3be7e35..e4a2573 100644
--- a/bcinfo/MetadataExtractor.cpp
+++ b/bcinfo/MetadataExtractor.cpp
@@ -20,6 +20,7 @@
#define LOG_TAG "bcinfo"
#include <cutils/log.h>
+#include <cutils/properties.h>
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Bitcode/ReaderWriter.h"
@@ -221,6 +222,7 @@
// Check to see if we have any FP precision-related pragmas.
std::string Relaxed("rs_fp_relaxed");
std::string Imprecise("rs_fp_imprecise");
+ std::string Full("rs_fp_full");
bool RelaxedPragmaSeen = false;
bool ImprecisePragmaSeen = false;
@@ -246,6 +248,26 @@
mRSFloatPrecision = RS_FP_Relaxed;
}
+ // Provide an override for precsion via adb shell setprop
+ // adb shell setprop debug.rs.precision rs_fp_full
+ // adb shell setprop debug.rs.precision rs_fp_relaxed
+ // adb shell setprop debug.rs.precision rs_fp_imprecise
+ char PrecisionPropBuf[PROPERTY_VALUE_MAX];
+ const std::string PrecisionPropName("debug.rs.precision");
+ property_get("debug.rs.precision", PrecisionPropBuf, "");
+ if (PrecisionPropBuf[0]) {
+ if (!Relaxed.compare(PrecisionPropBuf)) {
+ ALOGE("Switching to RS FP relaxed mode via setprop");
+ mRSFloatPrecision = RS_FP_Relaxed;
+ } else if (!Imprecise.compare(PrecisionPropBuf)) {
+ ALOGE("Switching to RS FP imprecise mode via setprop");
+ mRSFloatPrecision = RS_FP_Imprecise;
+ } else if (!Full.compare(PrecisionPropBuf)) {
+ ALOGE("Switching to RS FP full mode via setprop");
+ mRSFloatPrecision = RS_FP_Full;
+ }
+ }
+
return;
}
diff --git a/bcinfo/tools/Android.mk b/bcinfo/tools/Android.mk
index 0d99f71..f7cf34b 100644
--- a/bcinfo/tools/Android.mk
+++ b/bcinfo/tools/Android.mk
@@ -16,6 +16,8 @@
LOCAL_PATH := $(call my-dir)
+LLVM_ROOT_PATH := external/llvm
+
# Executable for host
# ========================================================
include $(CLEAR_VARS)
@@ -28,6 +30,12 @@
LOCAL_SHARED_LIBRARIES := \
libbcinfo
+LOCAL_STATIC_LIBRARIES := \
+ libLLVMBitReader \
+ libLLVMBitWriter \
+ libLLVMCore \
+ libLLVMSupport
+
LOCAL_CFLAGS += -D__HOST__
LOCAL_C_INCLUDES := \
@@ -37,5 +45,6 @@
LOCAL_LDLIBS = -ldl
+include $(LLVM_ROOT_PATH)/llvm-host-build.mk
include $(BUILD_HOST_EXECUTABLE)
diff --git a/bcinfo/tools/main.cpp b/bcinfo/tools/main.cpp
index 1360c68..2d1e449 100644
--- a/bcinfo/tools/main.cpp
+++ b/bcinfo/tools/main.cpp
@@ -18,6 +18,16 @@
#include <bcinfo/BitcodeWrapper.h>
#include <bcinfo/MetadataExtractor.h>
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Assembly/AssemblyAnnotationWriter.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/ToolOutputFile.h>
+
#include <ctype.h>
#include <dlfcn.h>
#include <stdarg.h>
@@ -33,12 +43,14 @@
#include <unistd.h>
+#include <string>
#include <vector>
// This file corresponds to the standalone bcinfo tool. It prints a variety of
// information about a supplied bitcode input file.
-const char* inFile = NULL;
+std::string inFile;
+std::string outFile;
extern int opterr;
extern int optind;
@@ -72,6 +84,13 @@
}
inFile = argv[optind];
+
+ int l = inFile.length();
+ if (l > 3 && inFile[l-3] == '.' && inFile[l-2] == 'b' && inFile[l-1] == 'c') {
+ outFile = std::string(inFile.begin(), inFile.end() - 3) + ".ll";
+ } else {
+ outFile = inFile + ".ll";
+ }
return 1;
}
@@ -141,26 +160,26 @@
static size_t readBitcode(const char **bitcode) {
- if (!inFile) {
+ if (!inFile.length()) {
fprintf(stderr, "input file required\n");
- return NULL;
+ return 0;
}
struct stat statInFile;
- if (stat(inFile, &statInFile) < 0) {
+ if (stat(inFile.c_str(), &statInFile) < 0) {
fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno));
- return NULL;
+ return 0;
}
if (!S_ISREG(statInFile.st_mode)) {
fprintf(stderr, "Input file should be a regular file.\n");
- return NULL;
+ return 0;
}
- FILE *in = fopen(inFile, "r");
+ FILE *in = fopen(inFile.c_str(), "r");
if (!in) {
- fprintf(stderr, "Could not open input file %s\n", inFile);
- return NULL;
+ fprintf(stderr, "Could not open input file %s\n", inFile.c_str());
+ return 0;
}
size_t bitcodeSize = statInFile.st_size;
@@ -169,7 +188,7 @@
size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in);
if (nread != bitcodeSize)
- fprintf(stderr, "Could not read all of file %s\n", inFile);
+ fprintf(stderr, "Could not read all of file %s\n", inFile.c_str());
fclose(in);
return nread;
@@ -192,7 +211,6 @@
}
const char *bitcode = NULL;
- const char *translatedBitcode = NULL;
size_t bitcodeSize = readBitcode(&bitcode);
unsigned int version = 0;
@@ -209,25 +227,58 @@
printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion());
printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel());
- bcinfo::BitcodeTranslator *BT =
- new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version);
+ llvm::OwningPtr<bcinfo::BitcodeTranslator> BT;
+ BT.reset(new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version));
if (!BT->translate()) {
fprintf(stderr, "failed to translate bitcode\n");
return 3;
}
- bcinfo::MetadataExtractor *ME =
- new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(),
- BT->getTranslatedBitcodeSize());
+ llvm::OwningPtr<bcinfo::MetadataExtractor> ME;
+ ME.reset(new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(),
+ BT->getTranslatedBitcodeSize()));
if (!ME->extract()) {
fprintf(stderr, "failed to get metadata\n");
return 4;
}
- dumpMetadata(ME);
+ dumpMetadata(ME.get());
- delete ME;
- delete BT;
+ const char *translatedBitcode = BT->getTranslatedBitcode();
+ size_t translatedBitcodeSize = BT->getTranslatedBitcodeSize();
+
+ llvm::LLVMContext &ctx = llvm::getGlobalContext();
+ llvm::llvm_shutdown_obj called_on_exit;
+
+ llvm::OwningPtr<llvm::MemoryBuffer> mem;
+
+ mem.reset(llvm::MemoryBuffer::getMemBuffer(
+ llvm::StringRef(translatedBitcode, translatedBitcodeSize),
+ inFile.c_str(), false));
+
+ llvm::OwningPtr<llvm::Module> module;
+ std::string errmsg;
+ module.reset(llvm::ParseBitcodeFile(mem.get(), ctx, &errmsg));
+ if (module.get() != 0 && module->MaterializeAllPermanently(&errmsg)) {
+ module.reset();
+ }
+
+ if (module.get() == 0) {
+ if (errmsg.size()) {
+ fprintf(stderr, "error: %s\n", errmsg.c_str());
+ } else {
+ fprintf(stderr, "error: failed to parse bitcode file\n");
+ }
+ return 5;
+ }
+
+ llvm::OwningPtr<llvm::tool_output_file> tof(
+ new llvm::tool_output_file(outFile.c_str(), errmsg,
+ llvm::raw_fd_ostream::F_Binary));
+ llvm::OwningPtr<llvm::AssemblyAnnotationWriter> ann;
+ module->print(tof->os(), ann.get());
+
+ tof->keep();
releaseBitcode(&bitcode);
diff --git a/helper/Android.mk b/helper/Android.mk
index ecba95f..54b408b 100644
--- a/helper/Android.mk
+++ b/helper/Android.mk
@@ -57,7 +57,6 @@
LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
LOCAL_SRC_FILES := \
- DebugHelper.c \
sha1.c
include $(LIBBCC_ROOT_PATH)/libbcc-gen-config-from-mk.mk
diff --git a/helper/DebugHelper.c b/helper/DebugHelper.c
deleted file mode 100644
index 5c01b1b..0000000
--- a/helper/DebugHelper.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include "DebugHelper.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define LOG_BUF_SIZE 1024
-
-#if USE_LOGGER && !defined(__arm__)
-int __android_log_print(int prio, const char *tag, const char *fmt, ...) {
- va_list ap;
- char buf[LOG_BUF_SIZE];
-
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- va_end(ap);
-
- return __android_log_write(prio, tag, buf);
-}
-
-int __android_log_write(int prio, const char *tag, const char *msg) {
- if (!tag) {
- tag = "";
- }
-
- return fprintf(stderr, "[%s] %s\n", tag, msg);
-}
-#endif // USE_LOGGER && !defined(__arm__)
diff --git a/helper/DebugHelper.h b/helper/DebugHelper.h
index ae68e3a..ae1d4af 100644
--- a/helper/DebugHelper.h
+++ b/helper/DebugHelper.h
@@ -19,30 +19,9 @@
#include "Config.h"
-#if USE_LOGGER
-
#define LOG_TAG "bcc"
#include <cutils/log.h>
-#else // !USE_LOGGER
-
-#undef ALOGV
-#undef ALOGI
-#undef ALOGD
-#undef ALOGW
-#undef ALOGE
-#undef LOGA
-
-#define ALOGV(...)
-#define ALOGI(...)
-#define ALOGD(...)
-#define ALOGW(...)
-#define ALOGE(...)
-#define LOGA(...)
-
-#endif
-
-
#if !USE_FUNC_LOGGER
#define BCC_FUNC_LOGGER()
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index c015bcc..855d055 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright (C) 2011-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.
@@ -23,6 +23,8 @@
#=====================================================================
libbcc_executionengine_SRC_FILES := \
+ BCCContext.cpp \
+ BCCContextImpl.cpp \
Compiler.cpp \
FileHandle.cpp \
GDBJIT.cpp \
@@ -35,7 +37,7 @@
ScriptCached.cpp \
ScriptCompiled.cpp \
Sha1Helper.cpp \
- SourceInfo.cpp
+ Source.cpp
#=====================================================================
diff --git a/lib/ExecutionEngine/BCCContext.cpp b/lib/ExecutionEngine/BCCContext.cpp
new file mode 100644
index 0000000..63df268
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContext.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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 "BCCContext.h"
+
+#include <new>
+
+#include "BCCContextImpl.h"
+#include "Compiler.h"
+#include "DebugHelper.h"
+#include "Source.h"
+
+using namespace bcc;
+
+static BCCContext *GlobalContext = NULL;
+
+BCCContext *BCCContext::GetOrCreateGlobalContext() {
+ if (GlobalContext == NULL) {
+ GlobalContext = new (std::nothrow) BCCContext();
+ if (GlobalContext == NULL) {
+ ALOGE("Out of memory when allocating global BCCContext!");
+ }
+ }
+ return GlobalContext;
+}
+
+void BCCContext::DestroyGlobalContext() {
+ delete GlobalContext;
+ GlobalContext = NULL;
+}
+
+BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) {
+ // Initialize the LLVM compiler infrastructure.
+ Compiler::GlobalInitialization();
+}
+
+BCCContext::~BCCContext() {
+ delete mImpl;
+ if (this == GlobalContext) {
+ // We're deleting the context returned from GetOrCreateGlobalContext().
+ // Reset the GlobalContext.
+ GlobalContext = NULL;
+ }
+}
+
+void BCCContext::addSource(Source &pSource)
+{ mImpl->mOwnSources.insert(&pSource); }
+
+void BCCContext::removeSource(Source &pSource)
+{ mImpl->mOwnSources.erase(&pSource); }
+
+llvm::LLVMContext &BCCContext::getLLVMContext()
+{ return mImpl->mLLVMContext; }
+
+const llvm::LLVMContext &BCCContext::getLLVMContext() const
+{ return mImpl->mLLVMContext; }
diff --git a/lib/ExecutionEngine/BCCContext.h b/lib/ExecutionEngine/BCCContext.h
new file mode 100644
index 0000000..56962fe
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContext.h
@@ -0,0 +1,52 @@
+/*
+ * 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_CONTEXT_H
+#define BCC_EXECUTION_ENGINE_CONTEXT_H
+
+namespace llvm {
+ class LLVMContext;
+}
+
+namespace bcc {
+
+class BCCContextImpl;
+class Source;
+
+/*
+ * class BCCContext manages the global data across the libbcc infrastructure.
+ */
+class BCCContext {
+public:
+ BCCContextImpl *const mImpl;
+
+ BCCContext();
+ ~BCCContext();
+
+ llvm::LLVMContext &getLLVMContext();
+ const llvm::LLVMContext &getLLVMContext() const;
+
+ void addSource(Source &pSource);
+ void removeSource(Source &pSource);
+
+ // Global BCCContext
+ static BCCContext *GetOrCreateGlobalContext();
+ static void DestroyGlobalContext();
+};
+
+} // namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_CONTEXT_H
diff --git a/lib/ExecutionEngine/BCCContextImpl.cpp b/lib/ExecutionEngine/BCCContextImpl.cpp
new file mode 100644
index 0000000..5558e17
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContextImpl.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 "BCCContextImpl.h"
+
+#include <vector>
+
+#include <llvm/ADT/STLExtras.h>
+
+#include "Source.h"
+
+using namespace bcc;
+
+BCCContextImpl::~BCCContextImpl() {
+ // Another temporary container is needed to store the Source objects that we
+ // are going to destroy. Since the destruction of Source object will call
+ // removeSource() and change the content of OwnSources.
+ std::vector<Source *> Sources(mOwnSources.begin(), mOwnSources.end());
+ llvm::DeleteContainerPointers(Sources);
+}
diff --git a/lib/ExecutionEngine/BCCContextImpl.h b/lib/ExecutionEngine/BCCContextImpl.h
new file mode 100644
index 0000000..e60997a
--- /dev/null
+++ b/lib/ExecutionEngine/BCCContextImpl.h
@@ -0,0 +1,45 @@
+/*
+ * 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_CONTEXT_IMPL_H
+#define BCC_EXECUTION_ENGINE_CONTEXT_IMPL_H
+
+#include <llvm/ADT/SmallPtrSet.h>
+#include <llvm/LLVMContext.h>
+
+namespace bcc {
+
+class BCCContext;
+class Source;
+
+/*
+ * class BCCContextImpl contains the implementation of BCCContext.
+ */
+class BCCContextImpl {
+public:
+ llvm::LLVMContext mLLVMContext;
+
+ // The set of sources that initialized in this context. They will be destroyed
+ // automatically when this context is gone.
+ llvm::SmallPtrSet<Source *, 2> mOwnSources;
+
+ BCCContextImpl(BCCContext &pContext) { }
+ ~BCCContextImpl();
+};
+
+} // namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_CONTEXT_IMPL_H
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index cf18ef6..5397d1d 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -220,27 +220,27 @@
mRSExecutable(NULL),
mpSymbolLookupFn(NULL),
mpSymbolLookupContext(NULL),
- mModule(NULL),
- mHasLinked(false) /* Turn off linker */ {
+ mModule(NULL) {
llvm::remove_fatal_error_handler();
llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
return;
}
-
-int Compiler::linkModule(llvm::Module *moduleWith) {
- if (llvm::Linker::LinkModules(mModule, moduleWith,
- llvm::Linker::PreserveSource,
- &mError) != 0) {
- return hasError();
+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;
+ }
}
-
- // Everything for linking should be settled down here with no error occurs
- mHasLinked = true;
return hasError();
}
-
int Compiler::compile(const CompilerOption &option) {
llvm::Target const *Target = NULL;
llvm::TargetData *TD = NULL;
@@ -391,7 +391,7 @@
runInternalPasses(ForEachNameList, ForEachSigList);
// Perform link-time optimization if we have multiple modules
- if (mHasLinked) {
+ if (option.RunLTO) {
runLTO(new llvm::TargetData(*TD), ExportSymbols, CodeGenOptLevel);
}
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 863cda6..8fee17c 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -93,8 +93,6 @@
llvm::Module *mModule;
- bool mHasLinked;
-
public:
Compiler(ScriptCompiled *result);
@@ -119,12 +117,7 @@
return mEmittedELFExecutable;
}
- int readModule(llvm::Module *module) {
- mModule = module;
- return hasError();
- }
-
- int linkModule(llvm::Module *module);
+ int readModule(llvm::Module &pModule);
int compile(const CompilerOption &option);
diff --git a/lib/ExecutionEngine/CompilerOption.h b/lib/ExecutionEngine/CompilerOption.h
index 75278c7..f7c1e50 100644
--- a/lib/ExecutionEngine/CompilerOption.h
+++ b/lib/ExecutionEngine/CompilerOption.h
@@ -82,6 +82,9 @@
CodeModelOpt = llvm::CodeModel::Small;
#endif
+ //-- Run LTO passes --//
+ RunLTO = true;
+
//-- Load the result object after successful compilation --//
LoadAfterCompile = true;
}
@@ -89,6 +92,7 @@
llvm::TargetOptions TargetOpt;
llvm::CodeModel::Model CodeModelOpt;
llvm::Reloc::Model RelocModelOpt;
+ bool RunLTO;
bool LoadAfterCompile;
};
diff --git a/lib/ExecutionEngine/FileHandle.cpp b/lib/ExecutionEngine/FileHandle.cpp
index c0a344c..c659fb5 100644
--- a/lib/ExecutionEngine/FileHandle.cpp
+++ b/lib/ExecutionEngine/FileHandle.cpp
@@ -37,9 +37,7 @@
static int const lock_flags[2] = { LOCK_SH, LOCK_EX };
-#if USE_LOGGER
static char const *const open_mode_str[2] = { "read", "write" };
-#endif
static size_t const RETRY_MAX = 4;
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 11ef0e1..dfa3f25 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -16,30 +16,33 @@
#include "Script.h"
-#include "Config.h"
-#include "bcinfo/BitcodeWrapper.h"
-
-#include "MCCacheReader.h"
-#include "MCCacheWriter.h"
-#include "CompilerOption.h"
-
-#include "DebugHelper.h"
-#include "FileHandle.h"
-#include "GDBJITRegistrar.h"
-#include "ScriptCompiled.h"
-#include "ScriptCached.h"
-#include "Sha1Helper.h"
-#include "SourceInfo.h"
-
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <new>
-#include <string.h>
+#include <cstring>
+
+#include <llvm/ADT/STLExtras.h>
+
#include <cutils/properties.h>
+#include "Config.h"
+
+#include "MCCacheReader.h"
+#include "MCCacheWriter.h"
+#include "CompilerOption.h"
+
+#include "BCCContextImpl.h"
+#include "DebugHelper.h"
+#include "FileHandle.h"
+#include "GDBJITRegistrar.h"
+#include "ScriptCompiled.h"
+#include "ScriptCached.h"
+#include "Sha1Helper.h"
+#include "Source.h"
+
namespace {
bool getBooleanProp(const char *str) {
@@ -48,10 +51,24 @@
return strcmp(buf, "0") != 0;
}
+bool isSetProp(const char *str) {
+ char buf[PROPERTY_VALUE_MAX];
+ property_get(str, buf, "");
+ return buf[0] != '\0';
+}
+
} // namespace anonymous
namespace bcc {
+Script::Script(Source &pSource)
+ : mSource(&pSource),
+ mpExtSymbolLookupFn(NULL),
+ mpExtSymbolLookupFnContext(NULL) {
+ resetState();
+ return;
+}
+
Script::~Script() {
switch (mStatus) {
case ScriptStatus::Compiled:
@@ -65,111 +82,62 @@
default:
break;
}
+ llvm::DeleteContainerPointers(mDependencyInfos);
+}
- for (size_t i = 0; i < 2; ++i) {
- delete mSourceList[i];
- }
+void Script::resetState() {
+ mErrorCode = BCC_NO_ERROR;
+ mStatus = ScriptStatus::Unknown;
+ mObjectType = ScriptObject::Unknown;
+ mIsContextSlotNotAvail = false;
+ // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be
+ // assigned to NULL during state resetting.
+ //mpExtSymbolLookupFn = NULL;
+ //mpExtSymbolLookupFnContext = NULL;
+ llvm::DeleteContainerPointers(mDependencyInfos);
+ return;
}
-int Script::addSourceBC(size_t idx,
- char const *resName,
- const char *bitcode,
- size_t bitcodeSize,
- unsigned long flags) {
-
- if (!resName) {
- mErrorCode = BCC_INVALID_VALUE;
- ALOGE("Invalid argument: resName = NULL\n");
- return 1;
- }
-
- if (mStatus != ScriptStatus::Unknown) {
- mErrorCode = BCC_INVALID_OPERATION;
- ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
- return 1;
- }
-
- if (!bitcode) {
- mErrorCode = BCC_INVALID_VALUE;
- ALOGE("Invalid argument: bitcode = NULL\n");
- return 1;
- }
-
- bcinfo::BitcodeWrapper wrapper(bitcode, bitcodeSize);
-
- mSourceList[idx] = SourceInfo::createFromBuffer(resName,
- bitcode, bitcodeSize,
- flags);
-
- if (!mSourceList[idx]) {
- mErrorCode = BCC_OUT_OF_MEMORY;
- ALOGE("Out of memory while adding source bitcode\n");
- return 1;
- }
-
- return 0;
+Script::DependencyInfo::DependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1)
+ : mSourceType(pSourceType), mSourceName(pSourceName) {
+ ::memcpy(mSHA1, pSHA1, sizeof(mSHA1));
+ return;
}
-
-int Script::addSourceModule(size_t idx,
- llvm::Module *module,
- unsigned long flags) {
- if (mStatus != ScriptStatus::Unknown) {
- mErrorCode = BCC_INVALID_OPERATION;
- ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
- return 1;
+bool Script::reset(Source &pSource, bool pPreserveCurrent) {
+ if (mSource == &pSource) {
+ return false;
}
- if (!module) {
- mErrorCode = BCC_INVALID_VALUE;
- ALOGE("Invalid argument: module = NULL\n");
- return 1;
+ if (!pPreserveCurrent) {
+ delete mSource;
}
-
- mSourceList[idx] = SourceInfo::createFromModule(module, flags);
-
- if (!mSourceList[idx]) {
- mErrorCode = BCC_OUT_OF_MEMORY;
- ALOGE("Out of memory when add source module\n");
- return 1;
- }
-
- return 0;
+ resetState();
+ mSource = &pSource;
+ return true;
}
+bool Script::mergeSource(Source &pSource, bool pPreserveSource) {
+ return mSource->merge(pSource, pPreserveSource);
+}
-int Script::addSourceFile(size_t idx,
- char const *path,
- unsigned long flags) {
- if (mStatus != ScriptStatus::Unknown) {
- mErrorCode = BCC_INVALID_OPERATION;
- ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
- return 1;
+bool Script::addSourceDependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1) {
+ DependencyInfo *dep_info = new (std::nothrow) DependencyInfo(pSourceType,
+ pSourceName,
+ pSHA1);
+ if (dep_info == NULL) {
+ ALOGE("Out of memory when record dependency information of `%s'!",
+ pSourceName.c_str());
+ return false;
}
- if (!path) {
- mErrorCode = BCC_INVALID_VALUE;
- ALOGE("Invalid argument: path = NULL\n");
- return 1;
- }
-
- struct stat sb;
- if (stat(path, &sb) != 0) {
- mErrorCode = BCC_INVALID_VALUE;
- ALOGE("File not found: %s\n", path);
- return 1;
- }
-
- mSourceList[idx] = SourceInfo::createFromFile(path, flags);
-
- if (!mSourceList[idx]) {
- mErrorCode = BCC_OUT_OF_MEMORY;
- ALOGE("Out of memory while adding source file\n");
- return 1;
- }
-
- return 0;
+ mDependencyInfos.push_back(dep_info);
+ return true;
}
int Script::prepareRelocatable(char const *objPath,
@@ -177,6 +145,7 @@
unsigned long flags) {
CompilerOption option;
option.RelocModelOpt = RelocModel;
+ option.RunLTO = false;
option.LoadAfterCompile = false;
int status = internalCompile(option);
@@ -294,10 +263,11 @@
reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
- for (size_t i = 0; i < 2; ++i) {
- if (mSourceList[i]) {
- mSourceList[i]->introDependency(reader);
- }
+ for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+ const DependencyInfo *dep_info = mDependencyInfos[i];
+ reader.addDependency(dep_info->getSourceType(),
+ dep_info->getSourceName(),
+ dep_info->getSHA1Checksum());
}
if (checkOnly)
@@ -341,39 +311,12 @@
mpExtSymbolLookupFnContext);
}
- if (!mSourceList[0]) {
- ALOGE("Source bitcode is not set.\n");
- return 1;
- }
-
- // Parse Source bitcode file (if necessary)
- if (mSourceList[0]->prepareModule() != 0) {
- ALOGE("Unable to setup source module\n");
- return 1;
- }
-
- // Parse Library bitcode file (if necessary)
- if (mSourceList[1]) {
- if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
- ALOGE("Unable to setup library module\n");
- return 1;
- }
- }
-
// Set the main source module
- if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
+ if (mCompiled->readModule(mSource->getModule()) != 0) {
ALOGE("Unable to read source module\n");
return 1;
}
- // Link the source module with the library module
- if (mSourceList[1]) {
- if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
- ALOGE("Unable to link library module\n");
- return 1;
- }
- }
-
// Compile and JIT the code
if (mCompiled->compile(option) != 0) {
ALOGE("Unable to compile.\n");
@@ -421,12 +364,14 @@
writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
#endif
- for (size_t i = 0; i < 2; ++i) {
- if (mSourceList[i]) {
- mSourceList[i]->introDependency(writer);
- }
+ for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+ const DependencyInfo *dep_info = mDependencyInfos[i];
+ writer.addDependency(dep_info->getSourceType(),
+ dep_info->getSourceName(),
+ dep_info->getSHA1Checksum());
}
+
// libRS is threadable dirty hack
// TODO: This should be removed in the future
uint32_t libRS_threadable = 0;
@@ -762,6 +707,11 @@
return false;
}
+ if (isSetProp("debug.rs.precision")) {
+ // If we have a floating point precision override, don't use the cache.
+ 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.
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index e95cf8a..b654797 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -17,18 +17,20 @@
#ifndef BCC_SCRIPT_H
#define BCC_SCRIPT_H
-#include <bcc/bcc.h>
-#include "bcc_internal.h"
-
-#include "Compiler.h"
-
-#include <llvm/Support/CodeGen.h>
-
#include <vector>
#include <string>
+#include <stdint.h>
#include <stddef.h>
+#include <llvm/ADT/SmallVector.h>
+
+#include <bcc/bcc.h>
+#include <bcc/bcc_mccache.h>
+#include "bcc_internal.h"
+
+#include "Compiler.h"
+
namespace llvm {
class Module;
class GDBJITRegistrar;
@@ -37,7 +39,7 @@
namespace bcc {
class ScriptCompiled;
class ScriptCached;
- class SourceInfo;
+ class Source;
struct CompilerOption;
namespace ScriptStatus {
@@ -85,11 +87,31 @@
bool mIsContextSlotNotAvail;
- // Source List
- SourceInfo *mSourceList[2];
- // Note: mSourceList[0] (main source)
- // Note: mSourceList[1] (library source)
- // TODO(logan): Generalize this, use vector or SmallVector instead!
+ // This is the source associated with this object and is going to be
+ // compiled.
+ Source *mSource;
+
+ class DependencyInfo {
+ private:
+ MCO_ResourceType mSourceType;
+ std::string mSourceName;
+ uint8_t mSHA1[20];
+
+ public:
+ DependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1);
+
+ inline MCO_ResourceType getSourceType() const
+ { return mSourceType; }
+
+ inline const std::string getSourceName() const
+ { return mSourceName; }
+
+ inline const uint8_t *getSHA1Checksum() const
+ { return mSHA1; }
+ };
+ llvm::SmallVector<DependencyInfo *, 2> mDependencyInfos;
// External Function List
std::vector<char const *> mUserDefinedExternalSymbols;
@@ -98,32 +120,31 @@
BCCSymbolLookupFn mpExtSymbolLookupFn;
void *mpExtSymbolLookupFnContext;
- public:
- Script() : mErrorCode(BCC_NO_ERROR), mStatus(ScriptStatus::Unknown),
- mObjectType(ScriptObject::Unknown),
- mIsContextSlotNotAvail(false),
- mpExtSymbolLookupFn(NULL), mpExtSymbolLookupFnContext(NULL) {
- Compiler::GlobalInitialization();
+ // Reset the state of this script object
+ void resetState();
- mSourceList[0] = NULL;
- mSourceList[1] = NULL;
- }
+ public:
+ Script(Source &pSource);
~Script();
- int addSourceBC(size_t idx,
- char const *resName,
- const char *bitcode,
- size_t bitcodeSize,
- unsigned long flags);
+ // Reset this object with the new source supplied. Return false if this
+ // object remains unchanged after the call (e.g., the supplied source is
+ // the same with the one contain in this object.) If pPreserveCurrent is
+ // false, the current containing source will be destroyed after successfully
+ // reset.
+ bool reset(Source &pSource, bool pPreserveCurrent = false);
- int addSourceModule(size_t idx,
- llvm::Module *module,
- unsigned long flags);
+ // Merge (or link) another source into the current source associated with
+ // this Script object. Return false on error.
+ bool mergeSource(Source &pSource, bool pPreserveSource = false);
- int addSourceFile(size_t idx,
- char const *path,
- unsigned long flags);
+ // 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 addSourceDependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1);
void markExternalSymbol(char const *name) {
mUserDefinedExternalSymbols.push_back(name);
@@ -139,7 +160,7 @@
int writeCache();
/*
- * Link the given bitcodes in mSourceList to shared object (.so).
+ * 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.
@@ -150,7 +171,7 @@
* 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 the bitcodes in mSourceList[0].
+ * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
*
*/
int prepareSharedObject(char const *objPath,
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index 7b7b62a..8752aa3 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -17,17 +17,17 @@
#ifndef BCC_SCRIPTCOMPILED_H
#define BCC_SCRIPTCOMPILED_H
-#include "Compiler.h"
-#include "Script.h"
-
-#include <bcc/bcc.h>
-
#include <list>
#include <map>
#include <string>
#include <utility>
#include <vector>
+#include <bcc/bcc.h>
+
+#include "Compiler.h"
+#include "Script.h"
+
namespace llvm {
class Module;
}
@@ -73,12 +73,8 @@
~ScriptCompiled();
- int readModule(llvm::Module *module) {
- return mCompiler.readModule(module);
- }
-
- int linkModule(llvm::Module *module) {
- return mCompiler.linkModule(module);
+ int readModule(llvm::Module &pModule) {
+ return mCompiler.readModule(pModule);
}
int compile(const CompilerOption &option) {
diff --git a/lib/ExecutionEngine/Source.cpp b/lib/ExecutionEngine/Source.cpp
new file mode 100644
index 0000000..754f3e5
--- /dev/null
+++ b/lib/ExecutionEngine/Source.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 "Source.h"
+
+#include <new>
+
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Linker.h>
+#include <llvm/Module.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/system_error.h>
+
+#include "BCCContext.h"
+#include "BCCContextImpl.h"
+#include "DebugHelper.h"
+
+namespace {
+
+// Helper function to load the bitcode. This uses "bitcode lazy load" feature to
+// reduce the startup time. On success, return the LLVM module object created
+// and take the ownership of input memory buffer (i.e., pInput). On error,
+// return NULL and will NOT take the ownership of pInput.
+static inline llvm::Module *helper_load_bitcode(llvm::LLVMContext &pContext,
+ llvm::MemoryBuffer *pInput) {
+ std::string error;
+ llvm::Module *module = llvm::getLazyBitcodeModule(pInput, pContext, &error);
+
+ if (module == NULL) {
+ ALOGE("Unable to parse the given bitcode file `%s'! (%s)",
+ pInput->getBufferIdentifier(), error.c_str());
+ }
+
+ return module;
+}
+
+} // end anonymous namespace
+
+namespace bcc {
+
+Source *Source::CreateFromBuffer(BCCContext &pContext,
+ const char *pName,
+ const char *pBitcode,
+ size_t pBitcodeSize) {
+ llvm::StringRef input_data(pBitcode, pBitcodeSize);
+ llvm::MemoryBuffer *input_memory =
+ llvm::MemoryBuffer::getMemBuffer(input_data, pName);
+
+ if (input_memory == NULL) {
+ ALOGE("Unable to load bitcode `%s' from buffer!", pName);
+ return NULL;
+ }
+
+ llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext,
+ input_memory);
+ if (module == NULL) {
+ delete input_memory;
+ return NULL;
+ }
+
+ Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
+ if (result == NULL) {
+ delete module;
+ }
+
+ return result;
+}
+
+
+Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) {
+ llvm::OwningPtr<llvm::MemoryBuffer> input_data;
+
+ llvm::error_code ec = llvm::MemoryBuffer::getFile(pPath, input_data);
+ if (ec != llvm::error_code::success()) {
+ ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(),
+ ec.message().c_str());
+ return NULL;
+ }
+
+ llvm::MemoryBuffer *input_memory = input_data.take();
+ llvm::Module *module = helper_load_bitcode(pContext.mImpl->mLLVMContext,
+ input_memory);
+ if (module == NULL) {
+ delete input_memory;
+ return NULL;
+ }
+
+ Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
+ if (result == NULL) {
+ delete module;
+ }
+
+ return result;
+}
+
+
+Source *Source::CreateFromModule(BCCContext &pContext, llvm::Module &pModule,
+ bool pNoDelete) {
+ Source *result = new (std::nothrow) Source(pContext, pModule, pNoDelete);
+ if (result == NULL) {
+ ALOGE("Out of memory during Source object allocation for `%s'!",
+ pModule.getModuleIdentifier().c_str());
+ }
+ return result;
+}
+
+Source::Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete)
+ : mContext(pContext), mModule(&pModule), mNoDelete(pNoDelete) {
+ pContext.addSource(*this);
+}
+
+Source::~Source() {
+ mContext.removeSource(*this);
+ if (!mNoDelete)
+ delete mModule;
+}
+
+bool Source::merge(Source &pSource, bool pPreserveSource) {
+ std::string error;
+ llvm::Linker::LinkerMode mode =
+ ((pPreserveSource) ? llvm::Linker::PreserveSource :
+ llvm::Linker::DestroySource);
+
+ if (llvm::Linker::LinkModules(mModule, &pSource.getModule(),
+ mode, &error) != 0) {
+ ALOGE("Failed to link source `%s' with `%s' (%s)!",
+ getIdentifier().c_str(),
+ pSource.getIdentifier().c_str(),
+ error.c_str());
+ return false;
+ }
+
+ if (!pPreserveSource) {
+ pSource.mNoDelete = true;
+ delete &pSource;
+ }
+
+ return true;
+}
+
+Source *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) {
+ // Create an empty module
+ llvm::Module *module =
+ new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext);
+
+ if (module == NULL) {
+ ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str());
+ return NULL;
+ }
+
+ Source *result = CreateFromModule(pContext, *module, /* pNoDelete */false);
+ if (result == NULL) {
+ delete module;
+ }
+
+ return result;
+}
+
+const std::string &Source::getIdentifier() const {
+ return mModule->getModuleIdentifier();
+}
+
+} // namespace bcc
diff --git a/lib/ExecutionEngine/Source.h b/lib/ExecutionEngine/Source.h
new file mode 100644
index 0000000..577865f
--- /dev/null
+++ b/lib/ExecutionEngine/Source.h
@@ -0,0 +1,81 @@
+/*
+ * 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_EXECUTION_ENGINE_SOURCE_H
+#define BCC_EXECUTION_ENGINE_SOURCE_H
+
+#include <string>
+
+namespace llvm {
+ class Module;
+}
+
+namespace bcc {
+
+class BCCContext;
+
+class Source {
+private:
+ BCCContext &mContext;
+ llvm::Module *mModule;
+
+ // If true, destructor won't destroy the mModule.
+ bool mNoDelete;
+
+private:
+ Source(BCCContext &pContext, llvm::Module &pModule, bool pNoDelete = false);
+
+public:
+ static Source *CreateFromBuffer(BCCContext &pContext,
+ const char *pName,
+ const char *pBitcode,
+ size_t pBitcodeSize);
+
+ static Source *CreateFromFile(BCCContext &pContext,
+ const std::string &pPath);
+
+ // Create a Source object from an existing module. If pNoDelete
+ // is true, destructor won't call delete on the given module.
+ static Source *CreateFromModule(BCCContext &pContext,
+ llvm::Module &pModule,
+ bool pNoDelete = false);
+
+ static Source *CreateEmpty(BCCContext &pContext, const std::string &pName);
+
+ // Merge the current source with pSource. If pPreserveSource is false, pSource
+ // will be destroyed after successfully merged. Return false on error.
+ bool merge(Source &pSource, bool pPreserveSource = false);
+
+ inline BCCContext &getContext()
+ { return mContext; }
+ inline const BCCContext &getContext() const
+ { return mContext; }
+
+ inline llvm::Module &getModule()
+ { return *mModule; }
+ inline const llvm::Module &getModule() const
+ { return *mModule; }
+
+ // Get the "identifier" of the bitcode. This will return the value of pName
+ // when it's created using CreateFromBuffer and pPath if CreateFromFile().
+ const std::string &getIdentifier() const;
+
+ ~Source();
+};
+
+} // namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_SOURCE_H
diff --git a/lib/ExecutionEngine/SourceInfo.cpp b/lib/ExecutionEngine/SourceInfo.cpp
deleted file mode 100644
index 1d0a950..0000000
--- a/lib/ExecutionEngine/SourceInfo.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SourceInfo.h"
-
-#include "MCCacheWriter.h"
-#include "MCCacheReader.h"
-
-#include "DebugHelper.h"
-#include "ScriptCompiled.h"
-#include "Sha1Helper.h"
-
-#include <bcc/bcc.h>
-
-#include <llvm/Bitcode/ReaderWriter.h>
-#include <llvm/Module.h>
-#include <llvm/LLVMContext.h>
-#include <llvm/ADT/OwningPtr.h>
-#include <llvm/ADT/StringRef.h>
-#include <llvm/Support/MemoryBuffer.h>
-#include <llvm/Support/system_error.h>
-
-#include <stddef.h>
-#include <string.h>
-
-namespace bcc {
-
-
-SourceInfo *SourceInfo::createFromBuffer(char const *resName,
- char const *bitcode,
- size_t bitcodeSize,
- unsigned long flags) {
- SourceInfo *result = new SourceInfo();
-
- if (!result) {
- return NULL;
- }
-
- result->type = SourceKind::Buffer;
- result->buffer.resName = resName;
- result->buffer.bitcode = bitcode;
- result->buffer.bitcodeSize = bitcodeSize;
- result->flags = flags;
-
- if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) {
- result->flags |= BCC_SKIP_DEP_SHA1;
-
- ALOGW("It is required to give resName for sha1 dependency check.\n");
- ALOGW("Sha1sum dependency check will be skipped.\n");
- ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
- }
-
- if (result->flags & BCC_SKIP_DEP_SHA1) {
- memset(result->sha1, '\0', 20);
- } else {
- calcSHA1(result->sha1, bitcode, bitcodeSize);
- }
-
- return result;
-}
-
-
-SourceInfo *SourceInfo::createFromFile(char const *path,
- unsigned long flags) {
- SourceInfo *result = new SourceInfo();
-
- if (!result) {
- return NULL;
- }
-
- result->type = SourceKind::File;
- result->file.path = path;
- result->flags = flags;
-
- memset(result->sha1, '\0', 20);
-
- if (!(result->flags & BCC_SKIP_DEP_SHA1)) {
- calcFileSHA1(result->sha1, path);
- }
-
- return result;
-}
-
-
-SourceInfo *SourceInfo::createFromModule(llvm::Module *module,
- unsigned long flags) {
- SourceInfo *result = new SourceInfo();
-
- if (!result) {
- return NULL;
- }
-
- result->type = SourceKind::Module;
- result->module = module;
- result->flags = flags;
-
- if (! (flags & BCC_SKIP_DEP_SHA1)) {
- result->flags |= BCC_SKIP_DEP_SHA1;
-
- ALOGW("Unable to calculate sha1sum for llvm::Module.\n");
- ALOGW("Sha1sum dependency check will be skipped.\n");
- ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
- }
-
- memset(result->sha1, '\0', 20);
-
- return result;
-}
-
-
-int SourceInfo::prepareModule(llvm::LLVMContext *context) {
- if (module)
- return 0;
-
- llvm::OwningPtr<llvm::MemoryBuffer> mem;
- std::string errmsg;
-
- switch (type) {
- case SourceKind::Buffer:
- {
- mem.reset(llvm::MemoryBuffer::getMemBuffer(
- llvm::StringRef(buffer.bitcode, buffer.bitcodeSize), "", false));
-
- if (!mem.get()) {
- ALOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
- buffer.bitcode, (unsigned long)buffer.bitcodeSize);
- return 1;
- }
- }
- break;
-
- case SourceKind::File:
- {
- if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, mem)) {
- ALOGE("Unable to MemoryBuffer::getFile(path=%s, %s)\n",
- file.path, ec.message().c_str());
- return 1;
- }
- }
- break;
-
- default:
- return 0;
- break;
- }
-
- if (context)
- shared_context = true;
- else
- context = new llvm::LLVMContext();
-
- module = llvm::ParseBitcodeFile(mem.get(), *context, &errmsg);
- if (module == NULL) {
- ALOGE("Unable to ParseBitcodeFile: %s\n", errmsg.c_str());
- if (!shared_context)
- delete context;
- }
-
- return (module == NULL);
-}
-
-SourceInfo::~SourceInfo() {
- if (module != NULL) {
- llvm::LLVMContext *context = &module->getContext();
- delete module;
- if (!shared_context)
- delete context;
- }
-}
-
-template <typename T> void SourceInfo::introDependency(T &checker) {
- if (flags & BCC_SKIP_DEP_SHA1) {
- return;
- }
-
- switch (type) {
- case SourceKind::Buffer:
- checker.addDependency(BCC_APK_RESOURCE, buffer.resName, sha1);
- break;
-
- case SourceKind::File:
- checker.addDependency(BCC_FILE_RESOURCE, file.path, sha1);
- break;
-
- default:
- break;
- }
-}
-
-template void SourceInfo::introDependency<MCCacheWriter>(MCCacheWriter &);
-template void SourceInfo::introDependency<MCCacheReader>(MCCacheReader &);
-
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/SourceInfo.h b/lib/ExecutionEngine/SourceInfo.h
deleted file mode 100644
index 080d3b4..0000000
--- a/lib/ExecutionEngine/SourceInfo.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_SOURCEINFO_H
-#define BCC_SOURCEINFO_H
-
-#include "Config.h"
-
-#include <llvm/Module.h>
-
-#include <stddef.h>
-
-namespace llvm {
- class LLVMContext;
-}
-
-namespace bcc {
- namespace SourceKind {
- enum SourceType {
- File,
- Buffer,
- Module,
- };
- }
-
- class SourceInfo {
- private:
- SourceKind::SourceType type;
-
- // Note: module should not be a part of union. Since, we are going to
- // use module to store the pointer to parsed bitcode.
- llvm::Module *module;
- // If true, the LLVM context behind the module is shared with others.
- // Therefore, don't try to destroy the context it when destroy the module.
- bool shared_context;
-
- union {
- struct {
- char const *resName;
- char const *bitcode;
- size_t bitcodeSize;
- } buffer;
-
- struct {
- char const *path;
- } file;
- };
-
- unsigned long flags;
-
- unsigned char sha1[20];
-
- private:
- SourceInfo() : module(NULL), shared_context(false) { }
-
- public:
- static SourceInfo *createFromBuffer(char const *resName,
- char const *bitcode,
- size_t bitcodeSize,
- unsigned long flags);
-
- static SourceInfo *createFromFile(char const *path,
- unsigned long flags);
-
- static SourceInfo *createFromModule(llvm::Module *module,
- unsigned long flags);
-
- inline llvm::Module *getModule() const {
- return module;
- }
-
- inline llvm::LLVMContext *getContext() const {
- return (module) ? &module->getContext() : NULL;
- }
-
- // Share with the given context if it's provided.
- int prepareModule(llvm::LLVMContext *context = NULL);
-
- template <typename T> void introDependency(T &checker);
-
- ~SourceInfo();
- };
-
-
-} // namespace bcc
-
-#endif // BCC_SOURCEINFO_H
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index 01ef32f..e1894b7 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -18,19 +18,22 @@
// This is an eager-compilation JIT running on Android.
#include <bcc/bcc.h>
-#include "bcc_internal.h"
-
-#include "Config.h"
-
-#include "Compiler.h"
-#include "DebugHelper.h"
-#include "Script.h"
#include <string>
#include <utils/StopWatch.h>
-#include <llvm/Support/CodeGen.h>
+#include "Config.h"
+
+#include <bcc/bcc_mccache.h>
+#include "bcc_internal.h"
+
+#include "BCCContext.h"
+#include "Compiler.h"
+#include "DebugHelper.h"
+#include "Script.h"
+#include "Sha1Helper.h"
+#include "Source.h"
using namespace bcc;
@@ -51,7 +54,15 @@
extern "C" BCCScriptRef bccCreateScript() {
BCC_FUNC_LOGGER();
bccPrintBuildStamp();
- return wrap(new bcc::Script());
+ // 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;
+ }
+
+ Source *source = Source::CreateEmpty(*context, "empty");
+ return wrap(new Script(*source));
}
@@ -74,13 +85,102 @@
return unwrap(script)->getError();
}
+static bool helper_add_source(Script *pScript,
+ char const *pName,
+ char const *pBitcode,
+ size_t pBitcodeSize,
+ unsigned long pFlags,
+ bool pIsLink) {
+ bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
+ if (!pName && need_dependency_check) {
+ pFlags |= BCC_SKIP_DEP_SHA1;
+
+ ALOGW("It is required to give resName for sha1 dependency check.\n");
+ ALOGW("Sha1sum dependency check will be skipped.\n");
+ ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to suppress this warning.\n");
+ }
+
+ BCCContext *context = BCCContext::GetOrCreateGlobalContext();
+ if (context == NULL) {
+ return false;
+ }
+
+ Source *source = Source::CreateFromBuffer(*context, pName,
+ pBitcode, pBitcodeSize);
+ if (source == NULL) {
+ return false;
+ }
+
+ if (need_dependency_check) {
+ uint8_t sha1[20];
+ calcSHA1(sha1, pBitcode, pBitcodeSize);
+ if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pName, sha1)) {
+ return false;
+ }
+ }
+
+ return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+}
+
+static bool helper_add_source(Script *pScript,
+ 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);
+ if (source == NULL) {
+ return false;
+ }
+
+ return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+}
+
+static bool helper_add_source(Script *pScript,
+ char const *pPath,
+ unsigned long pFlags,
+ bool pIsLink) {
+ bool need_dependency_check = !(pFlags & BCC_SKIP_DEP_SHA1);
+ BCCContext *context = BCCContext::GetOrCreateGlobalContext();
+ if (context == NULL) {
+ return false;
+ }
+
+ Source *source = Source::CreateFromFile(*context, pPath);
+ if (source == NULL) {
+ return false;
+ }
+
+ if (need_dependency_check) {
+ uint8_t sha1[20];
+ calcFileSHA1(sha1, pPath);
+ if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pPath, sha1)) {
+ return false;
+ }
+ }
+
+ return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
+}
+
extern "C" int bccReadBC(BCCScriptRef script,
char const *resName,
char const *bitcode,
size_t bitcodeSize,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->addSourceBC(0, resName, bitcode, bitcodeSize, flags);
+ return (helper_add_source(unwrap(script), resName,
+ bitcode, bitcodeSize,
+ flags, /* pIsLink */false) == false);
}
@@ -89,7 +189,8 @@
LLVMModuleRef module,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->addSourceModule(0, unwrap(module), flags);
+ return (helper_add_source(unwrap(script), unwrap(module),
+ /* pIsLink */false) == false);
}
@@ -97,7 +198,8 @@
char const *path,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->addSourceFile(0, path, flags);
+ return (helper_add_source(unwrap(script), path,
+ flags, /* pIsLink */false) == false);
}
@@ -107,7 +209,9 @@
size_t bitcodeSize,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->addSourceBC(1, resName, bitcode, bitcodeSize, flags);
+ return (helper_add_source(unwrap(script), resName,
+ bitcode, bitcodeSize,
+ flags, /* pIsLink */true) == false);
}
@@ -115,7 +219,8 @@
char const *path,
unsigned long flags) {
BCC_FUNC_LOGGER();
- return unwrap(script)->addSourceFile(1, path, flags);
+ return (helper_add_source(unwrap(script), path,
+ flags, /* pIsLink */true) == false);
}
diff --git a/lib/ScriptCRT/Android.mk b/lib/ScriptCRT/Android.mk
index f8b6d80..85b0f33 100644
--- a/lib/ScriptCRT/Android.mk
+++ b/lib/ScriptCRT/Android.mk
@@ -32,11 +32,11 @@
clcore_files := \
$(clcore_base_files) \
- clamp.c
+ arch/generic.c
clcore_neon_files := \
$(clcore_base_files) \
- neon/clamp.ll
+ arch/neon.ll
ifeq "REL" "$(PLATFORM_VERSION_CODENAME)"
RS_VERSION := $(PLATFORM_SDK_VERSION)
diff --git a/lib/ScriptCRT/arch/generic.c b/lib/ScriptCRT/arch/generic.c
new file mode 100644
index 0000000..801ab28
--- /dev/null
+++ b/lib/ScriptCRT/arch/generic.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 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 "rs_types.rsh"
+
+extern short __attribute__((overloadable, always_inline)) rsClamp(short amount, short low, short high);
+extern float4 __attribute__((overloadable)) clamp(float4 amount, float4 low, float4 high);
+extern uchar4 __attribute__((overloadable)) convert_uchar4(short4);
+
+
+/*
+ * CLAMP
+ */
+
+extern float __attribute__((overloadable)) clamp(float amount, float low, float high) {
+ return amount < low ? low : (amount > high ? high : amount);
+}
+
+extern float2 __attribute__((overloadable)) clamp(float2 amount, float2 low, float2 high) {
+ float2 r;
+ r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
+ r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
+ return r;
+}
+
+extern float3 __attribute__((overloadable)) clamp(float3 amount, float3 low, float3 high) {
+ float3 r;
+ r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
+ r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
+ r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
+ return r;
+}
+
+extern float4 __attribute__((overloadable)) clamp(float4 amount, float4 low, float4 high) {
+ float4 r;
+ r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
+ r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
+ r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
+ r.w = amount.w < low.w ? low.w : (amount.w > high.w ? high.w : amount.w);
+ return r;
+}
+
+extern float2 __attribute__((overloadable)) clamp(float2 amount, float low, float high) {
+ float2 r;
+ r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
+ r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
+ return r;
+}
+
+extern float3 __attribute__((overloadable)) clamp(float3 amount, float low, float high) {
+ float3 r;
+ r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
+ r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
+ r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
+ return r;
+}
+
+extern float4 __attribute__((overloadable)) clamp(float4 amount, float low, float high) {
+ float4 r;
+ r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
+ r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
+ r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
+ r.w = amount.w < low ? low : (amount.w > high ? high : amount.w);
+ return r;
+}
+
+
+/*
+ * FMAX
+ */
+
+extern float __attribute__((overloadable)) fmax(float v1, float v2) {
+ return v1 > v2 ? v1 : v2;
+}
+
+extern float2 __attribute__((overloadable)) fmax(float2 v1, float2 v2) {
+ float2 r;
+ r.x = v1.x > v2.x ? v1.x : v2.x;
+ r.y = v1.y > v2.y ? v1.y : v2.y;
+ return r;
+}
+
+extern float3 __attribute__((overloadable)) fmax(float3 v1, float3 v2) {
+ float3 r;
+ r.x = v1.x > v2.x ? v1.x : v2.x;
+ r.y = v1.y > v2.y ? v1.y : v2.y;
+ r.z = v1.z > v2.z ? v1.z : v2.z;
+ return r;
+}
+
+extern float4 __attribute__((overloadable)) fmax(float4 v1, float4 v2) {
+ float4 r;
+ r.x = v1.x > v2.x ? v1.x : v2.x;
+ r.y = v1.y > v2.y ? v1.y : v2.y;
+ r.z = v1.z > v2.z ? v1.z : v2.z;
+ r.w = v1.w > v2.w ? v1.w : v2.w;
+ return r;
+}
+
+extern float2 __attribute__((overloadable)) fmax(float2 v1, float v2) {
+ float2 r;
+ r.x = v1.x > v2 ? v1.x : v2;
+ r.y = v1.y > v2 ? v1.y : v2;
+ return r;
+}
+
+extern float3 __attribute__((overloadable)) fmax(float3 v1, float v2) {
+ float3 r;
+ r.x = v1.x > v2 ? v1.x : v2;
+ r.y = v1.y > v2 ? v1.y : v2;
+ r.z = v1.z > v2 ? v1.z : v2;
+ return r;
+}
+
+extern float4 __attribute__((overloadable)) fmax(float4 v1, float v2) {
+ float4 r;
+ r.x = v1.x > v2 ? v1.x : v2;
+ r.y = v1.y > v2 ? v1.y : v2;
+ r.z = v1.z > v2 ? v1.z : v2;
+ r.w = v1.w > v2 ? v1.w : v2;
+ return r;
+}
+
+extern float __attribute__((overloadable)) fmin(float v1, float v2) {
+ return v1 < v2 ? v1 : v2;
+}
+
+
+/*
+ * FMIN
+ */
+extern float2 __attribute__((overloadable)) fmin(float2 v1, float2 v2) {
+ float2 r;
+ r.x = v1.x < v2.x ? v1.x : v2.x;
+ r.y = v1.y < v2.y ? v1.y : v2.y;
+ return r;
+}
+
+extern float3 __attribute__((overloadable)) fmin(float3 v1, float3 v2) {
+ float3 r;
+ r.x = v1.x < v2.x ? v1.x : v2.x;
+ r.y = v1.y < v2.y ? v1.y : v2.y;
+ r.z = v1.z < v2.z ? v1.z : v2.z;
+ return r;
+}
+
+extern float4 __attribute__((overloadable)) fmin(float4 v1, float4 v2) {
+ float4 r;
+ r.x = v1.x < v2.x ? v1.x : v2.x;
+ r.y = v1.y < v2.y ? v1.y : v2.y;
+ r.z = v1.z < v2.z ? v1.z : v2.z;
+ r.w = v1.w < v2.w ? v1.w : v2.w;
+ return r;
+}
+
+extern float2 __attribute__((overloadable)) fmin(float2 v1, float v2) {
+ float2 r;
+ r.x = v1.x < v2 ? v1.x : v2;
+ r.y = v1.y < v2 ? v1.y : v2;
+ return r;
+}
+
+extern float3 __attribute__((overloadable)) fmin(float3 v1, float v2) {
+ float3 r;
+ r.x = v1.x < v2 ? v1.x : v2;
+ r.y = v1.y < v2 ? v1.y : v2;
+ r.z = v1.z < v2 ? v1.z : v2;
+ return r;
+}
+
+extern float4 __attribute__((overloadable)) fmin(float4 v1, float v2) {
+ float4 r;
+ r.x = v1.x < v2 ? v1.x : v2;
+ r.y = v1.y < v2 ? v1.y : v2;
+ r.z = v1.z < v2 ? v1.z : v2;
+ r.w = v1.w < v2 ? v1.w : v2;
+ return r;
+}
+
+/*
+ * YUV
+ */
+extern uchar4 __attribute__((overloadable)) rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
+ short Y = ((short)y) - 16;
+ short U = ((short)u) - 128;
+ short V = ((short)v) - 128;
+
+ short4 p;
+ p.r = (Y * 298 + V * 409 + 128) >> 8;
+ p.g = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
+ p.b = (Y * 298 + U * 516 + 128) >> 8;
+ p.a = 255;
+ p.r = rsClamp(p.r, (short)0, (short)255);
+ p.g = rsClamp(p.g, (short)0, (short)255);
+ p.b = rsClamp(p.b, (short)0, (short)255);
+
+ return convert_uchar4(p);
+}
+
+static float4 yuv_U_values = {0.f, -0.392f * 0.003921569f, +2.02 * 0.003921569f, 0.f};
+static float4 yuv_V_values = {1.603f * 0.003921569f, -0.815f * 0.003921569f, 0.f, 0.f};
+
+extern float4 __attribute__((overloadable)) rsYuvToRGBA_float4(uchar y, uchar u, uchar v) {
+ float4 color = (float)y * 0.003921569f;
+ float4 fU = ((float)u) - 128.f;
+ float4 fV = ((float)v) - 128.f;
+
+ color += fU * yuv_U_values;
+ color += fV * yuv_V_values;
+ color = clamp(color, 0.f, 1.f);
+ return color;
+}
+
diff --git a/lib/ScriptCRT/arch/neon.ll b/lib/ScriptCRT/arch/neon.ll
new file mode 100644
index 0000000..958f2e8
--- /dev/null
+++ b/lib/ScriptCRT/arch/neon.ll
@@ -0,0 +1,264 @@
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; INTRINSICS ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float>, <2 x float>) nounwind readnone
+declare <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float>, <4 x float>) nounwind readnone
+declare <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float>, <2 x float>) nounwind readnone
+declare <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float>, <4 x float>) nounwind readnone
+
+declare <8 x i8> @llvm.arm.neon.vqshiftns.v8i8(<8 x i16>, <8 x i16>) nounwind readnone
+declare <4 x i16> @llvm.arm.neon.vqshiftns.v4i16(<4 x i32>, <4 x i32>) nounwind readnone
+declare <2 x i32> @llvm.arm.neon.vqshiftns.v2i32(<2 x i64>, <2 x i64>) nounwind readnone
+
+declare <8 x i8> @llvm.arm.neon.vqshiftnu.v8i8(<8 x i16>, <8 x i16>) nounwind readnone
+declare <4 x i16> @llvm.arm.neon.vqshiftnu.v4i16(<4 x i32>, <4 x i32>) nounwind readnone
+declare <2 x i32> @llvm.arm.neon.vqshiftnu.v2i32(<2 x i64>, <2 x i64>) nounwind readnone
+
+declare <8 x i8> @llvm.arm.neon.vqshiftnsu.v8i8(<8 x i16>, <8 x i16>) nounwind readnone
+declare <4 x i16> @llvm.arm.neon.vqshiftnsu.v4i16(<4 x i32>, <4 x i32>) nounwind readnone
+declare <2 x i32> @llvm.arm.neon.vqshiftnsu.v2i32(<2 x i64>, <2 x i64>) nounwind readnone
+
+declare <4 x i32> @llvm.arm.neon.vmins.v4i32(<4 x i32>, <4 x i32>) nounwind readnone
+declare <4 x i32> @llvm.arm.neon.vmaxs.v4i32(<4 x i32>, <4 x i32>) nounwind readnone
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; HELPERS ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define internal <4 x float> @smear_4f(float %in) nounwind readnone alwaysinline {
+ %1 = insertelement <4 x float> undef, float %in, i32 0
+ %2 = insertelement <4 x float> %1, float %in, i32 1
+ %3 = insertelement <4 x float> %2, float %in, i32 2
+ %4 = insertelement <4 x float> %3, float %in, i32 3
+ ret <4 x float> %4
+}
+
+define internal <2 x float> @smear_2f(float %in) nounwind readnone alwaysinline {
+ %1 = insertelement <2 x float> undef, float %in, i32 0
+ %2 = insertelement <2 x float> %1, float %in, i32 1
+ ret <2 x float> %2
+}
+
+define internal <4 x i32> @smear_4i32(i32 %in) nounwind readnone alwaysinline {
+ %1 = insertelement <4 x i32> undef, i32 %in, i32 0
+ %2 = insertelement <4 x i32> %1, i32 %in, i32 1
+ %3 = insertelement <4 x i32> %2, i32 %in, i32 2
+ %4 = insertelement <4 x i32> %3, i32 %in, i32 3
+ ret <4 x i32> %4
+}
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; CLAMP ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %low, <4 x float> %high) nounwind readonly {
+ %1 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %value, <4 x float> %high) nounwind readnone
+ %2 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %low) nounwind readnone
+ ret <4 x float> %2
+}
+
+define <4 x float> @_Z5clampDv4_fff(<4 x float> %value, float %low, float %high) nounwind readonly {
+ %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
+ %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
+ %out = tail call <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %_low, <4 x float> %_high) nounwind readonly
+ ret <4 x float> %out
+}
+
+define <3 x float> @_Z5clampDv3_fS_S_(<3 x float> %value, <3 x float> %low, <3 x float> %high) nounwind readonly {
+ %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %_low = shufflevector <3 x float> %low, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %_high = shufflevector <3 x float> %high, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
+ %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
+ %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+ ret <3 x float> %c
+}
+
+define <3 x float> @_Z5clampDv3_fff(<3 x float> %value, float %low, float %high) nounwind readonly {
+ %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
+ %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
+ %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
+ %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
+ %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+ ret <3 x float> %c
+}
+
+define <2 x float> @_Z5clampDv2_fS_S_(<2 x float> %value, <2 x float> %low, <2 x float> %high) nounwind readonly {
+ %1 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %high) nounwind readnone
+ %2 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %1, <2 x float> %low) nounwind readnone
+ ret <2 x float> %2
+}
+
+define <2 x float> @_Z5clampDv2_fff(<2 x float> %value, float %low, float %high) nounwind readonly {
+ %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
+ %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
+ %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %_high) nounwind readnone
+ %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
+ ret <2 x float> %b
+}
+
+
+define float @_Z5clampfff(float %value, float %low, float %high) nounwind readonly {
+ %_value = tail call <2 x float> @smear_2f(float %value) nounwind readnone
+ %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
+ %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
+ %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %_value, <2 x float> %_high) nounwind readnone
+ %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
+ %c = extractelement <2 x float> %b, i32 0
+ ret float %c
+}
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; FMAX ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <4 x float> @_Z4fmaxDv4_fS_(<4 x float> %v1, <4 x float> %v2) nounwind readonly {
+ %1 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %v1, <4 x float> %v2) nounwind readnone
+ ret <4 x float> %1
+}
+
+define <4 x float> @_Z4fmaxDv4_ff(<4 x float> %v1, float %v2) nounwind readonly {
+ %1 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+ %2 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %v1, <4 x float> %1) nounwind readnone
+ ret <4 x float> %2
+}
+
+define <3 x float> @_Z4fmaxDv3_fS_(<3 x float> %v1, <3 x float> %v2) nounwind readonly {
+ %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %2 = shufflevector <3 x float> %v2, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %3 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+ %4 = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+ ret <3 x float> %4
+}
+
+define <3 x float> @_Z4fmaxDv3_ff(<3 x float> %v1, float %v2) nounwind readonly {
+ %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %2 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+ %3 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+ %c = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+ ret <3 x float> %c
+}
+
+define <2 x float> @_Z4fmaxDv2_fS_(<2 x float> %v1, <2 x float> %v2) nounwind readonly {
+ %1 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %v1, <2 x float> %v2) nounwind readnone
+ ret <2 x float> %1
+}
+
+define <2 x float> @_Z4fmaxDv2_ff(<2 x float> %v1, float %v2) nounwind readonly {
+ %1 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+ %2 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %v1, <2 x float> %1) nounwind readnone
+ ret <2 x float> %2
+}
+
+define float @_Z4fmaxff(float %v1, float %v2) nounwind readonly {
+ %1 = tail call <2 x float> @smear_2f(float %v1) nounwind readnone
+ %2 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+ %3 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %1, <2 x float> %2) nounwind readnone
+ %4 = extractelement <2 x float> %3, i32 0
+ ret float %4
+}
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; FMIN ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+define <4 x float> @_Z4fminDv4_fS_(<4 x float> %v1, <4 x float> %v2) nounwind readonly {
+ %1 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %v1, <4 x float> %v2) nounwind readnone
+ ret <4 x float> %1
+}
+
+define <4 x float> @_Z4fminDv4_ff(<4 x float> %v1, float %v2) nounwind readonly {
+ %1 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+ %2 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %v1, <4 x float> %1) nounwind readnone
+ ret <4 x float> %2
+}
+
+define <3 x float> @_Z4fminDv3_fS_(<3 x float> %v1, <3 x float> %v2) nounwind readonly {
+ %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %2 = shufflevector <3 x float> %v2, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %3 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+ %4 = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+ ret <3 x float> %4
+}
+
+define <3 x float> @_Z4fminDv3_ff(<3 x float> %v1, float %v2) nounwind readonly {
+ %1 = shufflevector <3 x float> %v1, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %2 = tail call <4 x float> @smear_4f(float %v2) nounwind readnone
+ %3 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %1, <4 x float> %2) nounwind readnone
+ %c = shufflevector <4 x float> %3, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
+ ret <3 x float> %c
+}
+
+define <2 x float> @_Z4fminDv2_fS_(<2 x float> %v1, <2 x float> %v2) nounwind readonly {
+ %1 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %v1, <2 x float> %v2) nounwind readnone
+ ret <2 x float> %1
+}
+
+define <2 x float> @_Z4fminDv2_ff(<2 x float> %v1, float %v2) nounwind readonly {
+ %1 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+ %2 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %v1, <2 x float> %1) nounwind readnone
+ ret <2 x float> %2
+}
+
+define float @_Z4fminff(float %v1, float %v2) nounwind readonly {
+ %1 = tail call <2 x float> @smear_2f(float %v1) nounwind readnone
+ %2 = tail call <2 x float> @smear_2f(float %v2) nounwind readnone
+ %3 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %1, <2 x float> %2) nounwind readnone
+ %4 = extractelement <2 x float> %3, i32 0
+ ret float %4
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; YUV ;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+@yuv_U = internal constant <4 x i32> <i32 0, i32 -100, i32 516, i32 0>, align 16
+@yuv_V = internal constant <4 x i32> <i32 409, i32 -208, i32 0, i32 0>, align 16
+@yuv_0 = internal constant <4 x i32> <i32 0, i32 0, i32 0, i32 0>, align 16
+@yuv_255 = internal constant <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>, align 16
+
+
+define <4 x i8> @_Z18rsYuvToRGBA_uchar4hhh(i8 %pY, i8 %pU, i8 %pV) nounwind readnone alwaysinline {
+ %_sy = zext i8 %pY to i32
+ %_su = zext i8 %pU to i32
+ %_sv = zext i8 %pV to i32
+
+ %_sy2 = add i32 -16, %_sy
+ %_sy3 = mul i32 298, %_sy2
+ %_su2 = add i32 -128, %_su
+ %_sv2 = add i32 -128, %_sv
+ %_y = tail call <4 x i32> @smear_4i32(i32 %_sy3) nounwind readnone
+ %_u = tail call <4 x i32> @smear_4i32(i32 %_su2) nounwind readnone
+ %_v = tail call <4 x i32> @smear_4i32(i32 %_sv2) nounwind readnone
+
+ %mu = load <4 x i32>* @yuv_U, align 8
+ %mv = load <4 x i32>* @yuv_V, align 8
+ %_u2 = mul <4 x i32> %_u, %mu
+ %_v2 = mul <4 x i32> %_v, %mv
+ %_y2 = add <4 x i32> %_y, %_u2
+ %_y3 = add <4 x i32> %_y2, %_v2
+
+ ; %r1 = tail call <4 x i16> @llvm.arm.neon.vqshiftnsu.v4i16(<4 x i32> %_y3, <4 x i32> <i32 8, i32 8, i32 8, i32 8>) nounwind readnone
+; %r2 = trunc <4 x i16> %r1 to <4 x i8>
+; ret <4 x i8> %r2
+
+ %c0 = load <4 x i32>* @yuv_0, align 8
+ %c255 = load <4 x i32>* @yuv_255, align 8
+ %r1 = tail call <4 x i32> @llvm.arm.neon.vmaxs.v4i32(<4 x i32> %_y3, <4 x i32> %c0) nounwind readnone
+ %r2 = tail call <4 x i32> @llvm.arm.neon.vmins.v4i32(<4 x i32> %r1, <4 x i32> %c255) nounwind readnone
+ %r3 = lshr <4 x i32> %r2, <i32 8, i32 8, i32 8, i32 8>
+ %r4 = trunc <4 x i32> %r3 to <4 x i8>
+ ret <4 x i8> %r4
+}
+
diff --git a/lib/ScriptCRT/clamp.c b/lib/ScriptCRT/clamp.c
deleted file mode 100644
index c7e2c39..0000000
--- a/lib/ScriptCRT/clamp.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 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 "rs_types.rsh"
-
-extern float __attribute__((overloadable)) clamp(float amount, float low, float high) {
- return amount < low ? low : (amount > high ? high : amount);
-}
-
-extern float2 __attribute__((overloadable)) clamp(float2 amount, float2 low, float2 high) {
- float2 r;
- r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
- r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
- return r;
-}
-
-extern float3 __attribute__((overloadable)) clamp(float3 amount, float3 low, float3 high) {
- float3 r;
- r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
- r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
- r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
- return r;
-}
-
-extern float4 __attribute__((overloadable)) clamp(float4 amount, float4 low, float4 high) {
- float4 r;
- r.x = amount.x < low.x ? low.x : (amount.x > high.x ? high.x : amount.x);
- r.y = amount.y < low.y ? low.y : (amount.y > high.y ? high.y : amount.y);
- r.z = amount.z < low.z ? low.z : (amount.z > high.z ? high.z : amount.z);
- r.w = amount.w < low.w ? low.w : (amount.w > high.w ? high.w : amount.w);
- return r;
-}
-
-extern float2 __attribute__((overloadable)) clamp(float2 amount, float low, float high) {
- float2 r;
- r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
- r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
- return r;
-}
-
-extern float3 __attribute__((overloadable)) clamp(float3 amount, float low, float high) {
- float3 r;
- r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
- r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
- r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
- return r;
-}
-
-extern float4 __attribute__((overloadable)) clamp(float4 amount, float low, float high) {
- float4 r;
- r.x = amount.x < low ? low : (amount.x > high ? high : amount.x);
- r.y = amount.y < low ? low : (amount.y > high ? high : amount.y);
- r.z = amount.z < low ? low : (amount.z > high ? high : amount.z);
- r.w = amount.w < low ? low : (amount.w > high ? high : amount.w);
- return r;
-}
-
-
diff --git a/lib/ScriptCRT/neon/clamp.ll b/lib/ScriptCRT/neon/clamp.ll
deleted file mode 100644
index 4bcbdaa..0000000
--- a/lib/ScriptCRT/neon/clamp.ll
+++ /dev/null
@@ -1,81 +0,0 @@
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
-target triple = "armv7-none-linux-gnueabi"
-
-define internal <4 x float> @smear_4f(float %in) nounwind readnone alwaysinline {
- %1 = insertelement <4 x float> undef, float %in, i32 0
- %2 = insertelement <4 x float> %1, float %in, i32 1
- %3 = insertelement <4 x float> %2, float %in, i32 2
- %4 = insertelement <4 x float> %3, float %in, i32 3
- ret <4 x float> %4
-}
-
-define internal <2 x float> @smear_2f(float %in) nounwind readnone alwaysinline {
- %1 = insertelement <2 x float> undef, float %in, i32 0
- %2 = insertelement <2 x float> %1, float %in, i32 1
- ret <2 x float> %2
-}
-
-declare <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float>, <2 x float>) nounwind readnone
-declare <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float>, <4 x float>) nounwind readnone
-declare <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float>, <2 x float>) nounwind readnone
-declare <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float>, <4 x float>) nounwind readnone
-
-define <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %low, <4 x float> %high) nounwind readonly {
- %1 = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %value, <4 x float> %high) nounwind readnone
- %2 = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %1, <4 x float> %low) nounwind readnone
- ret <4 x float> %2
-}
-
-define <4 x float> @_Z5clampDv4_fff(<4 x float> %value, float %low, float %high) nounwind readonly {
- %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
- %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
- %out = tail call <4 x float> @_Z5clampDv4_fS_S_(<4 x float> %value, <4 x float> %_low, <4 x float> %_high) nounwind readonly
- ret <4 x float> %out
-}
-
-define <3 x float> @_Z5clampDv3_fS_S_(<3 x float> %value, <3 x float> %low, <3 x float> %high) nounwind readonly {
- %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- %_low = shufflevector <3 x float> %low, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- %_high = shufflevector <3 x float> %high, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
- %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
- %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
- ret <3 x float> %c
-}
-
-define <3 x float> @_Z5clampDv3_fff(<3 x float> %value, float %low, float %high) nounwind readonly {
- %_value = shufflevector <3 x float> %value, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
- %_high = tail call <4 x float> @smear_4f(float %high) nounwind readnone
- %_low = tail call <4 x float> @smear_4f(float %low) nounwind readnone
- %a = tail call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %_value, <4 x float> %_high) nounwind readnone
- %b = tail call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %_low) nounwind readnone
- %c = shufflevector <4 x float> %b, <4 x float> undef, <3 x i32> <i32 0, i32 1, i32 2>
- ret <3 x float> %c
-}
-
-
-define <2 x float> @_Z5clampDv2_fS_S_(<2 x float> %value, <2 x float> %low, <2 x float> %high) nounwind readonly {
- %1 = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %high) nounwind readnone
- %2 = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %1, <2 x float> %low) nounwind readnone
- ret <2 x float> %2
-}
-
-define <2 x float> @_Z5clampDv2_fff(<2 x float> %value, float %low, float %high) nounwind readonly {
- %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
- %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
- %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %value, <2 x float> %_high) nounwind readnone
- %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
- ret <2 x float> %b
-}
-
-
-define float @_Z5clampfff(float %value, float %low, float %high) nounwind readonly {
- %_value = tail call <2 x float> @smear_2f(float %value) nounwind readnone
- %_low = tail call <2 x float> @smear_2f(float %low) nounwind readnone
- %_high = tail call <2 x float> @smear_2f(float %high) nounwind readnone
- %a = tail call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %_value, <2 x float> %_high) nounwind readnone
- %b = tail call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %_low) nounwind readnone
- %c = extractelement <2 x float> %b, i32 0
- ret float %c
-}
-
diff --git a/lib/ScriptCRT/rs_cl.c b/lib/ScriptCRT/rs_cl.c
index 8e6f8ef..f8fabc2 100644
--- a/lib/ScriptCRT/rs_cl.c
+++ b/lib/ScriptCRT/rs_cl.c
@@ -447,13 +447,7 @@
extern float __attribute__((overloadable)) fma(float, float, float);
FN_FUNC_FN_FN_FN(fma)
-extern float __attribute__((overloadable)) fmax(float, float);
-FN_FUNC_FN_FN(fmax);
-FN_FUNC_FN_F(fmax);
-
extern float __attribute__((overloadable)) fmin(float, float);
-FN_FUNC_FN_FN(fmin);
-FN_FUNC_FN_F(fmin);
extern float __attribute__((overloadable)) fmod(float, float);
FN_FUNC_FN_FN(fmod)
@@ -751,7 +745,15 @@
extern float __attribute__((overloadable)) degrees(float radians) {
return radians * (180.f / M_PI);
}
-FN_FUNC_FN(degrees)
+extern float2 __attribute__((overloadable)) degrees(float2 radians) {
+ return radians * (180.f / M_PI);
+}
+extern float3 __attribute__((overloadable)) degrees(float3 radians) {
+ return radians * (180.f / M_PI);
+}
+extern float4 __attribute__((overloadable)) degrees(float4 radians) {
+ return radians * (180.f / M_PI);
+}
extern float __attribute__((overloadable)) mix(float start, float stop, float amount) {
return start + (stop - start) * amount;
@@ -778,7 +780,15 @@
extern float __attribute__((overloadable)) radians(float degrees) {
return degrees * (M_PI / 180.f);
}
-FN_FUNC_FN(radians)
+extern float2 __attribute__((overloadable)) radians(float2 degrees) {
+ return degrees * (M_PI / 180.f);
+}
+extern float3 __attribute__((overloadable)) radians(float3 degrees) {
+ return degrees * (M_PI / 180.f);
+}
+extern float4 __attribute__((overloadable)) radians(float4 degrees) {
+ return degrees * (M_PI / 180.f);
+}
extern float __attribute__((overloadable)) step(float edge, float v) {
return (v < edge) ? 0.f : 1.f;
diff --git a/lib/ScriptCRT/rs_core.c b/lib/ScriptCRT/rs_core.c
index f655c05..aaf1336 100644
--- a/lib/ScriptCRT/rs_core.c
+++ b/lib/ScriptCRT/rs_core.c
@@ -2,29 +2,11 @@
#include "rs_graphics.rsh"
#include "rs_structs.h"
-/* Declaration of 4 basic functions in libRS */
-extern void __attribute__((overloadable))
- rsDebug(const char *, float, float);
-extern void __attribute__((overloadable))
- rsDebug(const char *, float, float, float);
-extern void __attribute__((overloadable))
- rsDebug(const char *, float, float, float, float);
+/* Function declarations from libRS */
extern float4 __attribute__((overloadable)) convert_float4(uchar4 c);
/* Implementation of Core Runtime */
-extern void __attribute__((overloadable)) rsDebug(const char *s, float2 v) {
- rsDebug(s, v.x, v.y);
-}
-
-extern void __attribute__((overloadable)) rsDebug(const char *s, float3 v) {
- rsDebug(s, v.x, v.y, v.z);
-}
-
-extern void __attribute__((overloadable)) rsDebug(const char *s, float4 v) {
- rsDebug(s, v.x, v.y, v.z, v.w);
-}
-
/*
extern uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b)
{
diff --git a/libbcc-config.mk b/libbcc-config.mk
index 37cc848..90e6fab 100644
--- a/libbcc-config.mk
+++ b/libbcc-config.mk
@@ -30,7 +30,6 @@
libbcc_DEBUG_MC_DISASSEMBLER := 0
-libbcc_USE_LOGGER := 1
libbcc_USE_FUNC_LOGGER := 0
libbcc_DEBUG_BCC_REFLECT := 0
libbcc_DEBUG_MC_REFLECT := 0
diff --git a/libbcc-gen-build-stamp.mk b/libbcc-gen-build-stamp.mk
index 22fe81d..a2d8374 100644
--- a/libbcc-gen-build-stamp.mk
+++ b/libbcc-gen-build-stamp.mk
@@ -55,3 +55,7 @@
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
+
+LOCAL_CFLAGS := \
+ -DHAVE_BCC_CONFIG_MK_H \
+ $(LOCAL_CFLAGS)
diff --git a/tools/bcc/Android.mk b/tools/bcc/Android.mk
index 414b4d2..3231228 100644
--- a/tools/bcc/Android.mk
+++ b/tools/bcc/Android.mk
@@ -14,9 +14,6 @@
# limitations under the License.
#
-ifeq (darwin,$(BUILD_OS))
-else
-
LOCAL_PATH := $(call my-dir)
# Executable for host
@@ -36,6 +33,10 @@
LOCAL_MODULE_TAGS := tests eng
+# The definition of those functions in libLLVMSupport may elude libbcc due to linker.
+# Should include libLLVMSupport since bcc references some functions within it.
+LOCAL_STATIC_LIBRARIES := libLLVMSupport
+LOCAL_SHARED_LIBRARIES := libbcc
LOCAL_LDLIBS = -ldl
LOCAL_CFLAGS += -D__HOST__ -Wall -Werror
@@ -60,5 +61,3 @@
include external/stlport/libstlport.mk
include $(BUILD_EXECUTABLE)
-
-endif