Project import
diff --git a/libbcc/Android.mk b/libbcc/Android.mk
new file mode 100644
index 0000000..4ed3ebd
--- /dev/null
+++ b/libbcc/Android.mk
@@ -0,0 +1,121 @@
+#
+# Copyright (C) 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+LIBBCC_ROOT_PATH := $(LOCAL_PATH)
+
+FORCE_BUILD_LLVM_DISABLE_NDEBUG ?= false
+# Legality check: FORCE_BUILD_LLVM_DISABLE_NDEBUG should consist of one word -- either "true" or "false".
+ifneq "$(words $(FORCE_BUILD_LLVM_DISABLE_NDEBUG))$(words $(filter-out true false,$(FORCE_BUILD_LLVM_DISABLE_NDEBUG)))" "10"
+  $(error FORCE_BUILD_LLVM_DISABLE_NDEBUG may only be true, false, or unset)
+endif
+
+FORCE_BUILD_LLVM_DEBUG ?= false
+# Legality check: FORCE_BUILD_LLVM_DEBUG should consist of one word -- either "true" or "false".
+ifneq "$(words $(FORCE_BUILD_LLVM_DEBUG))$(words $(filter-out true false,$(FORCE_BUILD_LLVM_DEBUG)))" "10"
+  $(error FORCE_BUILD_LLVM_DEBUG may only be true, false, or unset)
+endif
+
+include $(LIBBCC_ROOT_PATH)/libbcc.mk
+
+include frameworks/compile/slang/rs_version.mk
+
+#=====================================================================
+# Whole Static Library to Be Linked In
+#=====================================================================
+
+libbcc_WHOLE_STATIC_LIBRARIES += \
+  libbccRenderscript \
+  libbccCore \
+  libbccSupport
+
+#=====================================================================
+# Device Shared Library libbcc
+#=====================================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbcc
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+LOCAL_WHOLE_STATIC_LIBRARIES := $(libbcc_WHOLE_STATIC_LIBRARIES)
+
+LOCAL_SHARED_LIBRARIES := libbcinfo libLLVM libdl libutils libcutils liblog libc++
+
+# Modules that need get installed if and only if the target libbcc.so is
+# installed.
+LOCAL_REQUIRED_MODULES := libclcore.bc libclcore_debug.bc libclcore_g.bc libcompiler_rt
+
+LOCAL_REQUIRED_MODULES_x86 += libclcore_x86.bc
+LOCAL_REQUIRED_MODULES_x86_64 += libclcore_x86.bc
+
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+  LOCAL_REQUIRED_MODULES_arm += libclcore_neon.bc
+endif
+
+include $(LIBBCC_DEVICE_BUILD_MK)
+include $(LLVM_DEVICE_BUILD_MK)
+include $(BUILD_SHARED_LIBRARY)
+endif
+
+#=====================================================================
+# Host Shared Library libbcc
+#=====================================================================
+
+# Don't build for unbundled branches
+ifeq (,$(TARGET_BUILD_APPS))
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbcc
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_IS_HOST_MODULE := true
+
+LOCAL_WHOLE_STATIC_LIBRARIES += $(libbcc_WHOLE_STATIC_LIBRARIES)
+
+LOCAL_STATIC_LIBRARIES += \
+  libutils \
+  libcutils \
+  liblog
+
+LOCAL_SHARED_LIBRARIES := libbcinfo
+
+LOCAL_LDLIBS_darwin := -ldl -lpthread
+LOCAL_LDLIBS_linux := -ldl -lpthread
+
+include $(LIBBCC_ROOT_PATH)/llvm-loadable-libbcc.mk
+
+ifeq ($(CAN_BUILD_HOST_LLVM_LOADABLE_MODULE),true)
+LOCAL_STATIC_LIBRARIES_linux += libLLVMLinker
+else
+LOCAL_SHARED_LIBRARIES_linux += libLLVM
+endif
+LOCAL_SHARED_LIBRARIES_darwin += libLLVM
+LOCAL_SHARED_LIBRARIES_windows += libLLVM
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+endif # Don't build in unbundled branches
+
+#=====================================================================
+# Include Subdirectories
+#=====================================================================
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libbcc/CleanSpec.mk b/libbcc/CleanSpec.mk
new file mode 100644
index 0000000..86467c6
--- /dev/null
+++ b/libbcc/CleanSpec.mk
@@ -0,0 +1,72 @@
+# Copyright (C) 2007 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libbcc_intermediates)
+$(call add-clean-step, rm -rf $(HOST_OUT)/obj/SHARED_LIBRARIES/libbcc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libruntime.bc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libbcc_sha1_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libbcc_sha1.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore_neon.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore*.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libbcinfo_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libclcore*.bc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libbc*_intermediates)
+$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/libbc*_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libbc*_intermediates)
+$(call add-clean-step, rm -rf $(HOST_OUT)/obj/SHARED_LIBRARIES/libbc*_intermediates)
+$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/libbc*_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libbc*_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libbcc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libbcc.sha1_intermediates)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/libbcc/NOTICE b/libbcc/NOTICE
new file mode 100644
index 0000000..1344fe2
--- /dev/null
+++ b/libbcc/NOTICE
@@ -0,0 +1,322 @@
+==========================
+NOTICE file for libbcc.git
+==========================
+
+* NOTICE for lib/ExecutionEngine/, lib/ScriptCRT/, include and helper/.
+
+   Copyright (c) 2005-2011, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
+* NOTICE for runtime/ and lib/CodeGen/.
+  Note: The NOTICE is the same for another git project, external/llvm.git.
+
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties.  Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program             Directory
+-------             ---------
+Autoconf            llvm/autoconf
+                    llvm/projects/ModuleMaker/autoconf
+                    llvm/projects/sample/autoconf
+CellSPU backend     llvm/lib/Target/CellSPU/README.txt
+Google Test         llvm/utils/unittest/googletest
+OpenBSD regex       llvm/lib/Support/{reg*, COPYRIGHT.regex}
+
+
+
+* NOTICE for tests/disassem.cpp and tests/disassem.h.
+
+/*      $NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $    */
+
+/*-
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) 1996 Brini.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * db_disasm.c
+ *
+ * Kernel disassembler
+ *
+ * Created      : 10/02/96
+ *
+ * Structured after the sparc/sparc/db_disasm.c by David S. Miller &
+ * Paul Kranenburg
+ *
+ * This code is not complete. Not all instructions are disassembled.
+ */
diff --git a/libbcc/README.html b/libbcc/README.html
new file mode 100644
index 0000000..c4b9653
--- /dev/null
+++ b/libbcc/README.html
@@ -0,0 +1,473 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
+<title>libbcc: A Versatile Bitcode Execution Engine for Mobile Devices</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 5951 2009-05-18 18:03:10Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left{
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: left }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="libbcc-a-versatile-bitcode-execution-engine-for-mobile-devices">
+<h1 class="title">libbcc: A Versatile Bitcode Execution Engine for Mobile Devices</h1>
+
+<div class="section" id="introduction">
+<h1>Introduction</h1>
+<p>libbcc is an LLVM bitcode execution engine that compiles the bitcode
+to an in-memory executable. libbcc is versatile because:</p>
+<ul class="simple">
+<li>it implements both AOT (Ahead-of-Time) and JIT (Just-in-Time)
+compilation.</li>
+<li>Android devices demand fast start-up time, small size, and high
+performance <em>at the same time</em>. libbcc attempts to address these
+design constraints.</li>
+<li>it supports on-device linking. Each device vendor can supply his or
+her own runtime bitcode library (lib*.bc) that differentiates his or
+her system. Specialization becomes ecosystem-friendly.</li>
+</ul>
+<p>libbcc provides:</p>
+<ul class="simple">
+<li>a <em>just-in-time bitcode compiler</em>, which translates the LLVM bitcode
+into machine code</li>
+<li>a <em>caching mechanism</em>, which can:<ul>
+<li>after each compilation, serialize the in-memory executable into a
+cache file.  Note that the compilation is triggered by a cache
+miss.</li>
+<li>load from the cache file upon cache-hit.</li>
+</ul>
+</li>
+</ul>
+<p>Highlights of libbcc are:</p>
+<ul>
+<li><p class="first">libbcc supports bitcode from various language frontends, such as
+Renderscript, GLSL (pixelflinger2).</p>
+</li>
+<li><p class="first">libbcc strives to balance between library size, launch time and
+steady-state performance:</p>
+<ul>
+<li><p class="first">The size of libbcc is aggressively reduced for mobile devices. We
+customize and improve upon the default Execution Engine from
+upstream. Otherwise, libbcc's execution engine can easily become
+at least 2 times bigger.</p>
+</li>
+<li><p class="first">To reduce launch time, we support caching of
+binaries. Just-in-Time compilation are oftentimes Just-too-Late,
+if the given apps are performance-sensitive. Thus, we implemented
+AOT to get the best of both worlds: Fast launch time and high
+steady-state performance.</p>
+<p>AOT is also important for projects such as NDK on LLVM with
+portability enhancement. Launch time reduction after we
+implemented AOT is signficant:</p>
+<pre class="literal-block">
+Apps          libbcc without AOT       libbcc with AOT
+              launch time in libbcc    launch time in libbcc
+App_1            1218ms                   9ms
+App_2            842ms                    4ms
+Wallpaper:
+  MagicSmoke     182ms                    3ms
+  Halo           127ms                    3ms
+Balls            149ms                    3ms
+SceneGraph       146ms                    90ms
+Model            104ms                    4ms
+Fountain         57ms                     3ms
+</pre>
+<p>AOT also masks the launching time overhead of on-device linking
+and helps it become reality.</p>
+</li>
+<li><p class="first">For steady-state performance, we enable VFP3 and aggressive
+optimizations.</p>
+</li>
+</ul>
+</li>
+<li><p class="first">Currently we disable Lazy JITting.</p>
+</li>
+</ul>
+</div>
+<div class="section" id="api">
+<h1>API</h1>
+<p><strong>Basic:</strong></p>
+<ul class="simple">
+<li><strong>bccCreateScript</strong> - Create new bcc script</li>
+<li><strong>bccRegisterSymbolCallback</strong> - Register the callback function for external
+symbol lookup</li>
+<li><strong>bccReadBC</strong> - Set the source bitcode for compilation</li>
+<li><strong>bccReadModule</strong> - Set the llvm::Module for compilation</li>
+<li><strong>bccLinkBC</strong> - Set the library bitcode for linking</li>
+<li><strong>bccPrepareExecutable</strong> - <em>deprecated</em> - Use bccPrepareExecutableEx instead</li>
+<li><strong>bccPrepareExecutableEx</strong> - Create the in-memory executable by either
+just-in-time compilation or cache loading</li>
+<li><strong>bccGetFuncAddr</strong> - Get the entry address of the function</li>
+<li><strong>bccDisposeScript</strong> - Destroy bcc script and release the resources</li>
+<li><strong>bccGetError</strong> - <em>deprecated</em> - Don't use this</li>
+</ul>
+<p><strong>Reflection:</strong></p>
+<ul class="simple">
+<li><strong>bccGetExportVarCount</strong> - Get the count of exported variables</li>
+<li><strong>bccGetExportVarList</strong> - Get the addresses of exported variables</li>
+<li><strong>bccGetExportFuncCount</strong> - Get the count of exported functions</li>
+<li><strong>bccGetExportFuncList</strong> - Get the addresses of exported functions</li>
+<li><strong>bccGetPragmaCount</strong> - Get the count of pragmas</li>
+<li><strong>bccGetPragmaList</strong> - Get the pragmas</li>
+</ul>
+<p><strong>Debug:</strong></p>
+<ul class="simple">
+<li><strong>bccGetFuncCount</strong> - Get the count of functions (including non-exported)</li>
+<li><strong>bccGetFuncInfoList</strong> - Get the function information (name, base, size)</li>
+</ul>
+</div>
+<div class="section" id="cache-file-format">
+<h1>Cache File Format</h1>
+<p>A cache file (denoted as *.oBCC) for libbcc consists of several sections:
+header, string pool, dependencies table, relocation table, exported
+variable list, exported function list, pragma list, function information
+table, and bcc context.  Every section should be aligned to a word size.
+Here is the brief description of each sections:</p>
+<ul class="simple">
+<li><strong>Header</strong> (MCO_Header) - The header of a cache file. It contains the
+magic word, version, machine integer type information (the endianness,
+the size of off_t, size_t, and ptr_t), and the size
+and offset of other sections.  The header section is guaranteed
+to be at the beginning of the cache file.</li>
+<li><strong>String Pool</strong> (MCO_StringPool) - A collection of serialized variable
+length strings.  The strp_index in the other part of the cache file
+represents the index of such string in this string pool.</li>
+<li><strong>Dependencies Table</strong> (MCO_DependencyTable) - The dependencies table.
+This table stores the resource name (or file path), the resource
+type (rather in APK or on the file system), and the SHA1 checksum.</li>
+<li><strong>Relocation Table</strong> (MCO_RelocationTable) - <em>not enabled</em></li>
+<li><strong>Exported Variable List</strong> (MCO_ExportVarList) -
+The list of the addresses of exported variables.</li>
+<li><strong>Exported Function List</strong> (MCO_ExportFuncList) -
+The list of the addresses of exported functions.</li>
+<li><strong>Pragma List</strong> (MCO_PragmaList) - The list of pragma key-value pair.</li>
+<li><strong>Function Information Table</strong> (MCO_FuncTable) - This is a table of
+function information, such as function name, function entry address,
+and function binary size.  Besides, the table should be ordered by
+function name.</li>
+<li><strong>Context</strong> - The context of the in-memory executable, including
+the code and the data.  The offset of context should aligned to
+a page size, so that we can mmap the context directly into memory.</li>
+</ul>
+<p>For furthur information, you may read <a class="reference external" href="include/bcc/bcc_cache.h">bcc_cache.h</a>,
+<a class="reference external" href="lib/bcc/CacheReader.cpp">CacheReader.cpp</a>, and
+<a class="reference external" href="lib/bcc/CacheWriter.cpp">CacheWriter.cpp</a> for details.</p>
+</div>
+<div class="section" id="jit-ed-code-calling-conventions">
+<h1>JIT'ed Code Calling Conventions</h1>
+<ol class="arabic">
+<li><p class="first">Calls from Execution Environment or from/to within script:</p>
+<p>On ARM, the first 4 arguments will go into r0, r1, r2, and r3, in that order.
+The remaining (if any) will go through stack.</p>
+<p>For ext_vec_types such as float2, a set of registers will be used. In the case
+of float2, a register pair will be used. Specifically, if float2 is the first
+argument in the function prototype, float2.x will go into r0, and float2.y,
+r1.</p>
+<p>Note: stack will be aligned to the coarsest-grained argument. In the case of
+float2 above as an argument, parameter stack will be aligned to an 8-byte
+boundary (if the sizes of other arguments are no greater than 8.)</p>
+</li>
+<li><p class="first">Calls from/to a separate compilation unit: (E.g., calls to Execution
+Environment if those runtime library callees are not compiled using LLVM.)</p>
+<p>On ARM, we use hardfp.  Note that double will be placed in a register pair.</p>
+</li>
+</ol>
+</div>
+</div>
+</body>
+</html>
diff --git a/libbcc/README.rst b/libbcc/README.rst
new file mode 100644
index 0000000..a6db1f1
--- /dev/null
+++ b/libbcc/README.rst
@@ -0,0 +1,200 @@
+===============================================================
+libbcc: A Versatile Bitcode Execution Engine for Mobile Devices
+===============================================================
+
+
+Introduction
+------------
+
+libbcc is an LLVM bitcode execution engine that compiles the bitcode
+to an in-memory executable. libbcc is versatile because:
+
+* it implements both AOT (Ahead-of-Time) and JIT (Just-in-Time)
+  compilation.
+
+* Android devices demand fast start-up time, small size, and high
+  performance *at the same time*. libbcc attempts to address these
+  design constraints.
+
+* it supports on-device linking. Each device vendor can supply his or
+  her own runtime bitcode library (lib*.bc) that differentiates his or
+  her system. Specialization becomes ecosystem-friendly.
+
+libbcc provides:
+
+* a *just-in-time bitcode compiler*, which translates the LLVM bitcode
+  into machine code
+
+* a *caching mechanism*, which can:
+
+  * after each compilation, serialize the in-memory executable into a
+    cache file.  Note that the compilation is triggered by a cache
+    miss.
+  * load from the cache file upon cache-hit.
+
+Highlights of libbcc are:
+
+* libbcc supports bitcode from various language frontends, such as
+  Renderscript, GLSL (pixelflinger2).
+
+* libbcc strives to balance between library size, launch time and
+  steady-state performance:
+
+  * The size of libbcc is aggressively reduced for mobile devices. We
+    customize and improve upon the default Execution Engine from
+    upstream. Otherwise, libbcc's execution engine can easily become
+    at least 2 times bigger.
+
+  * To reduce launch time, we support caching of
+    binaries. Just-in-Time compilation are oftentimes Just-too-Late,
+    if the given apps are performance-sensitive. Thus, we implemented
+    AOT to get the best of both worlds: Fast launch time and high
+    steady-state performance.
+
+    AOT is also important for projects such as NDK on LLVM with
+    portability enhancement. Launch time reduction after we
+    implemented AOT is signficant::
+
+
+     Apps          libbcc without AOT       libbcc with AOT
+                   launch time in libbcc    launch time in libbcc
+     App_1            1218ms                   9ms
+     App_2            842ms                    4ms
+     Wallpaper:
+       MagicSmoke     182ms                    3ms
+       Halo           127ms                    3ms
+     Balls            149ms                    3ms
+     SceneGraph       146ms                    90ms
+     Model            104ms                    4ms
+     Fountain         57ms                     3ms
+
+    AOT also masks the launching time overhead of on-device linking
+    and helps it become reality.
+
+  * For steady-state performance, we enable VFP3 and aggressive
+    optimizations.
+
+* Currently we disable Lazy JITting.
+
+
+
+API
+---
+
+**Basic:**
+
+* **bccCreateScript** - Create new bcc script
+
+* **bccRegisterSymbolCallback** - Register the callback function for external
+  symbol lookup
+
+* **bccReadBC** - Set the source bitcode for compilation
+
+* **bccReadModule** - Set the llvm::Module for compilation
+
+* **bccLinkBC** - Set the library bitcode for linking
+
+* **bccPrepareExecutable** - *deprecated* - Use bccPrepareExecutableEx instead
+
+* **bccPrepareExecutableEx** - Create the in-memory executable by either
+  just-in-time compilation or cache loading
+
+* **bccGetFuncAddr** - Get the entry address of the function
+
+* **bccDisposeScript** - Destroy bcc script and release the resources
+
+* **bccGetError** - *deprecated* - Don't use this
+
+
+**Reflection:**
+
+* **bccGetExportVarCount** - Get the count of exported variables
+
+* **bccGetExportVarList** - Get the addresses of exported variables
+
+* **bccGetExportFuncCount** - Get the count of exported functions
+
+* **bccGetExportFuncList** - Get the addresses of exported functions
+
+* **bccGetPragmaCount** - Get the count of pragmas
+
+* **bccGetPragmaList** - Get the pragmas
+
+
+**Debug:**
+
+* **bccGetFuncCount** - Get the count of functions (including non-exported)
+
+* **bccGetFuncInfoList** - Get the function information (name, base, size)
+
+
+
+Cache File Format
+-----------------
+
+A cache file (denoted as \*.oBCC) for libbcc consists of several sections:
+header, string pool, dependencies table, relocation table, exported
+variable list, exported function list, pragma list, function information
+table, and bcc context.  Every section should be aligned to a word size.
+Here is the brief description of each sections:
+
+* **Header** (MCO_Header) - The header of a cache file. It contains the
+  magic word, version, machine integer type information (the endianness,
+  the size of off_t, size_t, and ptr_t), and the size
+  and offset of other sections.  The header section is guaranteed
+  to be at the beginning of the cache file.
+
+* **String Pool** (MCO_StringPool) - A collection of serialized variable
+  length strings.  The strp_index in the other part of the cache file
+  represents the index of such string in this string pool.
+
+* **Dependencies Table** (MCO_DependencyTable) - The dependencies table.
+  This table stores the resource name (or file path), the resource
+  type (rather in APK or on the file system), and the SHA1 checksum.
+
+* **Relocation Table** (MCO_RelocationTable) - *not enabled*
+
+* **Exported Variable List** (MCO_ExportVarList) -
+  The list of the addresses of exported variables.
+
+* **Exported Function List** (MCO_ExportFuncList) -
+  The list of the addresses of exported functions.
+
+* **Pragma List** (MCO_PragmaList) - The list of pragma key-value pair.
+
+* **Function Information Table** (MCO_FuncTable) - This is a table of
+  function information, such as function name, function entry address,
+  and function binary size.  Besides, the table should be ordered by
+  function name.
+
+* **Context** - The context of the in-memory executable, including
+  the code and the data.  The offset of context should aligned to
+  a page size, so that we can mmap the context directly into memory.
+
+For furthur information, you may read `bcc_cache.h <include/bcc/bcc_cache.h>`_,
+`CacheReader.cpp <lib/bcc/CacheReader.cpp>`_, and
+`CacheWriter.cpp <lib/bcc/CacheWriter.cpp>`_ for details.
+
+
+
+JIT'ed Code Calling Conventions
+-------------------------------
+
+1. Calls from Execution Environment or from/to within script:
+
+   On ARM, the first 4 arguments will go into r0, r1, r2, and r3, in that order.
+   The remaining (if any) will go through stack.
+
+   For ext_vec_types such as float2, a set of registers will be used. In the case
+   of float2, a register pair will be used. Specifically, if float2 is the first
+   argument in the function prototype, float2.x will go into r0, and float2.y,
+   r1.
+
+   Note: stack will be aligned to the coarsest-grained argument. In the case of
+   float2 above as an argument, parameter stack will be aligned to an 8-byte
+   boundary (if the sizes of other arguments are no greater than 8.)
+
+2. Calls from/to a separate compilation unit: (E.g., calls to Execution
+   Environment if those runtime library callees are not compiled using LLVM.)
+
+   On ARM, we use hardfp.  Note that double will be placed in a register pair.
diff --git a/libbcc/bcinfo/Android.mk b/libbcc/bcinfo/Android.mk
new file mode 100644
index 0000000..46b61a7
--- /dev/null
+++ b/libbcc/bcinfo/Android.mk
@@ -0,0 +1,105 @@
+#
+# 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.
+# 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.
+#
+
+local_cflags_for_libbcinfo := -Wall -Wno-unused-parameter -Werror
+ifneq ($(TARGET_BUILD_VARIANT),eng)
+local_cflags_for_libbcinfo += -D__DISABLE_ASSERTS
+endif
+
+LOCAL_PATH := $(call my-dir)
+
+include frameworks/compile/slang/rs_version.mk
+local_cflags_for_libbcinfo += $(RS_VERSION_DEFINE)
+
+libbcinfo_SRC_FILES := \
+  BitcodeTranslator.cpp \
+  BitcodeWrapper.cpp \
+  MetadataExtractor.cpp
+
+libbcinfo_C_INCLUDES := \
+  $(LOCAL_PATH)/../include \
+  $(RS_ROOT_PATH) \
+  $(LOCAL_PATH)/../../slang
+
+libbcinfo_STATIC_LIBRARIES := \
+  libLLVMWrap \
+  libLLVMBitReader_2_7 \
+  libLLVMBitReader_3_0 \
+  libLLVMBitWriter_3_2
+
+LLVM_ROOT_PATH := external/llvm
+
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbcinfo
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(libbcinfo_SRC_FILES)
+
+LOCAL_CFLAGS += $(local_cflags_for_libbcinfo)
+
+LOCAL_C_INCLUDES := $(libbcinfo_C_INCLUDES)
+
+LOCAL_STATIC_LIBRARIES := $(libbcinfo_STATIC_LIBRARIES)
+LOCAL_SHARED_LIBRARIES := libLLVM libcutils liblog
+
+include $(LLVM_ROOT_PATH)/llvm-device-build.mk
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(BUILD_SHARED_LIBRARY)
+endif
+
+# Don't build for unbundled branches
+ifeq (,$(TARGET_BUILD_APPS))
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbcinfo
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_IS_HOST_MODULE := true
+
+LOCAL_SRC_FILES := $(libbcinfo_SRC_FILES)
+
+LOCAL_CFLAGS += $(local_cflags_for_libbcinfo)
+
+LOCAL_C_INCLUDES := $(libbcinfo_C_INCLUDES)
+
+LOCAL_STATIC_LIBRARIES += $(libbcinfo_STATIC_LIBRARIES)
+LOCAL_STATIC_LIBRARIES += libcutils liblog
+
+LOCAL_LDLIBS_darwin := -ldl -lpthread
+LOCAL_LDLIBS_linux := -ldl -lpthread
+
+include $(LOCAL_PATH)/../llvm-loadable-libbcc.mk
+
+ifneq ($(CAN_BUILD_HOST_LLVM_LOADABLE_MODULE),true)
+LOCAL_SHARED_LIBRARIES_linux += libLLVM
+endif
+LOCAL_SHARED_LIBRARIES_darwin += libLLVM
+LOCAL_SHARED_LIBRARIES_windows += libLLVM
+
+include $(LLVM_ROOT_PATH)/llvm-host-build.mk
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+endif # don't build for unbundled branches
+
+#=====================================================================
+# Include Subdirectories
+#=====================================================================
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libbcc/bcinfo/BitReader_2_7/Android.mk b/libbcc/bcinfo/BitReader_2_7/Android.mk
new file mode 100644
index 0000000..773c3c9
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_2_7/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH:= $(call my-dir)
+
+LLVM_ROOT_PATH := external/llvm
+include $(LLVM_ROOT_PATH)/llvm.mk
+
+bitcode_reader_2_7_SRC_FILES := \
+  BitcodeReader.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(bitcode_reader_2_7_SRC_FILES)
+
+LOCAL_CFLAGS += -D__HOST__
+
+LOCAL_MODULE:= libLLVMBitReader_2_7
+
+LOCAL_MODULE_HOST_OS := darwin linux windows
+
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(bitcode_reader_2_7_SRC_FILES)
+
+LOCAL_MODULE:= libLLVMBitReader_2_7
+
+include $(LLVM_DEVICE_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/libbcc/bcinfo/BitReader_2_7/BitReader.cpp b/libbcc/bcinfo/BitReader_2_7/BitReader.cpp
new file mode 100644
index 0000000..15844c0
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_2_7/BitReader.cpp
@@ -0,0 +1,88 @@
+//===-- BitReader.cpp -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/BitReader.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <string>
+#include <cstring>
+
+using namespace llvm;
+
+/* Builds a module from the bitcode in the specified memory buffer, returning a
+   reference to the module via the OutModule parameter. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */
+LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf,
+                          LLVMModuleRef *OutModule, char **OutMessage) {
+  return LLVMParseBitcodeInContext(wrap(&getGlobalContext()), MemBuf, OutModule,
+                                   OutMessage);
+}
+
+LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef,
+                                   LLVMMemoryBufferRef MemBuf,
+                                   LLVMModuleRef *OutModule,
+                                   char **OutMessage) {
+  std::string Message;
+  
+  *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), *unwrap(ContextRef),
+                                     &Message));
+  if (!*OutModule) {
+    if (OutMessage)
+      *OutMessage = strdup(Message.c_str());
+    return 1;
+  }
+  
+  return 0;
+}
+
+/* Reads a module from the specified path, returning via the OutModule parameter
+   a module provider which performs lazy deserialization. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */ 
+LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef,
+                                       LLVMMemoryBufferRef MemBuf,
+                                       LLVMModuleRef *OutM,
+                                       char **OutMessage) {
+  std::string Message;
+  
+  *OutM = wrap(getLazyBitcodeModule(unwrap(MemBuf), *unwrap(ContextRef),
+                                    &Message));
+  if (!*OutM) {
+    if (OutMessage)
+      *OutMessage = strdup(Message.c_str());
+    return 1;
+  }
+  
+  return 0;
+
+}
+
+LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
+                              char **OutMessage) {
+  return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM,
+                                       OutMessage);
+}
+
+/* Deprecated: Use LLVMGetBitcodeModuleInContext instead. */
+LLVMBool LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef,
+                                               LLVMMemoryBufferRef MemBuf,
+                                               LLVMModuleProviderRef *OutMP,
+                                               char **OutMessage) {
+  return LLVMGetBitcodeModuleInContext(ContextRef, MemBuf,
+                                       reinterpret_cast<LLVMModuleRef*>(OutMP),
+                                       OutMessage);
+}
+
+/* Deprecated: Use LLVMGetBitcodeModule instead. */
+LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf,
+                                      LLVMModuleProviderRef *OutMP,
+                                      char **OutMessage) {
+  return LLVMGetBitcodeModuleProviderInContext(LLVMGetGlobalContext(), MemBuf,
+                                               OutMP, OutMessage);
+}
diff --git a/libbcc/bcinfo/BitReader_2_7/BitReader_2_7.h b/libbcc/bcinfo/BitReader_2_7/BitReader_2_7.h
new file mode 100644
index 0000000..d3b712f
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_2_7/BitReader_2_7.h
@@ -0,0 +1,65 @@
+//===- BitReader_2_7.h - Internal BitcodeReader 2.7 impl --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BITREADER_2_7_H
+#define BITREADER_2_7_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/GVMaterializer.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Support/ErrorOr.h"
+#include <string>
+
+namespace llvm {
+  class LLVMContext;
+  class MemoryBuffer;
+  class MemoryBufferRef;
+  class Module;
+} // End llvm namespace
+
+namespace llvm_2_7 {
+
+using llvm::DiagnosticHandlerFunction;
+using llvm::LLVMContext;
+using llvm::MemoryBuffer;
+using llvm::MemoryBufferRef;
+
+
+  /// Read the header of the specified bitcode buffer and prepare for lazy
+  /// deserialization of function bodies.  If successful, this moves Buffer. On
+  /// error, this *does not* move Buffer.
+  llvm::ErrorOr<llvm::Module *>
+  getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
+                       LLVMContext &Context,
+                       const DiagnosticHandlerFunction &DiagnosticHandler = nullptr);
+
+  /// Read the header of the specified bitcode buffer and extract just the
+  /// triple information. If successful, this returns a string. On error, this
+  /// returns "".
+  std::string
+  getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context,
+                         DiagnosticHandlerFunction DiagnosticHandler = nullptr);
+
+  /// Read the specified bitcode file, returning the module.
+  llvm::ErrorOr<llvm::Module *>
+  parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
+                   const DiagnosticHandlerFunction &DiagnosticHandler = nullptr);
+} // End llvm_2_7 namespace
+
+#endif
diff --git a/libbcc/bcinfo/BitReader_2_7/BitcodeReader.cpp b/libbcc/bcinfo/BitReader_2_7/BitcodeReader.cpp
new file mode 100644
index 0000000..c66ea1c
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_2_7/BitcodeReader.cpp
@@ -0,0 +1,3545 @@
+//===- BitcodeReader.cpp - Internal BitcodeReader implementation ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "BitReader_2_7.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/AutoUpgrade.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/GVMaterializer.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace llvm;
+using namespace llvm_2_7;
+
+#define METADATA_NODE_2_7             2
+#define METADATA_FN_NODE_2_7          3
+#define METADATA_NAMED_NODE_2_7       5
+#define METADATA_ATTACHMENT_2_7       7
+#define FUNC_CODE_INST_UNWIND_2_7     14
+#define FUNC_CODE_INST_MALLOC_2_7     17
+#define FUNC_CODE_INST_FREE_2_7       18
+#define FUNC_CODE_INST_STORE_2_7      21
+#define FUNC_CODE_INST_CALL_2_7       22
+#define FUNC_CODE_INST_GETRESULT_2_7  25
+#define FUNC_CODE_DEBUG_LOC_2_7       32
+
+#define TYPE_BLOCK_ID_OLD_3_0         10
+#define TYPE_SYMTAB_BLOCK_ID_OLD_3_0  13
+#define TYPE_CODE_STRUCT_OLD_3_0      10
+
+namespace {
+
+  void StripDebugInfoOfFunction(Module* M, const char* name) {
+    if (Function* FuncStart = M->getFunction(name)) {
+      while (!FuncStart->use_empty()) {
+        cast<CallInst>(*FuncStart->use_begin())->eraseFromParent();
+      }
+      FuncStart->eraseFromParent();
+    }
+  }
+
+  /// This function strips all debug info intrinsics, except for llvm.dbg.declare.
+  /// If an llvm.dbg.declare intrinsic is invalid, then this function simply
+  /// strips that use.
+  void CheckDebugInfoIntrinsics(Module *M) {
+    StripDebugInfoOfFunction(M, "llvm.dbg.func.start");
+    StripDebugInfoOfFunction(M, "llvm.dbg.stoppoint");
+    StripDebugInfoOfFunction(M, "llvm.dbg.region.start");
+    StripDebugInfoOfFunction(M, "llvm.dbg.region.end");
+
+    if (Function *Declare = M->getFunction("llvm.dbg.declare")) {
+      if (!Declare->use_empty()) {
+        DbgDeclareInst *DDI = cast<DbgDeclareInst>(*Declare->use_begin());
+        if (!isa<MDNode>(ValueAsMetadata::get(DDI->getArgOperand(0))) ||
+            !isa<MDNode>(ValueAsMetadata::get(DDI->getArgOperand(1)))) {
+          while (!Declare->use_empty()) {
+            CallInst *CI = cast<CallInst>(*Declare->use_begin());
+            CI->eraseFromParent();
+          }
+          Declare->eraseFromParent();
+        }
+      }
+    }
+  }
+
+//===----------------------------------------------------------------------===//
+//                          BitcodeReaderValueList Class
+//===----------------------------------------------------------------------===//
+
+class BitcodeReaderValueList {
+  std::vector<WeakVH> ValuePtrs;
+
+  /// ResolveConstants - As we resolve forward-referenced constants, we add
+  /// information about them to this vector.  This allows us to resolve them in
+  /// bulk instead of resolving each reference at a time.  See the code in
+  /// ResolveConstantForwardRefs for more information about this.
+  ///
+  /// The key of this vector is the placeholder constant, the value is the slot
+  /// number that holds the resolved value.
+  typedef std::vector<std::pair<Constant*, unsigned> > ResolveConstantsTy;
+  ResolveConstantsTy ResolveConstants;
+  LLVMContext &Context;
+public:
+  explicit BitcodeReaderValueList(LLVMContext &C) : Context(C) {}
+  ~BitcodeReaderValueList() {
+    assert(ResolveConstants.empty() && "Constants not resolved?");
+  }
+
+  // vector compatibility methods
+  unsigned size() const { return ValuePtrs.size(); }
+  void resize(unsigned N) { ValuePtrs.resize(N); }
+  void push_back(Value *V) {
+    ValuePtrs.push_back(V);
+  }
+
+  void clear() {
+    assert(ResolveConstants.empty() && "Constants not resolved?");
+    ValuePtrs.clear();
+  }
+
+  Value *operator[](unsigned i) const {
+    assert(i < ValuePtrs.size());
+    return ValuePtrs[i];
+  }
+
+  Value *back() const { return ValuePtrs.back(); }
+    void pop_back() { ValuePtrs.pop_back(); }
+  bool empty() const { return ValuePtrs.empty(); }
+  void shrinkTo(unsigned N) {
+    assert(N <= size() && "Invalid shrinkTo request!");
+    ValuePtrs.resize(N);
+  }
+
+  Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
+  Value *getValueFwdRef(unsigned Idx, Type *Ty);
+
+  void AssignValue(Value *V, unsigned Idx);
+
+  /// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+  /// resolves any forward references.
+  void ResolveConstantForwardRefs();
+};
+
+
+//===----------------------------------------------------------------------===//
+//                          BitcodeReaderMDValueList Class
+//===----------------------------------------------------------------------===//
+
+class BitcodeReaderMDValueList {
+  unsigned NumFwdRefs;
+  bool AnyFwdRefs;
+  std::vector<TrackingMDRef> MDValuePtrs;
+
+  LLVMContext &Context;
+public:
+  explicit BitcodeReaderMDValueList(LLVMContext &C)
+      : NumFwdRefs(0), AnyFwdRefs(false), Context(C) {}
+
+  // vector compatibility methods
+  unsigned size() const       { return MDValuePtrs.size(); }
+  void resize(unsigned N)     { MDValuePtrs.resize(N); }
+  void push_back(Metadata *MD) { MDValuePtrs.emplace_back(MD); }
+  void clear()                { MDValuePtrs.clear();  }
+  Metadata *back() const      { return MDValuePtrs.back(); }
+  void pop_back()             { MDValuePtrs.pop_back(); }
+  bool empty() const          { return MDValuePtrs.empty(); }
+
+  Metadata *operator[](unsigned i) const {
+    assert(i < MDValuePtrs.size());
+    return MDValuePtrs[i];
+  }
+
+  void shrinkTo(unsigned N) {
+    assert(N <= size() && "Invalid shrinkTo request!");
+    MDValuePtrs.resize(N);
+  }
+
+  Metadata *getValueFwdRef(unsigned Idx);
+  void AssignValue(Metadata *MD, unsigned Idx);
+  void tryToResolveCycles();
+};
+
+class BitcodeReader : public GVMaterializer {
+  LLVMContext &Context;
+  DiagnosticHandlerFunction DiagnosticHandler;
+  Module *TheModule;
+  std::unique_ptr<MemoryBuffer> Buffer;
+  std::unique_ptr<BitstreamReader> StreamFile;
+  BitstreamCursor Stream;
+  std::unique_ptr<DataStreamer> LazyStreamer;
+  uint64_t NextUnreadBit;
+  bool SeenValueSymbolTable;
+
+  std::vector<Type*> TypeList;
+  BitcodeReaderValueList ValueList;
+  BitcodeReaderMDValueList MDValueList;
+  SmallVector<Instruction *, 64> InstructionList;
+
+  std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
+  std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
+
+  /// MAttributes - The set of attributes by index.  Index zero in the
+  /// file is for null, and is thus not represented here.  As such all indices
+  /// are off by one.
+  std::vector<AttributeSet> MAttributes;
+
+  /// \brief The set of attribute groups.
+  std::map<unsigned, AttributeSet> MAttributeGroups;
+
+  /// FunctionBBs - While parsing a function body, this is a list of the basic
+  /// blocks for the function.
+  std::vector<BasicBlock*> FunctionBBs;
+
+  // When reading the module header, this list is populated with functions that
+  // have bodies later in the file.
+  std::vector<Function*> FunctionsWithBodies;
+
+  // When intrinsic functions are encountered which require upgrading they are
+  // stored here with their replacement function.
+  typedef std::vector<std::pair<Function*, Function*> > UpgradedIntrinsicMap;
+  UpgradedIntrinsicMap UpgradedIntrinsics;
+
+  // Map the bitcode's custom MDKind ID to the Module's MDKind ID.
+  DenseMap<unsigned, unsigned> MDKindMap;
+
+  // Several operations happen after the module header has been read, but
+  // before function bodies are processed. This keeps track of whether
+  // we've done this yet.
+  bool SeenFirstFunctionBody;
+
+  /// DeferredFunctionInfo - When function bodies are initially scanned, this
+  /// map contains info about where to find deferred function body in the
+  /// stream.
+  DenseMap<Function*, uint64_t> DeferredFunctionInfo;
+
+  /// BlockAddrFwdRefs - These are blockaddr references to basic blocks.  These
+  /// are resolved lazily when functions are loaded.
+  typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy;
+  DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs;
+
+  /// LLVM2_7MetadataDetected - True if metadata produced by LLVM 2.7 or
+  /// earlier was detected, in which case we behave slightly differently,
+  /// for compatibility.
+  /// FIXME: Remove in LLVM 3.0.
+  bool LLVM2_7MetadataDetected;
+  static const std::error_category &BitcodeErrorCategory();
+
+public:
+  std::error_code Error(BitcodeError E, const Twine &Message);
+  std::error_code Error(BitcodeError E);
+  std::error_code Error(const Twine &Message);
+
+  explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C,
+                         DiagnosticHandlerFunction DiagnosticHandler);
+  ~BitcodeReader() { FreeState(); }
+
+  void FreeState();
+
+  void releaseBuffer();
+
+  bool isDematerializable(const GlobalValue *GV) const;
+  std::error_code materialize(GlobalValue *GV) override;
+  std::error_code materializeModule() override;
+  std::vector<StructType *> getIdentifiedStructTypes() const override;
+  void dematerialize(GlobalValue *GV);
+
+  /// @brief Main interface to parsing a bitcode buffer.
+  /// @returns true if an error occurred.
+  std::error_code ParseBitcodeInto(Module *M);
+
+  /// @brief Cheap mechanism to just extract module triple
+  /// @returns true if an error occurred.
+  llvm::ErrorOr<std::string> parseTriple();
+
+  static uint64_t decodeSignRotatedValue(uint64_t V);
+
+  /// Materialize any deferred Metadata block.
+  std::error_code materializeMetadata() override;
+
+  void setStripDebugInfo() override;
+
+private:
+  std::vector<StructType *> IdentifiedStructTypes;
+  StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name);
+  StructType *createIdentifiedStructType(LLVMContext &Context);
+
+  Type *getTypeByID(unsigned ID);
+  Type *getTypeByIDOrNull(unsigned ID);
+  Value *getFnValueByID(unsigned ID, Type *Ty) {
+    if (Ty && Ty->isMetadataTy())
+      return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID));
+    return ValueList.getValueFwdRef(ID, Ty);
+  }
+  Metadata *getFnMetadataByID(unsigned ID) {
+    return MDValueList.getValueFwdRef(ID);
+  }
+  BasicBlock *getBasicBlock(unsigned ID) const {
+    if (ID >= FunctionBBs.size()) return nullptr; // Invalid ID
+    return FunctionBBs[ID];
+  }
+  AttributeSet getAttributes(unsigned i) const {
+    if (i-1 < MAttributes.size())
+      return MAttributes[i-1];
+    return AttributeSet();
+  }
+
+  /// getValueTypePair - Read a value/type pair out of the specified record from
+  /// slot 'Slot'.  Increment Slot past the number of slots used in the record.
+  /// Return true on failure.
+  bool getValueTypePair(SmallVectorImpl<uint64_t> &Record, unsigned &Slot,
+                        unsigned InstNum, Value *&ResVal) {
+    if (Slot == Record.size()) return true;
+    unsigned ValNo = (unsigned)Record[Slot++];
+    if (ValNo < InstNum) {
+      // If this is not a forward reference, just return the value we already
+      // have.
+      ResVal = getFnValueByID(ValNo, nullptr);
+      return ResVal == nullptr;
+    } else if (Slot == Record.size()) {
+      return true;
+    }
+
+    unsigned TypeNo = (unsigned)Record[Slot++];
+    ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo));
+    return ResVal == nullptr;
+  }
+  bool getValue(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
+                Type *Ty, Value *&ResVal) {
+    if (Slot == Record.size()) return true;
+    unsigned ValNo = (unsigned)Record[Slot++];
+    ResVal = getFnValueByID(ValNo, Ty);
+    return ResVal == 0;
+  }
+
+
+  std::error_code ParseModule(bool Resume);
+  std::error_code ParseAttributeBlock();
+  std::error_code ParseTypeTable();
+  std::error_code ParseOldTypeTable();         // FIXME: Remove in LLVM 3.1
+  std::error_code ParseTypeTableBody();
+
+  std::error_code ParseOldTypeSymbolTable();   // FIXME: Remove in LLVM 3.1
+  std::error_code ParseValueSymbolTable();
+  std::error_code ParseConstants();
+  std::error_code RememberAndSkipFunctionBody();
+  std::error_code ParseFunctionBody(Function *F);
+  std::error_code GlobalCleanup();
+  std::error_code ResolveGlobalAndAliasInits();
+  std::error_code ParseMetadata();
+  std::error_code ParseMetadataAttachment();
+  llvm::ErrorOr<std::string> parseModuleTriple();
+  std::error_code InitStream();
+  std::error_code InitStreamFromBuffer();
+  std::error_code InitLazyStream();
+};
+} // end anonymous namespace
+
+static std::error_code Error(const DiagnosticHandlerFunction &DiagnosticHandler,
+                             std::error_code EC, const Twine &Message) {
+  BitcodeDiagnosticInfo DI(EC, DS_Error, Message);
+  DiagnosticHandler(DI);
+  return EC;
+}
+
+static std::error_code Error(const DiagnosticHandlerFunction &DiagnosticHandler,
+                             std::error_code EC) {
+  return Error(DiagnosticHandler, EC, EC.message());
+}
+
+std::error_code BitcodeReader::Error(BitcodeError E, const Twine &Message) {
+  return ::Error(DiagnosticHandler, make_error_code(E), Message);
+}
+
+std::error_code BitcodeReader::Error(const Twine &Message) {
+  return ::Error(DiagnosticHandler,
+                 make_error_code(BitcodeError::CorruptedBitcode), Message);
+}
+
+std::error_code BitcodeReader::Error(BitcodeError E) {
+  return ::Error(DiagnosticHandler, make_error_code(E));
+}
+
+static DiagnosticHandlerFunction getDiagHandler(DiagnosticHandlerFunction F,
+                                                LLVMContext &C) {
+  if (F)
+    return F;
+  return [&C](const DiagnosticInfo &DI) { C.diagnose(DI); };
+}
+
+BitcodeReader::BitcodeReader(MemoryBuffer *buffer, LLVMContext &C,
+                             DiagnosticHandlerFunction DiagnosticHandler)
+    : Context(C), DiagnosticHandler(getDiagHandler(DiagnosticHandler, C)),
+      TheModule(nullptr), Buffer(buffer), LazyStreamer(nullptr),
+      NextUnreadBit(0), SeenValueSymbolTable(false), ValueList(C),
+      MDValueList(C), SeenFirstFunctionBody(false),
+      LLVM2_7MetadataDetected(false) {}
+
+
+void BitcodeReader::FreeState() {
+  Buffer = nullptr;
+  std::vector<Type*>().swap(TypeList);
+  ValueList.clear();
+  MDValueList.clear();
+
+  std::vector<AttributeSet>().swap(MAttributes);
+  std::vector<BasicBlock*>().swap(FunctionBBs);
+  std::vector<Function*>().swap(FunctionsWithBodies);
+  DeferredFunctionInfo.clear();
+  MDKindMap.clear();
+}
+
+//===----------------------------------------------------------------------===//
+//  Helper functions to implement forward reference resolution, etc.
+//===----------------------------------------------------------------------===//
+
+/// ConvertToString - Convert a string from a record into an std::string, return
+/// true on failure.
+template<typename StrTy>
+static bool ConvertToString(ArrayRef<uint64_t> Record, unsigned Idx,
+                            StrTy &Result) {
+  if (Idx > Record.size())
+    return true;
+
+  for (unsigned i = Idx, e = Record.size(); i != e; ++i)
+    Result += (char)Record[i];
+  return false;
+}
+
+static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) {
+  switch (Val) {
+  default: // Map unknown/new linkages to external
+  case 0:
+    return GlobalValue::ExternalLinkage;
+  case 1:
+    return GlobalValue::WeakAnyLinkage;
+  case 2:
+    return GlobalValue::AppendingLinkage;
+  case 3:
+    return GlobalValue::InternalLinkage;
+  case 4:
+    return GlobalValue::LinkOnceAnyLinkage;
+  case 5:
+    return GlobalValue::ExternalLinkage; // Obsolete DLLImportLinkage
+  case 6:
+    return GlobalValue::ExternalLinkage; // Obsolete DLLExportLinkage
+  case 7:
+    return GlobalValue::ExternalWeakLinkage;
+  case 8:
+    return GlobalValue::CommonLinkage;
+  case 9:
+    return GlobalValue::PrivateLinkage;
+  case 10:
+    return GlobalValue::WeakODRLinkage;
+  case 11:
+    return GlobalValue::LinkOnceODRLinkage;
+  case 12:
+    return GlobalValue::AvailableExternallyLinkage;
+  case 13:
+    return GlobalValue::PrivateLinkage; // Obsolete LinkerPrivateLinkage
+  case 14:
+    return GlobalValue::ExternalWeakLinkage; // Obsolete LinkerPrivateWeakLinkage
+  //ANDROID: convert LinkOnceODRAutoHideLinkage -> LinkOnceODRLinkage
+  case 15:
+    return GlobalValue::LinkOnceODRLinkage;
+  }
+}
+
+static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) {
+  switch (Val) {
+  default: // Map unknown visibilities to default.
+  case 0: return GlobalValue::DefaultVisibility;
+  case 1: return GlobalValue::HiddenVisibility;
+  case 2: return GlobalValue::ProtectedVisibility;
+  }
+}
+
+static GlobalVariable::ThreadLocalMode GetDecodedThreadLocalMode(unsigned Val) {
+  switch (Val) {
+    case 0: return GlobalVariable::NotThreadLocal;
+    default: // Map unknown non-zero value to general dynamic.
+    case 1: return GlobalVariable::GeneralDynamicTLSModel;
+    case 2: return GlobalVariable::LocalDynamicTLSModel;
+    case 3: return GlobalVariable::InitialExecTLSModel;
+    case 4: return GlobalVariable::LocalExecTLSModel;
+  }
+}
+
+static int GetDecodedCastOpcode(unsigned Val) {
+  switch (Val) {
+  default: return -1;
+  case bitc::CAST_TRUNC   : return Instruction::Trunc;
+  case bitc::CAST_ZEXT    : return Instruction::ZExt;
+  case bitc::CAST_SEXT    : return Instruction::SExt;
+  case bitc::CAST_FPTOUI  : return Instruction::FPToUI;
+  case bitc::CAST_FPTOSI  : return Instruction::FPToSI;
+  case bitc::CAST_UITOFP  : return Instruction::UIToFP;
+  case bitc::CAST_SITOFP  : return Instruction::SIToFP;
+  case bitc::CAST_FPTRUNC : return Instruction::FPTrunc;
+  case bitc::CAST_FPEXT   : return Instruction::FPExt;
+  case bitc::CAST_PTRTOINT: return Instruction::PtrToInt;
+  case bitc::CAST_INTTOPTR: return Instruction::IntToPtr;
+  case bitc::CAST_BITCAST : return Instruction::BitCast;
+  }
+}
+static int GetDecodedBinaryOpcode(unsigned Val, Type *Ty) {
+  switch (Val) {
+  default: return -1;
+  case bitc::BINOP_ADD:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FAdd : Instruction::Add;
+  case bitc::BINOP_SUB:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FSub : Instruction::Sub;
+  case bitc::BINOP_MUL:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FMul : Instruction::Mul;
+  case bitc::BINOP_UDIV: return Instruction::UDiv;
+  case bitc::BINOP_SDIV:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FDiv : Instruction::SDiv;
+  case bitc::BINOP_UREM: return Instruction::URem;
+  case bitc::BINOP_SREM:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FRem : Instruction::SRem;
+  case bitc::BINOP_SHL:  return Instruction::Shl;
+  case bitc::BINOP_LSHR: return Instruction::LShr;
+  case bitc::BINOP_ASHR: return Instruction::AShr;
+  case bitc::BINOP_AND:  return Instruction::And;
+  case bitc::BINOP_OR:   return Instruction::Or;
+  case bitc::BINOP_XOR:  return Instruction::Xor;
+  }
+}
+
+namespace llvm {
+namespace {
+  /// @brief A class for maintaining the slot number definition
+  /// as a placeholder for the actual definition for forward constants defs.
+  class ConstantPlaceHolder : public ConstantExpr {
+    void operator=(const ConstantPlaceHolder &) = delete;
+  public:
+    // allocate space for exactly one operand
+    void *operator new(size_t s) {
+      return User::operator new(s, 1);
+    }
+    explicit ConstantPlaceHolder(Type *Ty, LLVMContext& Context)
+      : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
+      Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
+    }
+
+    /// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
+    static bool classof(const Value *V) {
+      return isa<ConstantExpr>(V) &&
+             cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
+    }
+
+
+    /// Provide fast operand accessors
+    DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+  };
+}
+
+// FIXME: can we inherit this from ConstantExpr?
+template <>
+struct OperandTraits<ConstantPlaceHolder> :
+  public FixedNumOperandTraits<ConstantPlaceHolder, 1> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
+}
+
+
+void BitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) {
+  if (Idx == size()) {
+    push_back(V);
+    return;
+  }
+
+  if (Idx >= size())
+    resize(Idx+1);
+
+  WeakVH &OldV = ValuePtrs[Idx];
+  if (!OldV) {
+    OldV = V;
+    return;
+  }
+
+  // Handle constants and non-constants (e.g. instrs) differently for
+  // efficiency.
+  if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
+    ResolveConstants.push_back(std::make_pair(PHC, Idx));
+    OldV = V;
+  } else {
+    // If there was a forward reference to this value, replace it.
+    Value *PrevVal = OldV;
+    OldV->replaceAllUsesWith(V);
+    delete PrevVal;
+  }
+}
+
+
+Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
+                                                    Type *Ty) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Value *V = ValuePtrs[Idx]) {
+    assert(Ty == V->getType() && "Type mismatch in constant table!");
+    return cast<Constant>(V);
+  }
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  Constant *C = new ConstantPlaceHolder(Ty, Context);
+  ValuePtrs[Idx] = C;
+  return C;
+}
+
+Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Value *V = ValuePtrs[Idx]) {
+    assert((!Ty || Ty == V->getType()) && "Type mismatch in value table!");
+    return V;
+  }
+
+  // No type specified, must be invalid reference.
+  if (!Ty) return nullptr;
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  Value *V = new Argument(Ty);
+  ValuePtrs[Idx] = V;
+  return V;
+}
+
+/// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+/// resolves any forward references.  The idea behind this is that we sometimes
+/// get constants (such as large arrays) which reference *many* forward ref
+/// constants.  Replacing each of these causes a lot of thrashing when
+/// building/reuniquing the constant.  Instead of doing this, we look at all the
+/// uses and rewrite all the place holders at once for any constant that uses
+/// a placeholder.
+void BitcodeReaderValueList::ResolveConstantForwardRefs() {
+  // Sort the values by-pointer so that they are efficient to look up with a
+  // binary search.
+  std::sort(ResolveConstants.begin(), ResolveConstants.end());
+
+  SmallVector<Constant*, 64> NewOps;
+
+  while (!ResolveConstants.empty()) {
+    Value *RealVal = operator[](ResolveConstants.back().second);
+    Constant *Placeholder = ResolveConstants.back().first;
+    ResolveConstants.pop_back();
+
+    // Loop over all users of the placeholder, updating them to reference the
+    // new value.  If they reference more than one placeholder, update them all
+    // at once.
+    while (!Placeholder->use_empty()) {
+      auto UI = Placeholder->user_begin();
+      User *U = *UI;
+
+      // If the using object isn't uniqued, just update the operands.  This
+      // handles instructions and initializers for global variables.
+      if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
+        UI.getUse().set(RealVal);
+        continue;
+      }
+
+      // Otherwise, we have a constant that uses the placeholder.  Replace that
+      // constant with a new constant that has *all* placeholder uses updated.
+      Constant *UserC = cast<Constant>(U);
+      for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end();
+           I != E; ++I) {
+        Value *NewOp;
+        if (!isa<ConstantPlaceHolder>(*I)) {
+          // Not a placeholder reference.
+          NewOp = *I;
+        } else if (*I == Placeholder) {
+          // Common case is that it just references this one placeholder.
+          NewOp = RealVal;
+        } else {
+          // Otherwise, look up the placeholder in ResolveConstants.
+          ResolveConstantsTy::iterator It =
+            std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(),
+                             std::pair<Constant*, unsigned>(cast<Constant>(*I),
+                                                            0));
+          assert(It != ResolveConstants.end() && It->first == *I);
+          NewOp = operator[](It->second);
+        }
+
+        NewOps.push_back(cast<Constant>(NewOp));
+      }
+
+      // Make the new constant.
+      Constant *NewC;
+      if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
+        NewC = ConstantArray::get(UserCA->getType(), NewOps);
+      } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
+        NewC = ConstantStruct::get(UserCS->getType(), NewOps);
+      } else if (isa<ConstantVector>(UserC)) {
+        NewC = ConstantVector::get(NewOps);
+      } else {
+        assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
+        NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
+      }
+
+      UserC->replaceAllUsesWith(NewC);
+      UserC->destroyConstant();
+      NewOps.clear();
+    }
+
+    // Update all ValueHandles, they should be the only users at this point.
+    Placeholder->replaceAllUsesWith(RealVal);
+    delete Placeholder;
+  }
+}
+
+void BitcodeReaderMDValueList::AssignValue(Metadata *MD, unsigned Idx) {
+  if (Idx == size()) {
+    push_back(MD);
+    return;
+  }
+
+  if (Idx >= size())
+    resize(Idx+1);
+
+  TrackingMDRef &OldMD = MDValuePtrs[Idx];
+  if (!OldMD) {
+    OldMD.reset(MD);
+    return;
+  }
+
+  // If there was a forward reference to this value, replace it.
+  TempMDTuple PrevMD(cast<MDTuple>(OldMD.get()));
+  PrevMD->replaceAllUsesWith(MD);
+  --NumFwdRefs;
+}
+
+Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Metadata *MD = MDValuePtrs[Idx])
+    return MD;
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  AnyFwdRefs = true;
+  ++NumFwdRefs;
+  Metadata *MD = MDNode::getTemporary(Context, None).release();
+  MDValuePtrs[Idx].reset(MD);
+  return MD;
+}
+
+void BitcodeReaderMDValueList::tryToResolveCycles() {
+  if (!AnyFwdRefs)
+    // Nothing to do.
+    return;
+
+  if (NumFwdRefs)
+    // Still forward references... can't resolve cycles.
+    return;
+
+  // Resolve any cycles.
+  for (auto &MD : MDValuePtrs) {
+    auto *N = dyn_cast_or_null<MDNode>(MD);
+    if (!N)
+      continue;
+
+    assert(!N->isTemporary() && "Unexpected forward reference");
+    N->resolveCycles();
+  }
+}
+
+Type *BitcodeReader::getTypeByID(unsigned ID) {
+  // The type table size is always specified correctly.
+  if (ID >= TypeList.size())
+    return nullptr;
+
+  if (Type *Ty = TypeList[ID])
+    return Ty;
+
+  // If we have a forward reference, the only possible case is when it is to a
+  // named struct.  Just create a placeholder for now.
+  return TypeList[ID] = createIdentifiedStructType(Context);
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context,
+                                                      StringRef Name) {
+  auto *Ret = StructType::create(Context, Name);
+  IdentifiedStructTypes.push_back(Ret);
+  return Ret;
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context) {
+  auto *Ret = StructType::create(Context);
+  IdentifiedStructTypes.push_back(Ret);
+  return Ret;
+}
+
+
+/// FIXME: Remove in LLVM 3.1, only used by ParseOldTypeTable.
+Type *BitcodeReader::getTypeByIDOrNull(unsigned ID) {
+  if (ID >= TypeList.size())
+    TypeList.resize(ID+1);
+
+  return TypeList[ID];
+}
+
+//===----------------------------------------------------------------------===//
+//  Functions for parsing blocks from the bitcode file
+//===----------------------------------------------------------------------===//
+
+
+/// \brief This fills an AttrBuilder object with the LLVM attributes that have
+/// been decoded from the given integer. This function must stay in sync with
+/// 'encodeLLVMAttributesForBitcode'.
+static void decodeLLVMAttributesForBitcode(AttrBuilder &B,
+                                           uint64_t EncodedAttrs) {
+  // FIXME: Remove in 4.0.
+
+  // The alignment is stored as a 16-bit raw value from bits 31--16.  We shift
+  // the bits above 31 down by 11 bits.
+  unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
+  assert((!Alignment || isPowerOf2_32(Alignment)) &&
+         "Alignment must be a power of two.");
+
+  if (Alignment)
+    B.addAlignmentAttr(Alignment);
+  B.addRawValue(((EncodedAttrs & (0xfffffULL << 32)) >> 11) |
+                (EncodedAttrs & 0xffff));
+}
+
+std::error_code BitcodeReader::ParseAttributeBlock() {
+  if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
+    return Error("Invalid record");
+
+  if (!MAttributes.empty())
+    return Error("Invalid multiple blocks");
+
+  SmallVector<uint64_t, 64> Record;
+
+  SmallVector<AttributeSet, 8> Attrs;
+
+  // Read all the records.
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::PARAMATTR_CODE_ENTRY_OLD: { // ENTRY: [paramidx0, attr0, ...]
+      if (Record.size() & 1)
+        return Error("Invalid record");
+
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        AttrBuilder B;
+        decodeLLVMAttributesForBitcode(B, Record[i+1]);
+        Attrs.push_back(AttributeSet::get(Context, Record[i], B));
+      }
+
+      MAttributes.push_back(AttributeSet::get(Context, Attrs));
+      Attrs.clear();
+      break;
+    }
+    case bitc::PARAMATTR_CODE_ENTRY: { // ENTRY: [attrgrp0, attrgrp1, ...]
+      for (unsigned i = 0, e = Record.size(); i != e; ++i)
+        Attrs.push_back(MAttributeGroups[Record[i]]);
+
+      MAttributes.push_back(AttributeSet::get(Context, Attrs));
+      Attrs.clear();
+      break;
+    }
+    }
+  }
+}
+
+
+std::error_code BitcodeReader::ParseTypeTable() {
+  if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
+    return Error("Invalid record");
+
+  return ParseTypeTableBody();
+}
+
+std::error_code BitcodeReader::ParseTypeTableBody() {
+  if (!TypeList.empty())
+    return Error("Invalid multiple blocks");
+
+  SmallVector<uint64_t, 64> Record;
+  unsigned NumRecords = 0;
+
+  SmallString<64> TypeName;
+
+  // Read all the records for this type table.
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      if (NumRecords != TypeList.size())
+        return Error("Malformed block");
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    Record.clear();
+    Type *ResultTy = nullptr;
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default:
+      return Error("Invalid value");
+    case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+      // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+      // type list.  This allows us to reserve space.
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      TypeList.resize(Record[0]);
+      continue;
+    case bitc::TYPE_CODE_VOID:      // VOID
+      ResultTy = Type::getVoidTy(Context);
+      break;
+    case bitc::TYPE_CODE_HALF:     // HALF
+      ResultTy = Type::getHalfTy(Context);
+      break;
+    case bitc::TYPE_CODE_FLOAT:     // FLOAT
+      ResultTy = Type::getFloatTy(Context);
+      break;
+    case bitc::TYPE_CODE_DOUBLE:    // DOUBLE
+      ResultTy = Type::getDoubleTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_FP80:  // X86_FP80
+      ResultTy = Type::getX86_FP80Ty(Context);
+      break;
+    case bitc::TYPE_CODE_FP128:     // FP128
+      ResultTy = Type::getFP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+      ResultTy = Type::getPPC_FP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_LABEL:     // LABEL
+      ResultTy = Type::getLabelTy(Context);
+      break;
+    case bitc::TYPE_CODE_METADATA:  // METADATA
+      ResultTy = Type::getMetadataTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_MMX:   // X86_MMX
+      ResultTy = Type::getX86_MMXTy(Context);
+      break;
+    case bitc::TYPE_CODE_INTEGER:   // INTEGER: [width]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+
+      ResultTy = IntegerType::get(Context, Record[0]);
+      break;
+    case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+                                    //          [pointee type, address space]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      unsigned AddressSpace = 0;
+      if (Record.size() == 2)
+        AddressSpace = Record[1];
+      ResultTy = getTypeByID(Record[0]);
+      if (!ResultTy)
+        return Error("Invalid type");
+      ResultTy = PointerType::get(ResultTy, AddressSpace);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
+      // FIXME: attrid is dead, remove it in LLVM 4.0
+      // FUNCTION: [vararg, attrid, retty, paramty x N]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      SmallVector<Type*, 8> ArgTys;
+      for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          ArgTys.push_back(T);
+        else
+          break;
+      }
+
+      ResultTy = getTypeByID(Record[2]);
+      if (!ResultTy || ArgTys.size() < Record.size()-3)
+        return Error("Invalid type");
+
+      ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_STRUCT_ANON: {  // STRUCT: [ispacked, eltty x N]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      SmallVector<Type*, 8> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          EltTys.push_back(T);
+        else
+          break;
+      }
+      if (EltTys.size() != Record.size()-1)
+        return Error("Invalid type");
+      ResultTy = StructType::get(Context, EltTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_STRUCT_NAME:   // STRUCT_NAME: [strchr x N]
+      if (ConvertToString(Record, 0, TypeName))
+        return Error("Invalid record");
+      continue;
+
+    case bitc::TYPE_CODE_STRUCT_NAMED: { // STRUCT: [ispacked, eltty x N]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+
+      if (NumRecords >= TypeList.size())
+        return Error("Invalid TYPE table");
+
+      // Check to see if this was forward referenced, if so fill in the temp.
+      StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+      if (Res) {
+        Res->setName(TypeName);
+        TypeList[NumRecords] = nullptr;
+      } else  // Otherwise, create a new struct.
+        Res = createIdentifiedStructType(Context, TypeName);
+      TypeName.clear();
+
+      SmallVector<Type*, 8> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          EltTys.push_back(T);
+        else
+          break;
+      }
+      if (EltTys.size() != Record.size()-1)
+        return Error("Invalid record");
+      Res->setBody(EltTys, Record[0]);
+      ResultTy = Res;
+      break;
+    }
+    case bitc::TYPE_CODE_OPAQUE: {       // OPAQUE: []
+      if (Record.size() != 1)
+        return Error("Invalid record");
+
+      if (NumRecords >= TypeList.size())
+        return Error("Invalid TYPE table");
+
+      // Check to see if this was forward referenced, if so fill in the temp.
+      StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+      if (Res) {
+        Res->setName(TypeName);
+        TypeList[NumRecords] = nullptr;
+      } else  // Otherwise, create a new struct with no body.
+        Res = createIdentifiedStructType(Context, TypeName);
+      TypeName.clear();
+      ResultTy = Res;
+      break;
+    }
+    case bitc::TYPE_CODE_ARRAY:     // ARRAY: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      if ((ResultTy = getTypeByID(Record[1])))
+        ResultTy = ArrayType::get(ResultTy, Record[0]);
+      else
+        return Error("Invalid type");
+      break;
+    case bitc::TYPE_CODE_VECTOR:    // VECTOR: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      if ((ResultTy = getTypeByID(Record[1])))
+        ResultTy = VectorType::get(ResultTy, Record[0]);
+      else
+        return Error("Invalid type");
+      break;
+    }
+
+    if (NumRecords >= TypeList.size())
+      return Error("Invalid TYPE table");
+    assert(ResultTy && "Didn't read a type?");
+    assert(!TypeList[NumRecords] && "Already read type?");
+    TypeList[NumRecords++] = ResultTy;
+  }
+}
+
+// FIXME: Remove in LLVM 3.1
+std::error_code BitcodeReader::ParseOldTypeTable() {
+  if (Stream.EnterSubBlock(TYPE_BLOCK_ID_OLD_3_0))
+    return Error("Malformed block");
+
+  if (!TypeList.empty())
+    return Error("Invalid TYPE table");
+
+
+  // While horrible, we have no good ordering of types in the bc file.  Just
+  // iteratively parse types out of the bc file in multiple passes until we get
+  // them all.  Do this by saving a cursor for the start of the type block.
+  BitstreamCursor StartOfTypeBlockCursor(Stream);
+
+  unsigned NumTypesRead = 0;
+
+  SmallVector<uint64_t, 64> Record;
+RestartScan:
+  unsigned NextTypeID = 0;
+  bool ReadAnyTypes = false;
+
+  // Read all the records for this type table.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (NextTypeID != TypeList.size())
+        return Error("Invalid TYPE table");
+
+      // If we haven't read all of the types yet, iterate again.
+      if (NumTypesRead != TypeList.size()) {
+        // If we didn't successfully read any types in this pass, then we must
+        // have an unhandled forward reference.
+        if (!ReadAnyTypes)
+          return Error("Invalid TYPE table");
+
+        Stream = StartOfTypeBlockCursor;
+        goto RestartScan;
+      }
+
+      if (Stream.ReadBlockEnd())
+        return Error("Invalid TYPE table");
+      return std::error_code();
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Type *ResultTy = nullptr;
+    switch (Stream.readRecord(Code, Record)) {
+    default: return Error("Invalid TYPE table");
+    case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+      // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+      // type list.  This allows us to reserve space.
+      if (Record.size() < 1)
+        return Error("Invalid TYPE table");
+      TypeList.resize(Record[0]);
+      continue;
+    case bitc::TYPE_CODE_VOID:      // VOID
+      ResultTy = Type::getVoidTy(Context);
+      break;
+    case bitc::TYPE_CODE_FLOAT:     // FLOAT
+      ResultTy = Type::getFloatTy(Context);
+      break;
+    case bitc::TYPE_CODE_DOUBLE:    // DOUBLE
+      ResultTy = Type::getDoubleTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_FP80:  // X86_FP80
+      ResultTy = Type::getX86_FP80Ty(Context);
+      break;
+    case bitc::TYPE_CODE_FP128:     // FP128
+      ResultTy = Type::getFP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+      ResultTy = Type::getPPC_FP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_LABEL:     // LABEL
+      ResultTy = Type::getLabelTy(Context);
+      break;
+    case bitc::TYPE_CODE_METADATA:  // METADATA
+      ResultTy = Type::getMetadataTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_MMX:   // X86_MMX
+      ResultTy = Type::getX86_MMXTy(Context);
+      break;
+    case bitc::TYPE_CODE_INTEGER:   // INTEGER: [width]
+      if (Record.size() < 1)
+        return Error("Invalid TYPE table");
+      ResultTy = IntegerType::get(Context, Record[0]);
+      break;
+    case bitc::TYPE_CODE_OPAQUE:    // OPAQUE
+      if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0)
+        ResultTy = StructType::create(Context, "");
+      break;
+    case TYPE_CODE_STRUCT_OLD_3_0: {// STRUCT_OLD
+      if (NextTypeID >= TypeList.size()) break;
+      // If we already read it, don't reprocess.
+      if (TypeList[NextTypeID] &&
+          !cast<StructType>(TypeList[NextTypeID])->isOpaque())
+        break;
+
+      // Set a type.
+      if (TypeList[NextTypeID] == 0)
+        TypeList[NextTypeID] = StructType::create(Context, "");
+
+      std::vector<Type*> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          EltTys.push_back(Elt);
+        else
+          break;
+      }
+
+      if (EltTys.size() != Record.size()-1)
+        break;      // Not all elements are ready.
+
+      cast<StructType>(TypeList[NextTypeID])->setBody(EltTys, Record[0]);
+      ResultTy = TypeList[NextTypeID];
+      TypeList[NextTypeID] = 0;
+      break;
+    }
+    case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+      //          [pointee type, address space]
+      if (Record.size() < 1)
+        return Error("Invalid TYPE table");
+      unsigned AddressSpace = 0;
+      if (Record.size() == 2)
+        AddressSpace = Record[1];
+      if ((ResultTy = getTypeByIDOrNull(Record[0])))
+        ResultTy = PointerType::get(ResultTy, AddressSpace);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
+      // FIXME: attrid is dead, remove it in LLVM 3.0
+      // FUNCTION: [vararg, attrid, retty, paramty x N]
+      if (Record.size() < 3)
+        return Error("Invalid TYPE table");
+      std::vector<Type*> ArgTys;
+      for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          ArgTys.push_back(Elt);
+        else
+          break;
+      }
+      if (ArgTys.size()+3 != Record.size())
+        break;  // Something was null.
+      if ((ResultTy = getTypeByIDOrNull(Record[2])))
+        ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_ARRAY:     // ARRAY: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid TYPE table");
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = ArrayType::get(ResultTy, Record[0]);
+      break;
+    case bitc::TYPE_CODE_VECTOR:    // VECTOR: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid TYPE table");
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = VectorType::get(ResultTy, Record[0]);
+      break;
+    }
+
+    if (NextTypeID >= TypeList.size())
+      return Error("Invalid TYPE table");
+
+    if (ResultTy && TypeList[NextTypeID] == 0) {
+      ++NumTypesRead;
+      ReadAnyTypes = true;
+
+      TypeList[NextTypeID] = ResultTy;
+    }
+
+    ++NextTypeID;
+  }
+}
+
+
+std::error_code BitcodeReader::ParseOldTypeSymbolTable() {
+  if (Stream.EnterSubBlock(TYPE_SYMTAB_BLOCK_ID_OLD_3_0))
+    return Error("Malformed block");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this type table.
+  std::string TypeName;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      return std::error_code();
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.readRecord(Code, Record)) {
+    default:  // Default behavior: unknown type.
+      break;
+    case bitc::TST_CODE_ENTRY:    // TST_ENTRY: [typeid, namechar x N]
+      if (ConvertToString(Record, 1, TypeName))
+        return Error("Invalid record");
+      unsigned TypeID = Record[0];
+      if (TypeID >= TypeList.size())
+        return Error("Invalid record");
+
+      // Only apply the type name to a struct type with no name.
+      if (StructType *STy = dyn_cast<StructType>(TypeList[TypeID]))
+        if (!STy->isLiteral() && !STy->hasName())
+          STy->setName(TypeName);
+      TypeName.clear();
+      break;
+    }
+  }
+}
+
+std::error_code BitcodeReader::ParseValueSymbolTable() {
+  if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this value table.
+  SmallString<128> ValueName;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      return std::error_code();
+    }
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.readRecord(Code, Record)) {
+    default:  // Default behavior: unknown type.
+      break;
+    case bitc::VST_CODE_ENTRY: {  // VST_ENTRY: [valueid, namechar x N]
+      if (ConvertToString(Record, 1, ValueName))
+        return Error("Invalid record");
+      unsigned ValueID = Record[0];
+      if (ValueID >= ValueList.size())
+        return Error("Invalid record");
+      Value *V = ValueList[ValueID];
+
+      V->setName(StringRef(ValueName.data(), ValueName.size()));
+      ValueName.clear();
+      break;
+    }
+    case bitc::VST_CODE_BBENTRY: {
+      if (ConvertToString(Record, 1, ValueName))
+        return Error("Invalid record");
+      BasicBlock *BB = getBasicBlock(Record[0]);
+      if (!BB)
+        return Error("Invalid record");
+
+      BB->setName(StringRef(ValueName.data(), ValueName.size()));
+      ValueName.clear();
+      break;
+    }
+    }
+  }
+}
+
+std::error_code BitcodeReader::ParseMetadata() {
+  unsigned NextMDValueNo = MDValueList.size();
+
+  if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      return std::error_code();
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    bool IsFunctionLocal = false;
+    // Read a record.
+    Record.clear();
+    Code = Stream.readRecord(Code, Record);
+    switch (Code) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::METADATA_NAME: {
+      // Read named of the named metadata.
+      unsigned NameLength = Record.size();
+      SmallString<8> Name;
+      Name.resize(NameLength);
+      for (unsigned i = 0; i != NameLength; ++i)
+        Name[i] = Record[i];
+      Record.clear();
+      Code = Stream.ReadCode();
+
+      // METADATA_NAME is always followed by METADATA_NAMED_NODE.
+      unsigned NextBitCode = Stream.readRecord(Code, Record);
+      if (NextBitCode == METADATA_NAMED_NODE_2_7) {
+        LLVM2_7MetadataDetected = true;
+      } else if (NextBitCode != bitc::METADATA_NAMED_NODE) {
+        assert(!"Invalid Named Metadata record.");  (void)NextBitCode;
+      }
+
+      // Read named metadata elements.
+      unsigned Size = Record.size();
+      NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata(Name);
+      for (unsigned i = 0; i != Size; ++i) {
+        MDNode *MD = dyn_cast_or_null<MDNode>(MDValueList.getValueFwdRef(Record[i]));
+        if (!MD)
+          return Error("Invalid record");
+        NMD->addOperand(MD);
+      }
+
+      if (LLVM2_7MetadataDetected) {
+        MDValueList.AssignValue(0, NextMDValueNo++);
+      }
+      break;
+    }
+    case METADATA_FN_NODE_2_7:
+    case bitc::METADATA_OLD_FN_NODE:
+      IsFunctionLocal = true;
+      // fall-through
+    case METADATA_NODE_2_7:
+    case bitc::METADATA_OLD_NODE: {
+      if (Code == METADATA_FN_NODE_2_7 ||
+          Code == METADATA_NODE_2_7) {
+        LLVM2_7MetadataDetected = true;
+      }
+
+      if (Record.size() % 2 == 1)
+        return Error("Invalid record");
+
+      unsigned Size = Record.size();
+      SmallVector<Metadata *, 8> Elts;
+      for (unsigned i = 0; i != Size; i += 2) {
+        Type *Ty = getTypeByID(Record[i]);
+        if (!Ty)
+          return Error("Invalid record");
+        if (Ty->isMetadataTy())
+          Elts.push_back(MDValueList.getValueFwdRef(Record[i+1]));
+        else if (!Ty->isVoidTy()) {
+          auto *MD =
+              ValueAsMetadata::get(ValueList.getValueFwdRef(Record[i + 1], Ty));
+          assert(isa<ConstantAsMetadata>(MD) &&
+                 "Expected non-function-local metadata");
+          Elts.push_back(MD);
+        } else
+          Elts.push_back(nullptr);
+      }
+      MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++);
+      break;
+    }
+    case bitc::METADATA_STRING: {
+      std::string String(Record.begin(), Record.end());
+      llvm::UpgradeMDStringConstant(String);
+      Metadata *MD = MDString::get(Context, String);
+      MDValueList.AssignValue(MD, NextMDValueNo++);
+      break;
+    }
+    case bitc::METADATA_KIND: {
+      if (Record.size() < 2)
+        return Error("Invalid record");
+
+      unsigned Kind = Record[0];
+      SmallString<8> Name(Record.begin()+1, Record.end());
+
+      unsigned NewKind = TheModule->getMDKindID(Name.str());
+      if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
+        return Error("Conflicting METADATA_KIND records");
+      break;
+    }
+    }
+  }
+}
+
+/// decodeSignRotatedValue - Decode a signed value stored with the sign bit in
+/// the LSB for dense VBR encoding.
+uint64_t BitcodeReader::decodeSignRotatedValue(uint64_t V) {
+  if ((V & 1) == 0)
+    return V >> 1;
+  if (V != 1)
+    return -(V >> 1);
+  // There is no such thing as -0 with integers.  "-0" really means MININT.
+  return 1ULL << 63;
+}
+
+// FIXME: Delete this in LLVM 4.0 and just assert that the aliasee is a
+// GlobalObject.
+static GlobalObject &
+getGlobalObjectInExpr(const DenseMap<GlobalAlias *, Constant *> &Map,
+                      Constant &C) {
+  auto *GO = dyn_cast<GlobalObject>(&C);
+  if (GO)
+    return *GO;
+
+  auto *GA = dyn_cast<GlobalAlias>(&C);
+  if (GA)
+    return getGlobalObjectInExpr(Map, *Map.find(GA)->second);
+
+  auto &CE = cast<ConstantExpr>(C);
+  assert(CE.getOpcode() == Instruction::BitCast ||
+         CE.getOpcode() == Instruction::GetElementPtr ||
+         CE.getOpcode() == Instruction::AddrSpaceCast);
+  if (CE.getOpcode() == Instruction::GetElementPtr)
+    assert(cast<GEPOperator>(CE).hasAllZeroIndices());
+  return getGlobalObjectInExpr(Map, *CE.getOperand(0));
+}
+
+/// ResolveGlobalAndAliasInits - Resolve all of the initializers for global
+/// values and aliases that we can.
+std::error_code BitcodeReader::ResolveGlobalAndAliasInits() {
+  std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
+  std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
+
+  GlobalInitWorklist.swap(GlobalInits);
+  AliasInitWorklist.swap(AliasInits);
+
+  while (!GlobalInitWorklist.empty()) {
+    unsigned ValID = GlobalInitWorklist.back().second;
+    if (ValID >= ValueList.size()) {
+      // Not ready to resolve this yet, it requires something later in the file.
+      GlobalInits.push_back(GlobalInitWorklist.back());
+    } else {
+      if (Constant *C = dyn_cast_or_null<Constant>(ValueList[ValID]))
+        GlobalInitWorklist.back().first->setInitializer(C);
+      else
+        return Error("Expected a constant");
+    }
+    GlobalInitWorklist.pop_back();
+  }
+
+  // FIXME: Delete this in LLVM 4.0
+  // Older versions of llvm could write an alias pointing to another. We cannot
+  // construct those aliases, so we first collect an alias to aliasee expression
+  // and then compute the actual aliasee.
+  DenseMap<GlobalAlias *, Constant *> AliasInit;
+
+  while (!AliasInitWorklist.empty()) {
+    unsigned ValID = AliasInitWorklist.back().second;
+    if (ValID >= ValueList.size()) {
+      AliasInits.push_back(AliasInitWorklist.back());
+    } else {
+      if (Constant *C = dyn_cast_or_null<Constant>(ValueList[ValID]))
+        AliasInit.insert(std::make_pair(AliasInitWorklist.back().first, C));
+      else
+        return Error("Expected a constant");
+    }
+    AliasInitWorklist.pop_back();
+  }
+
+  for (auto &Pair : AliasInit) {
+    auto &GO = getGlobalObjectInExpr(AliasInit, *Pair.second);
+    Pair.first->setAliasee(&GO);
+  }
+
+  return std::error_code();
+}
+
+static APInt ReadWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
+  SmallVector<uint64_t, 8> Words(Vals.size());
+  std::transform(Vals.begin(), Vals.end(), Words.begin(),
+                 BitcodeReader::decodeSignRotatedValue);
+
+  return APInt(TypeBits, Words);
+}
+
+std::error_code BitcodeReader::ParseConstants() {
+  if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this value table.
+  Type *CurTy = Type::getInt32Ty(Context);
+  unsigned NextCstNo = ValueList.size();
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      if (NextCstNo != ValueList.size())
+        return Error("Invalid constant reference");
+
+      // Once all the constants have been read, go through and resolve forward
+      // references.
+      ValueList.ResolveConstantForwardRefs();
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    Record.clear();
+    Value *V = nullptr;
+    unsigned BitCode = Stream.readRecord(Entry.ID, Record);
+    switch (BitCode) {
+    default:  // Default behavior: unknown constant
+    case bitc::CST_CODE_UNDEF:     // UNDEF
+      V = UndefValue::get(CurTy);
+      break;
+    case bitc::CST_CODE_SETTYPE:   // SETTYPE: [typeid]
+      if (Record.empty())
+        return Error("Invalid record");
+      if (Record[0] >= TypeList.size())
+        return Error("Invalid record");
+      CurTy = TypeList[Record[0]];
+      continue;  // Skip the ValueList manipulation.
+    case bitc::CST_CODE_NULL:      // NULL
+      V = Constant::getNullValue(CurTy);
+      break;
+    case bitc::CST_CODE_INTEGER:   // INTEGER: [intval]
+      if (!CurTy->isIntegerTy() || Record.empty())
+        return Error("Invalid record");
+      V = ConstantInt::get(CurTy, decodeSignRotatedValue(Record[0]));
+      break;
+    case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval]
+      if (!CurTy->isIntegerTy() || Record.empty())
+        return Error("Invalid record");
+
+      APInt VInt = ReadWideAPInt(Record,
+                                 cast<IntegerType>(CurTy)->getBitWidth());
+      V = ConstantInt::get(Context, VInt);
+
+      break;
+    }
+    case bitc::CST_CODE_FLOAT: {    // FLOAT: [fpval]
+      if (Record.empty())
+        return Error("Invalid record");
+      if (CurTy->isHalfTy())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEhalf,
+                                             APInt(16, (uint16_t)Record[0])));
+      else if (CurTy->isFloatTy())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEsingle,
+                                             APInt(32, (uint32_t)Record[0])));
+      else if (CurTy->isDoubleTy())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEdouble,
+                                             APInt(64, Record[0])));
+      else if (CurTy->isX86_FP80Ty()) {
+        // Bits are not stored the same way as a normal i80 APInt, compensate.
+        uint64_t Rearrange[2];
+        Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16);
+        Rearrange[1] = Record[0] >> 48;
+        V = ConstantFP::get(Context, APFloat(APFloat::x87DoubleExtended,
+                                             APInt(80, Rearrange)));
+      } else if (CurTy->isFP128Ty())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEquad,
+                                             APInt(128, Record)));
+      else if (CurTy->isPPC_FP128Ty())
+        V = ConstantFP::get(Context, APFloat(APFloat::PPCDoubleDouble,
+                                             APInt(128, Record)));
+      else
+        V = UndefValue::get(CurTy);
+      break;
+    }
+
+    case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number]
+      if (Record.empty())
+        return Error("Invalid record");
+
+      unsigned Size = Record.size();
+      SmallVector<Constant*, 16> Elts;
+
+      if (StructType *STy = dyn_cast<StructType>(CurTy)) {
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i],
+                                                     STy->getElementType(i)));
+        V = ConstantStruct::get(STy, Elts);
+      } else if (ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {
+        Type *EltTy = ATy->getElementType();
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+        V = ConstantArray::get(ATy, Elts);
+      } else if (VectorType *VTy = dyn_cast<VectorType>(CurTy)) {
+        Type *EltTy = VTy->getElementType();
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+        V = ConstantVector::get(Elts);
+      } else {
+        V = UndefValue::get(CurTy);
+      }
+      break;
+    }
+    case bitc::CST_CODE_STRING: { // STRING: [values]
+      if (Record.empty())
+        return Error("Invalid record");
+
+      ArrayType *ATy = cast<ArrayType>(CurTy);
+      Type *EltTy = ATy->getElementType();
+
+      unsigned Size = Record.size();
+      std::vector<Constant*> Elts;
+      for (unsigned i = 0; i != Size; ++i)
+        Elts.push_back(ConstantInt::get(EltTy, Record[i]));
+      V = ConstantArray::get(ATy, Elts);
+      break;
+    }
+    case bitc::CST_CODE_CSTRING: { // CSTRING: [values]
+      if (Record.empty())
+        return Error("Invalid record");
+
+      ArrayType *ATy = cast<ArrayType>(CurTy);
+      Type *EltTy = ATy->getElementType();
+
+      unsigned Size = Record.size();
+      std::vector<Constant*> Elts;
+      for (unsigned i = 0; i != Size; ++i)
+        Elts.push_back(ConstantInt::get(EltTy, Record[i]));
+      Elts.push_back(Constant::getNullValue(EltTy));
+      V = ConstantArray::get(ATy, Elts);
+      break;
+    }
+    case bitc::CST_CODE_CE_BINOP: {  // CE_BINOP: [opcode, opval, opval]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      int Opc = GetDecodedBinaryOpcode(Record[0], CurTy);
+      if (Opc < 0) {
+        V = UndefValue::get(CurTy);  // Unknown binop.
+      } else {
+        Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
+        Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
+        unsigned Flags = 0;
+        if (Record.size() >= 4) {
+          if (Opc == Instruction::Add ||
+              Opc == Instruction::Sub ||
+              Opc == Instruction::Mul ||
+              Opc == Instruction::Shl) {
+            if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
+              Flags |= OverflowingBinaryOperator::NoSignedWrap;
+            if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
+              Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
+          } else if (Opc == Instruction::SDiv ||
+                     Opc == Instruction::UDiv ||
+                     Opc == Instruction::LShr ||
+                     Opc == Instruction::AShr) {
+            if (Record[3] & (1 << bitc::PEO_EXACT))
+              Flags |= SDivOperator::IsExact;
+          }
+        }
+        V = ConstantExpr::get(Opc, LHS, RHS, Flags);
+      }
+      break;
+    }
+    case bitc::CST_CODE_CE_CAST: {  // CE_CAST: [opcode, opty, opval]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      int Opc = GetDecodedCastOpcode(Record[0]);
+      if (Opc < 0) {
+        V = UndefValue::get(CurTy);  // Unknown cast.
+      } else {
+        Type *OpTy = getTypeByID(Record[1]);
+        if (!OpTy)
+          return Error("Invalid record");
+        Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy);
+        V = ConstantExpr::getCast(Opc, Op, CurTy);
+      }
+      break;
+    }
+    case bitc::CST_CODE_CE_INBOUNDS_GEP:
+    case bitc::CST_CODE_CE_GEP: {  // CE_GEP:        [n x operands]
+      Type *PointeeType = nullptr;
+      if (Record.size() & 1)
+        return Error("Invalid record");
+      SmallVector<Constant*, 16> Elts;
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        Type *ElTy = getTypeByID(Record[i]);
+        if (!ElTy)
+          return Error("Invalid record");
+        Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
+      }
+      ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
+      V = ConstantExpr::getGetElementPtr(PointeeType, Elts[0], Indices,
+                                         BitCode ==
+                                           bitc::CST_CODE_CE_INBOUNDS_GEP);
+      break;
+    }
+    case bitc::CST_CODE_CE_SELECT:  // CE_SELECT: [opval#, opval#, opval#]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0],
+                                                              Type::getInt1Ty(Context)),
+                                  ValueList.getConstantFwdRef(Record[1],CurTy),
+                                  ValueList.getConstantFwdRef(Record[2],CurTy));
+      break;
+    case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      VectorType *OpTy =
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (!OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
+      V = ConstantExpr::getExtractElement(Op0, Op1);
+      break;
+    }
+    case bitc::CST_CODE_CE_INSERTELT: { // CE_INSERTELT: [opval, opval, opval]
+      VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+      if (Record.size() < 3 || !OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[1],
+                                                  OpTy->getElementType());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
+      V = ConstantExpr::getInsertElement(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval]
+      VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+      if (Record.size() < 3 || !OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+                                                 OpTy->getNumElements());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy);
+      V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval]
+      VectorType *RTy = dyn_cast<VectorType>(CurTy);
+      VectorType *OpTy =
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (Record.size() < 4 || !RTy || !OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+      Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+                                                 RTy->getNumElements());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[3], ShufTy);
+      V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_CMP: {     // CE_CMP: [opty, opval, opval, pred]
+      if (Record.size() < 4)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      if (!OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+
+      if (OpTy->isFPOrFPVectorTy())
+        V = ConstantExpr::getFCmp(Record[3], Op0, Op1);
+      else
+        V = ConstantExpr::getICmp(Record[3], Op0, Op1);
+      break;
+    }
+    case bitc::CST_CODE_INLINEASM:
+    case bitc::CST_CODE_INLINEASM_OLD: {
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      std::string AsmStr, ConstrStr;
+      bool HasSideEffects = Record[0] & 1;
+      bool IsAlignStack = Record[0] >> 1;
+      unsigned AsmStrSize = Record[1];
+      if (2+AsmStrSize >= Record.size())
+        return Error("Invalid record");
+      unsigned ConstStrSize = Record[2+AsmStrSize];
+      if (3+AsmStrSize+ConstStrSize > Record.size())
+        return Error("Invalid record");
+
+      for (unsigned i = 0; i != AsmStrSize; ++i)
+        AsmStr += (char)Record[2+i];
+      for (unsigned i = 0; i != ConstStrSize; ++i)
+        ConstrStr += (char)Record[3+AsmStrSize+i];
+      PointerType *PTy = cast<PointerType>(CurTy);
+      V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
+                         AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
+      break;
+    }
+    case bitc::CST_CODE_BLOCKADDRESS:{
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      Type *FnTy = getTypeByID(Record[0]);
+      if (!FnTy)
+        return Error("Invalid record");
+      Function *Fn =
+        dyn_cast_or_null<Function>(ValueList.getConstantFwdRef(Record[1],FnTy));
+      if (!Fn)
+        return Error("Invalid record");
+
+      GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(),
+                                                  Type::getInt8Ty(Context),
+                                            false, GlobalValue::InternalLinkage,
+                                                  0, "");
+      BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef));
+      V = FwdRef;
+      break;
+    }
+    }
+
+    ValueList.AssignValue(V, NextCstNo);
+    ++NextCstNo;
+  }
+
+  if (NextCstNo != ValueList.size())
+    return Error("Invalid constant reference");
+
+  if (Stream.ReadBlockEnd())
+    return Error("Expected a constant");
+
+  // Once all the constants have been read, go through and resolve forward
+  // references.
+  ValueList.ResolveConstantForwardRefs();
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::materializeMetadata() {
+  return std::error_code();
+}
+
+void BitcodeReader::setStripDebugInfo() { }
+
+/// RememberAndSkipFunctionBody - When we see the block for a function body,
+/// remember where it is and then skip it.  This lets us lazily deserialize the
+/// functions.
+std::error_code BitcodeReader::RememberAndSkipFunctionBody() {
+  // Get the function we are talking about.
+  if (FunctionsWithBodies.empty())
+    return Error("Insufficient function protos");
+
+  Function *Fn = FunctionsWithBodies.back();
+  FunctionsWithBodies.pop_back();
+
+  // Save the current stream state.
+  uint64_t CurBit = Stream.GetCurrentBitNo();
+  DeferredFunctionInfo[Fn] = CurBit;
+
+  // Skip over the function block for now.
+  if (Stream.SkipBlock())
+    return Error("Invalid record");
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::GlobalCleanup() {
+  // Patch the initializers for globals and aliases up.
+  ResolveGlobalAndAliasInits();
+  if (!GlobalInits.empty() || !AliasInits.empty())
+    return Error("Malformed global initializer set");
+
+  // Look for intrinsic functions which need to be upgraded at some point
+  for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
+       FI != FE; ++FI) {
+    Function *NewFn;
+    if (UpgradeIntrinsicFunction(&*FI, NewFn))
+      UpgradedIntrinsics.push_back(std::make_pair(&*FI, NewFn));
+  }
+
+  // Look for global variables which need to be renamed.
+  for (Module::global_iterator
+         GI = TheModule->global_begin(), GE = TheModule->global_end();
+       GI != GE; GI++) {
+    GlobalVariable *GV = &*GI;
+    UpgradeGlobalVariable(&*GV);
+  }
+
+  // Force deallocation of memory for these vectors to favor the client that
+  // want lazy deserialization.
+  std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
+  std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::ParseModule(bool Resume) {
+  if (Resume)
+    Stream.JumpToBit(NextUnreadBit);
+  else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+  std::vector<std::string> SectionTable;
+  std::vector<std::string> GCTable;
+
+  // Read all the records for this module.
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+
+      // Patch the initializers for globals and aliases up.
+      ResolveGlobalAndAliasInits();
+      if (!GlobalInits.empty() || !AliasInits.empty())
+        return Error("Malformed global initializer set");
+      if (!FunctionsWithBodies.empty())
+        return Error("Insufficient function protos");
+
+      // Look for intrinsic functions which need to be upgraded at some point
+      for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
+           FI != FE; ++FI) {
+        Function* NewFn;
+        if (UpgradeIntrinsicFunction(&*FI, NewFn))
+          UpgradedIntrinsics.push_back(std::make_pair(&*FI, NewFn));
+      }
+
+      // Look for global variables which need to be renamed.
+      for (Module::global_iterator
+             GI = TheModule->global_begin(), GE = TheModule->global_end();
+           GI != GE; ++GI)
+        UpgradeGlobalVariable(&*GI);
+
+      // Force deallocation of memory for these vectors to favor the client that
+      // want lazy deserialization.
+      std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
+      std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
+      std::vector<Function*>().swap(FunctionsWithBodies);
+      return std::error_code();
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      default:  // Skip unknown content.
+        if (Stream.SkipBlock())
+          return Error("Invalid record");
+        break;
+      case bitc::BLOCKINFO_BLOCK_ID:
+        if (Stream.ReadBlockInfoBlock())
+          return Error("Malformed block");
+        break;
+      case bitc::PARAMATTR_BLOCK_ID:
+        if (std::error_code EC = ParseAttributeBlock())
+          return EC;
+        break;
+      case bitc::TYPE_BLOCK_ID_NEW:
+        if (std::error_code EC = ParseTypeTable())
+          return EC;
+        break;
+      case TYPE_BLOCK_ID_OLD_3_0:
+        if (std::error_code EC = ParseOldTypeTable())
+          return EC;
+        break;
+      case TYPE_SYMTAB_BLOCK_ID_OLD_3_0:
+        if (std::error_code EC = ParseOldTypeSymbolTable())
+          return EC;
+        break;
+      case bitc::VALUE_SYMTAB_BLOCK_ID:
+        if (std::error_code EC = ParseValueSymbolTable())
+          return EC;
+        SeenValueSymbolTable = true;
+        break;
+      case bitc::CONSTANTS_BLOCK_ID:
+        if (std::error_code EC = ParseConstants())
+          return EC;
+        if (std::error_code EC = ResolveGlobalAndAliasInits())
+          return EC;
+        break;
+      case bitc::METADATA_BLOCK_ID:
+        if (std::error_code EC = ParseMetadata())
+          return EC;
+        break;
+      case bitc::FUNCTION_BLOCK_ID:
+        // If this is the first function body we've seen, reverse the
+        // FunctionsWithBodies list.
+        if (!SeenFirstFunctionBody) {
+          std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
+          if (std::error_code EC = GlobalCleanup())
+            return EC;
+          SeenFirstFunctionBody = true;
+        }
+
+        if (std::error_code EC = RememberAndSkipFunctionBody())
+          return EC;
+        // For streaming bitcode, suspend parsing when we reach the function
+        // bodies. Subsequent materialization calls will resume it when
+        // necessary. For streaming, the function bodies must be at the end of
+        // the bitcode. If the bitcode file is old, the symbol table will be
+        // at the end instead and will not have been seen yet. In this case,
+        // just finish the parse now.
+        if (LazyStreamer && SeenValueSymbolTable) {
+          NextUnreadBit = Stream.GetCurrentBitNo();
+          return std::error_code();
+        }
+        break;
+        break;
+      }
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    switch (Stream.readRecord(Code, Record)) {
+    default: break;  // Default behavior, ignore unknown content.
+    case bitc::MODULE_CODE_VERSION: {  // VERSION: [version#]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      // Only version #0 is supported so far.
+      if (Record[0] != 0)
+        return Error("Invalid value");
+      break;
+    }
+    case bitc::MODULE_CODE_TRIPLE: {  // TRIPLE: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      TheModule->setTargetTriple(S);
+      break;
+    }
+    case bitc::MODULE_CODE_DATALAYOUT: {  // DATALAYOUT: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      TheModule->setDataLayout(S);
+      break;
+    }
+    case bitc::MODULE_CODE_ASM: {  // ASM: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      TheModule->setModuleInlineAsm(S);
+      break;
+    }
+    case bitc::MODULE_CODE_DEPLIB: {  // DEPLIB: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      // ANDROID: Ignore value, since we never used it anyways.
+      // TheModule->addLibrary(S);
+      break;
+    }
+    case bitc::MODULE_CODE_SECTIONNAME: {  // SECTIONNAME: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      SectionTable.push_back(S);
+      break;
+    }
+    case bitc::MODULE_CODE_GCNAME: {  // SECTIONNAME: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      GCTable.push_back(S);
+      break;
+    }
+    // GLOBALVAR: [pointer type, isconst, initid,
+    //             linkage, alignment, section, visibility, threadlocal,
+    //             unnamed_addr]
+    case bitc::MODULE_CODE_GLOBALVAR: {
+      if (Record.size() < 6)
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+      if (!Ty->isPointerTy())
+        return Error("Invalid type for value");
+      unsigned AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
+      Ty = cast<PointerType>(Ty)->getElementType();
+
+      bool isConstant = Record[1];
+      uint64_t RawLinkage = Record[3];
+      GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
+      unsigned Alignment = (1 << Record[4]) >> 1;
+      std::string Section;
+      if (Record[5]) {
+        if (Record[5]-1 >= SectionTable.size())
+          return Error("Invalid ID");
+        Section = SectionTable[Record[5]-1];
+      }
+      GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility;
+      if (Record.size() > 6)
+        Visibility = GetDecodedVisibility(Record[6]);
+
+      GlobalVariable::ThreadLocalMode TLM = GlobalVariable::NotThreadLocal;
+      if (Record.size() > 7)
+        TLM = GetDecodedThreadLocalMode(Record[7]);
+
+      bool UnnamedAddr = false;
+      if (Record.size() > 8)
+        UnnamedAddr = Record[8];
+
+      GlobalVariable *NewGV =
+        new GlobalVariable(*TheModule, Ty, isConstant, Linkage, nullptr, "", nullptr,
+                           TLM, AddressSpace);
+      NewGV->setAlignment(Alignment);
+      if (!Section.empty())
+        NewGV->setSection(Section);
+      NewGV->setVisibility(Visibility);
+      NewGV->setUnnamedAddr(UnnamedAddr);
+
+      ValueList.push_back(NewGV);
+
+      // Remember which value to use for the global initializer.
+      if (unsigned InitID = Record[2])
+        GlobalInits.push_back(std::make_pair(NewGV, InitID-1));
+      break;
+    }
+    // FUNCTION:  [type, callingconv, isproto, linkage, paramattr,
+    //             alignment, section, visibility, gc, unnamed_addr]
+    case bitc::MODULE_CODE_FUNCTION: {
+      if (Record.size() < 8)
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+      if (!Ty->isPointerTy())
+        return Error("Invalid type for value");
+      FunctionType *FTy =
+        dyn_cast<FunctionType>(cast<PointerType>(Ty)->getElementType());
+      if (!FTy)
+        return Error("Invalid type for value");
+
+      Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
+                                        "", TheModule);
+
+      Func->setCallingConv(static_cast<CallingConv::ID>(Record[1]));
+      bool isProto = Record[2];
+      uint64_t RawLinkage = Record[3];
+      Func->setLinkage(getDecodedLinkage(RawLinkage));
+      Func->setAttributes(getAttributes(Record[4]));
+
+      Func->setAlignment((1 << Record[5]) >> 1);
+      if (Record[6]) {
+        if (Record[6]-1 >= SectionTable.size())
+          return Error("Invalid ID");
+        Func->setSection(SectionTable[Record[6]-1]);
+      }
+      Func->setVisibility(GetDecodedVisibility(Record[7]));
+      if (Record.size() > 8 && Record[8]) {
+        if (Record[8]-1 > GCTable.size())
+          return Error("Invalid ID");
+        Func->setGC(GCTable[Record[8]-1].c_str());
+      }
+      bool UnnamedAddr = false;
+      if (Record.size() > 9)
+        UnnamedAddr = Record[9];
+      Func->setUnnamedAddr(UnnamedAddr);
+      ValueList.push_back(Func);
+
+      // If this is a function with a body, remember the prototype we are
+      // creating now, so that we can match up the body with them later.
+      if (!isProto) {
+        Func->setIsMaterializable(true);
+        FunctionsWithBodies.push_back(Func);
+        if (LazyStreamer)
+          DeferredFunctionInfo[Func] = 0;
+      }
+      break;
+    }
+    // ALIAS: [alias type, aliasee val#, linkage]
+    // ALIAS: [alias type, aliasee val#, linkage, visibility]
+    case bitc::MODULE_CODE_ALIAS_OLD: {
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+      auto *PTy = dyn_cast<PointerType>(Ty);
+      if (!PTy)
+        return Error("Invalid type for value");
+
+      auto *NewGA =
+          GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
+                              getDecodedLinkage(Record[2]), "", TheModule);
+      // Old bitcode files didn't have visibility field.
+      if (Record.size() > 3)
+        NewGA->setVisibility(GetDecodedVisibility(Record[3]));
+      ValueList.push_back(NewGA);
+      AliasInits.push_back(std::make_pair(NewGA, Record[1]));
+      break;
+    }
+    /// MODULE_CODE_PURGEVALS: [numvals]
+    case bitc::MODULE_CODE_PURGEVALS:
+      // Trim down the value list to the specified size.
+      if (Record.size() < 1 || Record[0] > ValueList.size())
+        return Error("Invalid record");
+      ValueList.shrinkTo(Record[0]);
+      break;
+    }
+    Record.clear();
+  }
+
+  return Error("Invalid bitcode signature");
+}
+
+std::error_code BitcodeReader::ParseBitcodeInto(Module *M) {
+  TheModule = nullptr;
+
+  if (std::error_code EC = InitStream())
+    return EC;
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'B' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(4) != 0x0 ||
+      Stream.Read(4) != 0xC ||
+      Stream.Read(4) != 0xE ||
+      Stream.Read(4) != 0xD)
+    return Error("Invalid bitcode signature");
+
+  // We expect a number of well-defined blocks, though we don't necessarily
+  // need to understand them all.
+  while (1) {
+    if (Stream.AtEndOfStream())
+      return std::error_code();
+
+    BitstreamEntry Entry =
+      Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+
+    case BitstreamEntry::SubBlock:
+      switch (Entry.ID) {
+      case bitc::BLOCKINFO_BLOCK_ID:
+        if (Stream.ReadBlockInfoBlock())
+          return Error("Malformed block");
+        break;
+      case bitc::MODULE_BLOCK_ID:
+        // Reject multiple MODULE_BLOCK's in a single bitstream.
+        if (TheModule)
+          return Error("Invalid multiple blocks");
+        TheModule = M;
+        if (std::error_code EC = ParseModule(false))
+          return EC;
+        if (LazyStreamer)
+          return std::error_code();
+        break;
+      default:
+        if (Stream.SkipBlock())
+          return Error("Invalid record");
+        break;
+      }
+      continue;
+    case BitstreamEntry::Record:
+      // There should be no records in the top-level of blocks.
+
+      // The ranlib in Xcode 4 will align archive members by appending newlines
+      // to the end of them. If this file size is a multiple of 4 but not 8, we
+      // have to read and ignore these final 4 bytes :-(
+      if (Stream.getAbbrevIDWidth() == 2 && Entry.ID == 2 &&
+          Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a &&
+          Stream.AtEndOfStream())
+        return std::error_code();
+
+      return Error("Invalid record");
+    }
+  }
+}
+
+llvm::ErrorOr<std::string> BitcodeReader::parseModuleTriple() {
+  if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  std::string Triple;
+  // Read all the records for this module.
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return Triple;
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default: break;  // Default behavior, ignore unknown content.
+    case bitc::MODULE_CODE_VERSION:  // VERSION: [version#]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      // Only version #0 is supported so far.
+      if (Record[0] != 0)
+        return Error("Invalid record");
+      break;
+    case bitc::MODULE_CODE_TRIPLE: {  // TRIPLE: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      Triple = S;
+      break;
+    }
+    }
+    Record.clear();
+  }
+
+  return Error("Invalid bitcode signature");
+}
+
+llvm::ErrorOr<std::string> BitcodeReader::parseTriple() {
+  if (std::error_code EC = InitStream())
+    return EC;
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'B' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(4) != 0x0 ||
+      Stream.Read(4) != 0xC ||
+      Stream.Read(4) != 0xE ||
+      Stream.Read(4) != 0xD)
+    return Error("Invalid bitcode signature");
+
+  // We expect a number of well-defined blocks, though we don't necessarily
+  // need to understand them all.
+  while (1) {
+    BitstreamEntry Entry = Stream.advance();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+
+    case BitstreamEntry::SubBlock:
+      if (Entry.ID == bitc::MODULE_BLOCK_ID)
+        return parseModuleTriple();
+
+      // Ignore other sub-blocks.
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+
+    case BitstreamEntry::Record:
+      Stream.skipRecord(Entry.ID);
+      continue;
+    }
+  }
+}
+
+/// ParseMetadataAttachment - Parse metadata attachments.
+std::error_code BitcodeReader::ParseMetadataAttachment() {
+  if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a metadata attachment record.
+    Record.clear();
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default:  // Default behavior: ignore.
+      break;
+    case METADATA_ATTACHMENT_2_7:
+      LLVM2_7MetadataDetected = true;
+    case bitc::METADATA_ATTACHMENT: {
+      unsigned RecordLength = Record.size();
+      if (Record.empty() || (RecordLength - 1) % 2 == 1)
+        return Error("Invalid record");
+      Instruction *Inst = InstructionList[Record[0]];
+      for (unsigned i = 1; i != RecordLength; i = i+2) {
+        unsigned Kind = Record[i];
+        DenseMap<unsigned, unsigned>::iterator I =
+          MDKindMap.find(Kind);
+        if (I == MDKindMap.end())
+          return Error("Invalid ID");
+        Metadata *Node = MDValueList.getValueFwdRef(Record[i + 1]);
+        Inst->setMetadata(I->second, cast<MDNode>(Node));
+      }
+      break;
+    }
+    }
+  }
+}
+
+/// ParseFunctionBody - Lazily parse the specified function body block.
+std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
+  if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
+    return Error("Invalid record");
+
+  InstructionList.clear();
+  unsigned ModuleValueListSize = ValueList.size();
+  unsigned ModuleMDValueListSize = MDValueList.size();
+
+  // Add all the function arguments to the value table.
+  for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
+    ValueList.push_back(&*I);
+
+  unsigned NextValueNo = ValueList.size();
+  BasicBlock *CurBB = nullptr;
+  unsigned CurBBNo = 0;
+
+  DebugLoc LastLoc;
+
+  // Read all the records.
+  SmallVector<uint64_t, 64> Record;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      break;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      default:  // Skip unknown content.
+        if (Stream.SkipBlock())
+          return Error("Invalid record");
+        break;
+      case bitc::CONSTANTS_BLOCK_ID:
+        if (std::error_code EC = ParseConstants())
+          return EC;
+        NextValueNo = ValueList.size();
+        break;
+      case bitc::VALUE_SYMTAB_BLOCK_ID:
+        if (std::error_code EC = ParseValueSymbolTable())
+          return EC;
+        break;
+      case bitc::METADATA_ATTACHMENT_ID:
+        if (std::error_code EC = ParseMetadataAttachment())
+          return EC;
+        break;
+      case bitc::METADATA_BLOCK_ID:
+        if (std::error_code EC = ParseMetadata())
+          return EC;
+        break;
+      }
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Instruction *I = nullptr;
+    unsigned BitCode = Stream.readRecord(Code, Record);
+    switch (BitCode) {
+    default: // Default behavior: reject
+      return Error("Invalid value");
+    case bitc::FUNC_CODE_DECLAREBLOCKS:     // DECLAREBLOCKS: [nblocks]
+      if (Record.size() < 1 || Record[0] == 0)
+        return Error("Invalid record");
+      // Create all the basic blocks for the function.
+      FunctionBBs.resize(Record[0]);
+      for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
+        FunctionBBs[i] = BasicBlock::Create(Context, "", F);
+      CurBB = FunctionBBs[0];
+      continue;
+
+    case bitc::FUNC_CODE_DEBUG_LOC_AGAIN:  // DEBUG_LOC_AGAIN
+      // This record indicates that the last instruction is at the same
+      // location as the previous instruction with a location.
+      I = nullptr;
+
+      // Get the last instruction emitted.
+      if (CurBB && !CurBB->empty())
+        I = &CurBB->back();
+      else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+               !FunctionBBs[CurBBNo-1]->empty())
+        I = &FunctionBBs[CurBBNo-1]->back();
+
+      if (!I)
+        return Error("Invalid record");
+      I->setDebugLoc(LastLoc);
+      I = nullptr;
+      continue;
+
+    case FUNC_CODE_DEBUG_LOC_2_7:
+      LLVM2_7MetadataDetected = true;
+    case bitc::FUNC_CODE_DEBUG_LOC: {      // DEBUG_LOC: [line, col, scope, ia]
+      I = nullptr;     // Get the last instruction emitted.
+      if (CurBB && !CurBB->empty())
+        I = &CurBB->back();
+      else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+               !FunctionBBs[CurBBNo-1]->empty())
+        I = &FunctionBBs[CurBBNo-1]->back();
+      if (!I || Record.size() < 4)
+        return Error("Invalid record");
+
+      unsigned Line = Record[0], Col = Record[1];
+      unsigned ScopeID = Record[2], IAID = Record[3];
+
+      MDNode *Scope = nullptr, *IA = nullptr;
+      if (ScopeID) Scope = cast<MDNode>(MDValueList.getValueFwdRef(ScopeID-1));
+      if (IAID)    IA = cast<MDNode>(MDValueList.getValueFwdRef(IAID-1));
+      LastLoc = DebugLoc::get(Line, Col, Scope, IA);
+      I->setDebugLoc(LastLoc);
+      I = nullptr;
+      continue;
+    }
+
+    case bitc::FUNC_CODE_INST_BINOP: {    // BINOP: [opval, ty, opval, opcode]
+      unsigned OpNum = 0;
+      Value *LHS, *RHS;
+      if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+          getValue(Record, OpNum, LHS->getType(), RHS) ||
+          OpNum+1 > Record.size())
+        return Error("Invalid record");
+
+      int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
+      if (Opc == -1)
+        return Error("Invalid record");
+      I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
+      InstructionList.push_back(I);
+      if (OpNum < Record.size()) {
+        if (Opc == Instruction::Add ||
+            Opc == Instruction::Sub ||
+            Opc == Instruction::Mul ||
+            Opc == Instruction::Shl) {
+          if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP))
+            cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
+          if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
+            cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
+        } else if (Opc == Instruction::SDiv ||
+                   Opc == Instruction::UDiv ||
+                   Opc == Instruction::LShr ||
+                   Opc == Instruction::AShr) {
+          if (Record[OpNum] & (1 << bitc::PEO_EXACT))
+            cast<BinaryOperator>(I)->setIsExact(true);
+        }
+      }
+      break;
+    }
+    case bitc::FUNC_CODE_INST_CAST: {    // CAST: [opval, opty, destty, castopc]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid record");
+
+      Type *ResTy = getTypeByID(Record[OpNum]);
+      int Opc = GetDecodedCastOpcode(Record[OpNum+1]);
+      if (Opc == -1 || !ResTy)
+        return Error("Invalid record");
+      I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD:
+    case bitc::FUNC_CODE_INST_GEP_OLD: // GEP: [n x operands]
+    case bitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands]
+      unsigned OpNum = 0;
+
+      Type *Ty;
+      bool InBounds;
+
+      if (BitCode == bitc::FUNC_CODE_INST_GEP) {
+        InBounds = Record[OpNum++];
+        Ty = getTypeByID(Record[OpNum++]);
+      } else {
+        InBounds = BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD;
+        Ty = nullptr;
+      }
+
+      Value *BasePtr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr))
+        return Error("Invalid record");
+
+      if (Ty &&
+          Ty !=
+              cast<SequentialType>(BasePtr->getType()->getScalarType())
+                  ->getElementType())
+        return Error(
+            "Explicit gep type does not match pointee type of pointer operand");
+
+      SmallVector<Value*, 16> GEPIdx;
+      while (OpNum != Record.size()) {
+        Value *Op;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid record");
+        GEPIdx.push_back(Op);
+      }
+
+      I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx);
+
+      InstructionList.push_back(I);
+      if (InBounds)
+        cast<GetElementPtrInst>(I)->setIsInBounds(true);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_EXTRACTVAL: {
+                                       // EXTRACTVAL: [opty, opval, n x indices]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid record");
+
+      SmallVector<unsigned, 4> EXTRACTVALIdx;
+      for (unsigned RecSize = Record.size();
+           OpNum != RecSize; ++OpNum) {
+        uint64_t Index = Record[OpNum];
+        if ((unsigned)Index != Index)
+          return Error("Invalid value");
+        EXTRACTVALIdx.push_back((unsigned)Index);
+      }
+
+      I = ExtractValueInst::Create(Agg, EXTRACTVALIdx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INSERTVAL: {
+                           // INSERTVAL: [opty, opval, opty, opval, n x indices]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid record");
+      Value *Val;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Val))
+        return Error("Invalid record");
+
+      SmallVector<unsigned, 4> INSERTVALIdx;
+      for (unsigned RecSize = Record.size();
+           OpNum != RecSize; ++OpNum) {
+        uint64_t Index = Record[OpNum];
+        if ((unsigned)Index != Index)
+          return Error("Invalid value");
+        INSERTVALIdx.push_back((unsigned)Index);
+      }
+
+      I = InsertValueInst::Create(Agg, Val, INSERTVALIdx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval]
+      // obsolete form of select
+      // handles select i1 ... in old bitcode
+      unsigned OpNum = 0;
+      Value *TrueVal, *FalseVal, *Cond;
+      if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+          getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
+          getValue(Record, OpNum, Type::getInt1Ty(Context), Cond))
+        return Error("Invalid record");
+
+      I = SelectInst::Create(Cond, TrueVal, FalseVal);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [ty,opval,opval,predty,pred]
+      // new form of select
+      // handles select i1 or select [N x i1]
+      unsigned OpNum = 0;
+      Value *TrueVal, *FalseVal, *Cond;
+      if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+          getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
+          getValueTypePair(Record, OpNum, NextValueNo, Cond))
+        return Error("Invalid record");
+
+      // select condition can be either i1 or [N x i1]
+      if (VectorType* vector_type =
+          dyn_cast<VectorType>(Cond->getType())) {
+        // expect <n x i1>
+        if (vector_type->getElementType() != Type::getInt1Ty(Context))
+          return Error("Invalid type for value");
+      } else {
+        // expect i1
+        if (Cond->getType() != Type::getInt1Ty(Context))
+          return Error("Invalid type for value");
+      }
+
+      I = SelectInst::Create(Cond, TrueVal, FalseVal);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval]
+      unsigned OpNum = 0;
+      Value *Vec, *Idx;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+          getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+        return Error("Invalid record");
+      I = ExtractElementInst::Create(Vec, Idx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval]
+      unsigned OpNum = 0;
+      Value *Vec, *Elt, *Idx;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+          getValue(Record, OpNum,
+                   cast<VectorType>(Vec->getType())->getElementType(), Elt) ||
+          getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+        return Error("Invalid record");
+      I = InsertElementInst::Create(Vec, Elt, Idx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval]
+      unsigned OpNum = 0;
+      Value *Vec1, *Vec2, *Mask;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) ||
+          getValue(Record, OpNum, Vec1->getType(), Vec2))
+        return Error("Invalid record");
+
+      if (getValueTypePair(Record, OpNum, NextValueNo, Mask))
+        return Error("Invalid record");
+      I = new ShuffleVectorInst(Vec1, Vec2, Mask);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_CMP:   // CMP: [opty, opval, opval, pred]
+      // Old form of ICmp/FCmp returning bool
+      // Existed to differentiate between icmp/fcmp and vicmp/vfcmp which were
+      // both legal on vectors but had different behaviour.
+    case bitc::FUNC_CODE_INST_CMP2: { // CMP2: [opty, opval, opval, pred]
+      // FCmp/ICmp returning bool or vector of bool
+
+      unsigned OpNum = 0;
+      Value *LHS, *RHS;
+      if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+          getValue(Record, OpNum, LHS->getType(), RHS) ||
+          OpNum+1 != Record.size())
+        return Error("Invalid record");
+
+      if (LHS->getType()->isFPOrFPVectorTy())
+        I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS);
+      else
+        I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case FUNC_CODE_INST_GETRESULT_2_7: {
+      if (Record.size() != 2) {
+        return Error("Invalid record");
+      }
+      unsigned OpNum = 0;
+      Value *Op;
+      getValueTypePair(Record, OpNum, NextValueNo, Op);
+      unsigned Index = Record[1];
+      I = ExtractValueInst::Create(Op, Index);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_RET: // RET: [opty,opval<optional>]
+      {
+        unsigned Size = Record.size();
+        if (Size == 0) {
+          I = ReturnInst::Create(Context);
+          InstructionList.push_back(I);
+          break;
+        }
+
+        unsigned OpNum = 0;
+        Value *Op = nullptr;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid record");
+        if (OpNum != Record.size())
+          return Error("Invalid record");
+
+        I = ReturnInst::Create(Context, Op);
+        InstructionList.push_back(I);
+        break;
+      }
+    case bitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#]
+      if (Record.size() != 1 && Record.size() != 3)
+        return Error("Invalid record");
+      BasicBlock *TrueDest = getBasicBlock(Record[0]);
+      if (!TrueDest)
+        return Error("Invalid record");
+
+      if (Record.size() == 1) {
+        I = BranchInst::Create(TrueDest);
+        InstructionList.push_back(I);
+      }
+      else {
+        BasicBlock *FalseDest = getBasicBlock(Record[1]);
+        Value *Cond = getFnValueByID(Record[2], Type::getInt1Ty(Context));
+        if (!FalseDest || !Cond)
+          return Error("Invalid record");
+        I = BranchInst::Create(TrueDest, FalseDest, Cond);
+        InstructionList.push_back(I);
+      }
+      break;
+    }
+    case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
+      if (Record.size() < 3 || (Record.size() & 1) == 0)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Cond = getFnValueByID(Record[1], OpTy);
+      BasicBlock *Default = getBasicBlock(Record[2]);
+      if (!OpTy || !Cond || !Default)
+        return Error("Invalid record");
+      unsigned NumCases = (Record.size()-3)/2;
+      SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
+      InstructionList.push_back(SI);
+      for (unsigned i = 0, e = NumCases; i != e; ++i) {
+        ConstantInt *CaseVal =
+          dyn_cast_or_null<ConstantInt>(getFnValueByID(Record[3+i*2], OpTy));
+        BasicBlock *DestBB = getBasicBlock(Record[1+3+i*2]);
+        if (!CaseVal || !DestBB) {
+          delete SI;
+          return Error("Invalid record");
+        }
+        SI->addCase(CaseVal, DestBB);
+      }
+      I = SI;
+      break;
+    }
+    case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...]
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Address = getFnValueByID(Record[1], OpTy);
+      if (!OpTy || !Address)
+        return Error("Invalid record");
+      unsigned NumDests = Record.size()-2;
+      IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests);
+      InstructionList.push_back(IBI);
+      for (unsigned i = 0, e = NumDests; i != e; ++i) {
+        if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) {
+          IBI->addDestination(DestBB);
+        } else {
+          delete IBI;
+          return Error("Invalid record");
+        }
+      }
+      I = IBI;
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INVOKE: {
+      // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
+      if (Record.size() < 4)
+        return Error("Invalid record");
+      AttributeSet PAL = getAttributes(Record[0]);
+      unsigned CCInfo = Record[1];
+      BasicBlock *NormalBB = getBasicBlock(Record[2]);
+      BasicBlock *UnwindBB = getBasicBlock(Record[3]);
+
+      unsigned OpNum = 4;
+      Value *Callee;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+        return Error("Invalid record");
+
+      PointerType *CalleeTy = dyn_cast<PointerType>(Callee->getType());
+      FunctionType *FTy = !CalleeTy ? nullptr :
+        dyn_cast<FunctionType>(CalleeTy->getElementType());
+
+      // Check that the right number of fixed parameters are here.
+      if (!FTy || !NormalBB || !UnwindBB ||
+          Record.size() < OpNum+FTy->getNumParams())
+        return Error("Invalid record");
+
+      SmallVector<Value*, 16> Ops;
+      for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+        Ops.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+        if (!Ops.back())
+          return Error("Invalid record");
+      }
+
+      if (!FTy->isVarArg()) {
+        if (Record.size() != OpNum)
+          return Error("Invalid record");
+      } else {
+        // Read type/value pairs for varargs params.
+        while (OpNum != Record.size()) {
+          Value *Op;
+          if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+            return Error("Invalid record");
+          Ops.push_back(Op);
+        }
+      }
+
+      I = InvokeInst::Create(Callee, NormalBB, UnwindBB, Ops);
+      InstructionList.push_back(I);
+      cast<InvokeInst>(I)->setCallingConv(
+        static_cast<CallingConv::ID>(CCInfo));
+      cast<InvokeInst>(I)->setAttributes(PAL);
+      break;
+    }
+    case FUNC_CODE_INST_UNWIND_2_7: { // UNWIND_OLD
+      // 'unwind' instruction has been removed in LLVM 3.1
+      // Replace 'unwind' with 'landingpad' and 'resume'.
+      Type *ExnTy = StructType::get(Type::getInt8PtrTy(Context),
+                                    Type::getInt32Ty(Context), nullptr);
+
+      LandingPadInst *LP = LandingPadInst::Create(ExnTy, 1);
+      LP->setCleanup(true);
+
+      CurBB->getInstList().push_back(LP);
+      I = ResumeInst::Create(LP);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
+      I = new UnreachableInst(Context);
+      InstructionList.push_back(I);
+      break;
+    case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
+      if (Record.size() < 1 || ((Record.size()-1)&1))
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+
+      PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2);
+      InstructionList.push_back(PN);
+
+      for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) {
+        Value *V = getFnValueByID(Record[1+i], Ty);
+        BasicBlock *BB = getBasicBlock(Record[2+i]);
+        if (!V || !BB)
+          return Error("Invalid record");
+        PN->addIncoming(V, BB);
+      }
+      I = PN;
+      break;
+    }
+
+    case FUNC_CODE_INST_MALLOC_2_7: { // MALLOC: [instty, op, align]
+      // Autoupgrade malloc instruction to malloc call.
+      // FIXME: Remove in LLVM 3.0.
+      if (Record.size() < 3) {
+        return Error("Invalid record");
+      }
+      PointerType *Ty =
+          dyn_cast_or_null<PointerType>(getTypeByID(Record[0]));
+      Value *Size = getFnValueByID(Record[1], Type::getInt32Ty(Context));
+      if (!Ty || !Size)
+        return Error("Invalid record");
+      if (!CurBB)
+        return Error("Invalid instruction with no BB");
+      Type *Int32Ty = IntegerType::getInt32Ty(CurBB->getContext());
+      Constant *AllocSize = ConstantExpr::getSizeOf(Ty->getElementType());
+      AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, Int32Ty);
+      I = CallInst::CreateMalloc(CurBB, Int32Ty, Ty->getElementType(),
+                                 AllocSize, Size, nullptr);
+      InstructionList.push_back(I);
+      break;
+    }
+    case FUNC_CODE_INST_FREE_2_7: { // FREE: [op, opty]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum != Record.size()) {
+        return Error("Invalid record");
+      }
+      if (!CurBB)
+        return Error("Invalid instruction with no BB");
+      I = CallInst::CreateFree(Op, CurBB);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align]
+      // For backward compatibility, tolerate a lack of an opty, and use i32.
+      // Remove this in LLVM 3.0.
+      if (Record.size() < 3 || Record.size() > 4) {
+        return Error("Invalid record");
+      }
+      unsigned OpNum = 0;
+      PointerType *Ty =
+        dyn_cast_or_null<PointerType>(getTypeByID(Record[OpNum++]));
+      Type *OpTy = Record.size() == 4 ? getTypeByID(Record[OpNum++]) :
+                                              Type::getInt32Ty(Context);
+      Value *Size = getFnValueByID(Record[OpNum++], OpTy);
+      unsigned Align = Record[OpNum++];
+      if (!Ty || !Size)
+        return Error("Invalid record");
+      I = new AllocaInst(Ty->getElementType(), Size, (1 << Align) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid record");
+
+      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_STORE_OLD: { // STORE2:[ptrty, ptr, val, align, vol]
+      unsigned OpNum = 0;
+      Value *Val, *Ptr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid record");
+
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case FUNC_CODE_INST_STORE_2_7: {
+      unsigned OpNum = 0;
+      Value *Val, *Ptr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Val) ||
+          getValue(Record, OpNum,
+                   PointerType::getUnqual(Val->getType()), Ptr)||
+          OpNum+2 != Record.size()) {
+        return Error("Invalid record");
+      }
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case FUNC_CODE_INST_CALL_2_7:
+      LLVM2_7MetadataDetected = true;
+    case bitc::FUNC_CODE_INST_CALL: {
+      // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+
+      AttributeSet PAL = getAttributes(Record[0]);
+      unsigned CCInfo = Record[1];
+
+      unsigned OpNum = 2;
+      Value *Callee;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+        return Error("Invalid record");
+
+      PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
+      FunctionType *FTy = nullptr;
+      if (OpTy) FTy = dyn_cast<FunctionType>(OpTy->getElementType());
+      if (!FTy || Record.size() < FTy->getNumParams()+OpNum)
+        return Error("Invalid record");
+
+      SmallVector<Value*, 16> Args;
+      // Read the fixed params.
+      for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+        if (FTy->getParamType(i)->isLabelTy())
+          Args.push_back(getBasicBlock(Record[OpNum]));
+        else
+          Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+        if (!Args.back())
+          return Error("Invalid record");
+      }
+
+      // Read type/value pairs for varargs params.
+      if (!FTy->isVarArg()) {
+        if (OpNum != Record.size())
+          return Error("Invalid record");
+      } else {
+        while (OpNum != Record.size()) {
+          Value *Op;
+          if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+            return Error("Invalid record");
+          Args.push_back(Op);
+        }
+      }
+
+      I = CallInst::Create(Callee, Args);
+      InstructionList.push_back(I);
+      cast<CallInst>(I)->setCallingConv(
+        static_cast<CallingConv::ID>(CCInfo>>1));
+      cast<CallInst>(I)->setTailCall(CCInfo & 1);
+      cast<CallInst>(I)->setAttributes(PAL);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Op = getFnValueByID(Record[1], OpTy);
+      Type *ResTy = getTypeByID(Record[2]);
+      if (!OpTy || !Op || !ResTy)
+        return Error("Invalid record");
+      I = new VAArgInst(Op, ResTy);
+      InstructionList.push_back(I);
+      break;
+    }
+    }
+
+    // Add instruction to end of current BB.  If there is no current BB, reject
+    // this file.
+    if (!CurBB) {
+      delete I;
+      return Error("Invalid instruction with no BB");
+    }
+    CurBB->getInstList().push_back(I);
+
+    // If this was a terminator instruction, move to the next block.
+    if (isa<TerminatorInst>(I)) {
+      ++CurBBNo;
+      CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : nullptr;
+    }
+
+    // Non-void values get registered in the value table for future use.
+    if (I && !I->getType()->isVoidTy())
+      ValueList.AssignValue(I, NextValueNo++);
+  }
+
+  // Check the function list for unresolved values.
+  if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
+    if (!A->getParent()) {
+      // We found at least one unresolved value.  Nuke them all to avoid leaks.
+      for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
+        if ((A = dyn_cast_or_null<Argument>(ValueList[i])) && !A->getParent()) {
+          A->replaceAllUsesWith(UndefValue::get(A->getType()));
+          delete A;
+        }
+      }
+      return Error("Never resolved value found in function");
+    }
+  }
+
+  // FIXME: Check for unresolved forward-declared metadata references
+  // and clean up leaks.
+
+  // See if anything took the address of blocks in this function.  If so,
+  // resolve them now.
+  DenseMap<Function*, std::vector<BlockAddrRefTy> >::iterator BAFRI =
+    BlockAddrFwdRefs.find(F);
+  if (BAFRI != BlockAddrFwdRefs.end()) {
+    std::vector<BlockAddrRefTy> &RefList = BAFRI->second;
+    for (unsigned i = 0, e = RefList.size(); i != e; ++i) {
+      unsigned BlockIdx = RefList[i].first;
+      if (BlockIdx >= FunctionBBs.size())
+        return Error("Invalid ID");
+
+      GlobalVariable *FwdRef = RefList[i].second;
+      FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx]));
+      FwdRef->eraseFromParent();
+    }
+
+    BlockAddrFwdRefs.erase(BAFRI);
+  }
+
+  unsigned NewMDValueListSize = MDValueList.size();
+  // Trim the value list down to the size it was before we parsed this function.
+  ValueList.shrinkTo(ModuleValueListSize);
+  MDValueList.shrinkTo(ModuleMDValueListSize);
+
+  if (LLVM2_7MetadataDetected) {
+    MDValueList.resize(NewMDValueListSize);
+  }
+
+  std::vector<BasicBlock*>().swap(FunctionBBs);
+  return std::error_code();
+}
+
+//===----------------------------------------------------------------------===//
+// GVMaterializer implementation
+//===----------------------------------------------------------------------===//
+
+void BitcodeReader::releaseBuffer() { Buffer.release(); }
+
+std::error_code BitcodeReader::materialize(GlobalValue *GV) {
+  if (std::error_code EC = materializeMetadata())
+    return EC;
+
+  Function *F = dyn_cast<Function>(GV);
+  // If it's not a function or is already material, ignore the request.
+  if (!F || !F->isMaterializable())
+    return std::error_code();
+
+  DenseMap<Function*, uint64_t>::iterator DFII = DeferredFunctionInfo.find(F);
+  assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!");
+
+  // Move the bit stream to the saved position of the deferred function body.
+  Stream.JumpToBit(DFII->second);
+
+  if (std::error_code EC = ParseFunctionBody(F))
+    return EC;
+  F->setIsMaterializable(false);
+
+  // Upgrade any old intrinsic calls in the function.
+  for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(),
+       E = UpgradedIntrinsics.end(); I != E; ++I) {
+    if (I->first != I->second) {
+      for (auto UI = I->first->user_begin(), UE = I->first->user_end();
+           UI != UE;) {
+        if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+          UpgradeIntrinsicCall(CI, I->second);
+      }
+    }
+  }
+
+  return std::error_code();
+}
+
+bool BitcodeReader::isDematerializable(const GlobalValue *GV) const {
+  const Function *F = dyn_cast<Function>(GV);
+  if (!F || F->isDeclaration())
+    return false;
+  return DeferredFunctionInfo.count(const_cast<Function*>(F));
+}
+
+void BitcodeReader::dematerialize(GlobalValue *GV) {
+  Function *F = dyn_cast<Function>(GV);
+  // If this function isn't dematerializable, this is a noop.
+  if (!F || !isDematerializable(F))
+    return;
+
+  assert(DeferredFunctionInfo.count(F) && "No info to read function later?");
+
+  // Just forget the function body, we can remat it later.
+  F->deleteBody();
+  F->setIsMaterializable(true);
+}
+
+std::error_code BitcodeReader::materializeModule() {
+  // Iterate over the module, deserializing any functions that are still on
+  // disk.
+  for (Module::iterator F = TheModule->begin(), E = TheModule->end();
+       F != E; ++F) {
+    if (std::error_code EC = materialize(&*F))
+      return EC;
+  }
+  // At this point, if there are any function bodies, the current bit is
+  // pointing to the END_BLOCK record after them. Now make sure the rest
+  // of the bits in the module have been read.
+  if (NextUnreadBit)
+    ParseModule(true);
+
+  // Upgrade any intrinsic calls that slipped through (should not happen!) and
+  // delete the old functions to clean up. We can't do this unless the entire
+  // module is materialized because there could always be another function body
+  // with calls to the old function.
+  for (std::vector<std::pair<Function*, Function*> >::iterator I =
+       UpgradedIntrinsics.begin(), E = UpgradedIntrinsics.end(); I != E; ++I) {
+    if (I->first != I->second) {
+      for (auto UI = I->first->user_begin(), UE = I->first->user_end();
+           UI != UE;) {
+        if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+          UpgradeIntrinsicCall(CI, I->second);
+      }
+      if (!I->first->use_empty())
+        I->first->replaceAllUsesWith(I->second);
+      I->first->eraseFromParent();
+    }
+  }
+  std::vector<std::pair<Function*, Function*> >().swap(UpgradedIntrinsics);
+
+  // Check debug info intrinsics.
+  CheckDebugInfoIntrinsics(TheModule);
+
+  return std::error_code();
+}
+
+std::vector<StructType *> BitcodeReader::getIdentifiedStructTypes() const {
+  return IdentifiedStructTypes;
+}
+
+std::error_code BitcodeReader::InitStream() {
+  if (LazyStreamer)
+    return InitLazyStream();
+  return InitStreamFromBuffer();
+}
+
+std::error_code BitcodeReader::InitStreamFromBuffer() {
+  const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart();
+  const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
+
+  if (Buffer->getBufferSize() & 3)
+    return Error("Invalid bitcode signature");
+
+  // If we have a wrapper header, parse it and ignore the non-bc file contents.
+  // The magic number is 0x0B17C0DE stored in little endian.
+  if (isBitcodeWrapper(BufPtr, BufEnd))
+    if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))
+      return Error("Invalid bitcode wrapper header");
+
+  StreamFile.reset(new BitstreamReader(BufPtr, BufEnd));
+  Stream.init(&*StreamFile);
+
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::InitLazyStream() {
+  // Check and strip off the bitcode wrapper; BitstreamReader expects never to
+  // see it.
+  auto OwnedBytes = llvm::make_unique<StreamingMemoryObject>(
+      std::move(LazyStreamer));
+  StreamingMemoryObject &Bytes = *OwnedBytes;
+  StreamFile = llvm::make_unique<BitstreamReader>(std::move(OwnedBytes));
+  Stream.init(&*StreamFile);
+
+  unsigned char buf[16];
+  if (Bytes.readBytes(buf, 16, 0) != 16)
+    return Error("Invalid bitcode signature");
+
+  if (!isBitcode(buf, buf + 16))
+    return Error("Invalid bitcode signature");
+
+  if (isBitcodeWrapper(buf, buf + 4)) {
+    const unsigned char *bitcodeStart = buf;
+    const unsigned char *bitcodeEnd = buf + 16;
+    SkipBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false);
+    Bytes.dropLeadingBytes(bitcodeStart - buf);
+    Bytes.setKnownObjectSize(bitcodeEnd - bitcodeStart);
+  }
+  return std::error_code();
+}
+
+namespace {
+class BitcodeErrorCategoryType : public std::error_category {
+  const char *name() const LLVM_NOEXCEPT override {
+    return "llvm.bitcode";
+  }
+  std::string message(int IE) const override {
+    BitcodeError E = static_cast<BitcodeError>(IE);
+    switch (E) {
+    case BitcodeError::InvalidBitcodeSignature:
+      return "Invalid bitcode signature";
+    case BitcodeError::CorruptedBitcode:
+      return "Corrupted bitcode";
+    }
+    llvm_unreachable("Unknown error type!");
+  }
+};
+}
+
+static ManagedStatic<BitcodeErrorCategoryType> ErrorCategory;
+
+const std::error_category &BitcodeReader::BitcodeErrorCategory() {
+  return *ErrorCategory;
+}
+
+//===----------------------------------------------------------------------===//
+// External interface
+//===----------------------------------------------------------------------===//
+
+/// getLazyBitcodeModule - lazy function-at-a-time loading from a file.
+///
+static llvm::ErrorOr<llvm::Module *>
+getLazyBitcodeModuleImpl(std::unique_ptr<MemoryBuffer> &&Buffer,
+                         LLVMContext &Context, bool WillMaterializeAll,
+                         const DiagnosticHandlerFunction &DiagnosticHandler) {
+  Module *M = new Module(Buffer->getBufferIdentifier(), Context);
+  BitcodeReader *R =
+      new BitcodeReader(Buffer.get(), Context, DiagnosticHandler);
+  M->setMaterializer(R);
+
+  auto cleanupOnError = [&](std::error_code EC) {
+    R->releaseBuffer(); // Never take ownership on error.
+    delete M;  // Also deletes R.
+    return EC;
+  };
+
+  if (std::error_code EC = R->ParseBitcodeInto(M))
+    return cleanupOnError(EC);
+
+  Buffer.release(); // The BitcodeReader owns it now.
+  return M;
+}
+
+llvm::ErrorOr<Module *>
+llvm_2_7::getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
+                           LLVMContext &Context,
+                           const DiagnosticHandlerFunction &DiagnosticHandler) {
+  return getLazyBitcodeModuleImpl(std::move(Buffer), Context, false,
+                                  DiagnosticHandler);
+}
+
+/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
+/// If an error occurs, return null and fill in *ErrMsg if non-null.
+llvm::ErrorOr<llvm::Module *>
+llvm_2_7::parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
+                       const DiagnosticHandlerFunction &DiagnosticHandler) {
+  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
+  ErrorOr<Module *> ModuleOrErr = getLazyBitcodeModuleImpl(
+      std::move(Buf), Context, true, DiagnosticHandler);
+  if (!ModuleOrErr)
+    return ModuleOrErr;
+  Module *M = ModuleOrErr.get();
+  // Read in the entire module, and destroy the BitcodeReader.
+  if (std::error_code EC = M->materializeAll()) {
+    delete M;
+    return EC;
+  }
+
+  return M;
+}
+
+std::string
+llvm_2_7::getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context,
+                             DiagnosticHandlerFunction DiagnosticHandler) {
+  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
+  auto R = llvm::make_unique<BitcodeReader>(Buf.release(), Context,
+                                            DiagnosticHandler);
+  ErrorOr<std::string> Triple = R->parseTriple();
+  if (Triple.getError())
+    return "";
+  return Triple.get();
+}
diff --git a/libbcc/bcinfo/BitReader_2_7/CMakeLists.txt b/libbcc/bcinfo/BitReader_2_7/CMakeLists.txt
new file mode 100644
index 0000000..693d431
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_2_7/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_llvm_library(LLVMBitReader
+  BitReader.cpp
+  BitcodeReader.cpp
+  )
diff --git a/libbcc/bcinfo/BitReader_2_7/Makefile b/libbcc/bcinfo/BitReader_2_7/Makefile
new file mode 100644
index 0000000..59af8d5
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_2_7/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMBitReader
+BUILD_ARCHIVE = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/libbcc/bcinfo/BitReader_3_0/Android.mk b/libbcc/bcinfo/BitReader_3_0/Android.mk
new file mode 100644
index 0000000..dd6ce8d
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_3_0/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH:= $(call my-dir)
+
+LLVM_ROOT_PATH := external/llvm
+include $(LLVM_ROOT_PATH)/llvm.mk
+
+bitcode_reader_3_0_SRC_FILES := \
+  BitcodeReader.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libLLVMBitReader_3_0
+LOCAL_MODULE_HOST_OS := darwin linux windows
+
+LOCAL_SRC_FILES := $(bitcode_reader_3_0_SRC_FILES)
+LOCAL_CFLAGS += -D__HOST__
+
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libLLVMBitReader_3_0
+
+LOCAL_SRC_FILES := $(bitcode_reader_3_0_SRC_FILES)
+
+include $(LLVM_DEVICE_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/libbcc/bcinfo/BitReader_3_0/BitReader.cpp b/libbcc/bcinfo/BitReader_3_0/BitReader.cpp
new file mode 100644
index 0000000..15844c0
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_3_0/BitReader.cpp
@@ -0,0 +1,88 @@
+//===-- BitReader.cpp -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/BitReader.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <string>
+#include <cstring>
+
+using namespace llvm;
+
+/* Builds a module from the bitcode in the specified memory buffer, returning a
+   reference to the module via the OutModule parameter. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */
+LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf,
+                          LLVMModuleRef *OutModule, char **OutMessage) {
+  return LLVMParseBitcodeInContext(wrap(&getGlobalContext()), MemBuf, OutModule,
+                                   OutMessage);
+}
+
+LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef,
+                                   LLVMMemoryBufferRef MemBuf,
+                                   LLVMModuleRef *OutModule,
+                                   char **OutMessage) {
+  std::string Message;
+  
+  *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), *unwrap(ContextRef),
+                                     &Message));
+  if (!*OutModule) {
+    if (OutMessage)
+      *OutMessage = strdup(Message.c_str());
+    return 1;
+  }
+  
+  return 0;
+}
+
+/* Reads a module from the specified path, returning via the OutModule parameter
+   a module provider which performs lazy deserialization. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */ 
+LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef,
+                                       LLVMMemoryBufferRef MemBuf,
+                                       LLVMModuleRef *OutM,
+                                       char **OutMessage) {
+  std::string Message;
+  
+  *OutM = wrap(getLazyBitcodeModule(unwrap(MemBuf), *unwrap(ContextRef),
+                                    &Message));
+  if (!*OutM) {
+    if (OutMessage)
+      *OutMessage = strdup(Message.c_str());
+    return 1;
+  }
+  
+  return 0;
+
+}
+
+LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
+                              char **OutMessage) {
+  return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM,
+                                       OutMessage);
+}
+
+/* Deprecated: Use LLVMGetBitcodeModuleInContext instead. */
+LLVMBool LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef,
+                                               LLVMMemoryBufferRef MemBuf,
+                                               LLVMModuleProviderRef *OutMP,
+                                               char **OutMessage) {
+  return LLVMGetBitcodeModuleInContext(ContextRef, MemBuf,
+                                       reinterpret_cast<LLVMModuleRef*>(OutMP),
+                                       OutMessage);
+}
+
+/* Deprecated: Use LLVMGetBitcodeModule instead. */
+LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf,
+                                      LLVMModuleProviderRef *OutMP,
+                                      char **OutMessage) {
+  return LLVMGetBitcodeModuleProviderInContext(LLVMGetGlobalContext(), MemBuf,
+                                               OutMP, OutMessage);
+}
diff --git a/libbcc/bcinfo/BitReader_3_0/BitReader_3_0.h b/libbcc/bcinfo/BitReader_3_0/BitReader_3_0.h
new file mode 100644
index 0000000..d10f8b3
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_3_0/BitReader_3_0.h
@@ -0,0 +1,65 @@
+//===- BitReader_3_0.h - Internal BitcodeReader 3.0 impl --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BITREADER_3_0_H
+#define BITREADER_3_0_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/GVMaterializer.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Support/ErrorOr.h"
+#include <string>
+
+namespace llvm {
+  class LLVMContext;
+  class MemoryBuffer;
+  class MemoryBufferRef;
+  class Module;
+} // End llvm namespace
+
+namespace llvm_3_0 {
+
+using llvm::DiagnosticHandlerFunction;
+using llvm::LLVMContext;
+using llvm::MemoryBuffer;
+using llvm::MemoryBufferRef;
+
+
+  /// Read the header of the specified bitcode buffer and prepare for lazy
+  /// deserialization of function bodies.  If successful, this moves Buffer. On
+  /// error, this *does not* move Buffer.
+  llvm::ErrorOr<llvm::Module *>
+  getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
+                       LLVMContext &Context,
+                       const DiagnosticHandlerFunction &DiagnosticHandler = nullptr);
+
+  /// Read the header of the specified bitcode buffer and extract just the
+  /// triple information. If successful, this returns a string. On error, this
+  /// returns "".
+  std::string
+  getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context,
+                         DiagnosticHandlerFunction DiagnosticHandler = nullptr);
+
+  /// Read the specified bitcode file, returning the module.
+  llvm::ErrorOr<llvm::Module *>
+  parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
+                   const DiagnosticHandlerFunction &DiagnosticHandler = nullptr);
+} // End llvm_3_0 namespace
+
+#endif
diff --git a/libbcc/bcinfo/BitReader_3_0/BitcodeReader.cpp b/libbcc/bcinfo/BitReader_3_0/BitcodeReader.cpp
new file mode 100644
index 0000000..a768cf6
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_3_0/BitcodeReader.cpp
@@ -0,0 +1,3882 @@
+//===- BitcodeReader.cpp - Internal BitcodeReader implementation ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the BitcodeReader class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "BitReader_3_0.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/AutoUpgrade.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/GVMaterializer.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace llvm;
+using namespace llvm_3_0;
+
+#define FUNC_CODE_INST_UNWIND_2_7     14
+#define eh_exception_2_7             145
+#define eh_selector_2_7              149
+
+#define TYPE_BLOCK_ID_OLD_3_0         10
+#define TYPE_SYMTAB_BLOCK_ID_OLD_3_0  13
+#define TYPE_CODE_STRUCT_OLD_3_0      10
+
+namespace {
+  void FindExnAndSelIntrinsics(BasicBlock *BB, CallInst *&Exn,
+                                      CallInst *&Sel,
+                                      SmallPtrSet<BasicBlock*, 8> &Visited) {
+    if (!Visited.insert(BB).second) return;
+
+    for (BasicBlock::iterator
+           I = BB->begin(), E = BB->end(); I != E; ++I) {
+      if (CallInst *CI = dyn_cast<CallInst>(I)) {
+        switch (CI->getCalledFunction()->getIntrinsicID()) {
+        default: break;
+        case eh_exception_2_7:
+          assert(!Exn && "Found more than one eh.exception call!");
+          Exn = CI;
+          break;
+        case eh_selector_2_7:
+          assert(!Sel && "Found more than one eh.selector call!");
+          Sel = CI;
+          break;
+        }
+
+        if (Exn && Sel) return;
+      }
+    }
+
+    if (Exn && Sel) return;
+
+    for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
+      FindExnAndSelIntrinsics(*I, Exn, Sel, Visited);
+      if (Exn && Sel) return;
+    }
+  }
+
+
+
+  /// TransferClausesToLandingPadInst - Transfer the exception handling clauses
+  /// from the eh_selector call to the new landingpad instruction.
+  void TransferClausesToLandingPadInst(LandingPadInst *LPI,
+                                              CallInst *EHSel) {
+    LLVMContext &Context = LPI->getContext();
+    unsigned N = EHSel->getNumArgOperands();
+
+    for (unsigned i = N - 1; i > 1; --i) {
+      if (const ConstantInt *CI = dyn_cast<ConstantInt>(EHSel->getArgOperand(i))){
+        unsigned FilterLength = CI->getZExtValue();
+        unsigned FirstCatch = i + FilterLength + !FilterLength;
+        assert(FirstCatch <= N && "Invalid filter length");
+
+        if (FirstCatch < N)
+          for (unsigned j = FirstCatch; j < N; ++j) {
+            Value *Val = EHSel->getArgOperand(j);
+            if (!Val->hasName() || Val->getName() != "llvm.eh.catch.all.value") {
+              LPI->addClause(cast<Constant>(EHSel->getArgOperand(j)));
+            } else {
+              GlobalVariable *GV = cast<GlobalVariable>(Val);
+              LPI->addClause(GV->getInitializer());
+            }
+          }
+
+        if (!FilterLength) {
+          // Cleanup.
+          LPI->setCleanup(true);
+        } else {
+          // Filter.
+          SmallVector<Constant *, 4> TyInfo;
+          TyInfo.reserve(FilterLength - 1);
+          for (unsigned j = i + 1; j < FirstCatch; ++j)
+            TyInfo.push_back(cast<Constant>(EHSel->getArgOperand(j)));
+          ArrayType *AType =
+            ArrayType::get(!TyInfo.empty() ? TyInfo[0]->getType() :
+                           PointerType::getUnqual(Type::getInt8Ty(Context)),
+                           TyInfo.size());
+          LPI->addClause(ConstantArray::get(AType, TyInfo));
+        }
+
+        N = i;
+      }
+    }
+
+    if (N > 2)
+      for (unsigned j = 2; j < N; ++j) {
+        Value *Val = EHSel->getArgOperand(j);
+        if (!Val->hasName() || Val->getName() != "llvm.eh.catch.all.value") {
+          LPI->addClause(cast<Constant>(EHSel->getArgOperand(j)));
+        } else {
+          GlobalVariable *GV = cast<GlobalVariable>(Val);
+          LPI->addClause(GV->getInitializer());
+        }
+      }
+  }
+
+
+  /// This function upgrades the old pre-3.0 exception handling system to the new
+  /// one. N.B. This will be removed in 3.1.
+  void UpgradeExceptionHandling(Module *M) {
+    Function *EHException = M->getFunction("llvm.eh.exception");
+    Function *EHSelector = M->getFunction("llvm.eh.selector");
+    if (!EHException || !EHSelector)
+      return;
+
+    LLVMContext &Context = M->getContext();
+    Type *ExnTy = PointerType::getUnqual(Type::getInt8Ty(Context));
+    Type *SelTy = Type::getInt32Ty(Context);
+    Type *LPadSlotTy = StructType::get(ExnTy, SelTy, nullptr);
+
+    // This map links the invoke instruction with the eh.exception and eh.selector
+    // calls associated with it.
+    DenseMap<InvokeInst*, std::pair<Value*, Value*> > InvokeToIntrinsicsMap;
+    for (Module::iterator
+           I = M->begin(), E = M->end(); I != E; ++I) {
+      Function &F = *I;
+
+      for (Function::iterator
+             II = F.begin(), IE = F.end(); II != IE; ++II) {
+        BasicBlock *BB = &*II;
+        InvokeInst *Inst = dyn_cast<InvokeInst>(BB->getTerminator());
+        if (!Inst) continue;
+        BasicBlock *UnwindDest = Inst->getUnwindDest();
+        if (UnwindDest->isLandingPad()) continue; // Already converted.
+
+        SmallPtrSet<BasicBlock*, 8> Visited;
+        CallInst *Exn = 0;
+        CallInst *Sel = 0;
+        FindExnAndSelIntrinsics(UnwindDest, Exn, Sel, Visited);
+        assert(Exn && Sel && "Cannot find eh.exception and eh.selector calls!");
+        InvokeToIntrinsicsMap[Inst] = std::make_pair(Exn, Sel);
+      }
+    }
+
+    // This map stores the slots where the exception object and selector value are
+    // stored within a function.
+    DenseMap<Function*, std::pair<Value*, Value*> > FnToLPadSlotMap;
+    SmallPtrSet<Instruction*, 32> DeadInsts;
+    for (DenseMap<InvokeInst*, std::pair<Value*, Value*> >::iterator
+           I = InvokeToIntrinsicsMap.begin(), E = InvokeToIntrinsicsMap.end();
+         I != E; ++I) {
+      InvokeInst *Invoke = I->first;
+      BasicBlock *UnwindDest = Invoke->getUnwindDest();
+      Function *F = UnwindDest->getParent();
+      std::pair<Value*, Value*> EHIntrinsics = I->second;
+      CallInst *Exn = cast<CallInst>(EHIntrinsics.first);
+      CallInst *Sel = cast<CallInst>(EHIntrinsics.second);
+
+      // Store the exception object and selector value in the entry block.
+      Value *ExnSlot = 0;
+      Value *SelSlot = 0;
+      if (!FnToLPadSlotMap[F].first) {
+        BasicBlock *Entry = &F->front();
+        ExnSlot = new AllocaInst(ExnTy, "exn", Entry->getTerminator());
+        SelSlot = new AllocaInst(SelTy, "sel", Entry->getTerminator());
+        FnToLPadSlotMap[F] = std::make_pair(ExnSlot, SelSlot);
+      } else {
+        ExnSlot = FnToLPadSlotMap[F].first;
+        SelSlot = FnToLPadSlotMap[F].second;
+      }
+
+      if (!UnwindDest->getSinglePredecessor()) {
+        // The unwind destination doesn't have a single predecessor. Create an
+        // unwind destination which has only one predecessor.
+        BasicBlock *NewBB = BasicBlock::Create(Context, "new.lpad",
+                                               UnwindDest->getParent());
+        BranchInst::Create(UnwindDest, NewBB);
+        Invoke->setUnwindDest(NewBB);
+
+        // Fix up any PHIs in the original unwind destination block.
+        for (BasicBlock::iterator
+               II = UnwindDest->begin(); isa<PHINode>(II); ++II) {
+          PHINode *PN = cast<PHINode>(II);
+          int Idx = PN->getBasicBlockIndex(Invoke->getParent());
+          if (Idx == -1) continue;
+          PN->setIncomingBlock(Idx, NewBB);
+        }
+
+        UnwindDest = NewBB;
+      }
+
+      IRBuilder<> Builder(Context);
+      Builder.SetInsertPoint(UnwindDest, UnwindDest->getFirstInsertionPt());
+
+      LandingPadInst *LPI = Builder.CreateLandingPad(LPadSlotTy, 0);
+      Value *LPExn = Builder.CreateExtractValue(LPI, 0);
+      Value *LPSel = Builder.CreateExtractValue(LPI, 1);
+      Builder.CreateStore(LPExn, ExnSlot);
+      Builder.CreateStore(LPSel, SelSlot);
+
+      TransferClausesToLandingPadInst(LPI, Sel);
+
+      DeadInsts.insert(Exn);
+      DeadInsts.insert(Sel);
+    }
+
+    // Replace the old intrinsic calls with the values from the landingpad
+    // instruction(s). These values were stored in allocas for us to use here.
+    for (DenseMap<InvokeInst*, std::pair<Value*, Value*> >::iterator
+           I = InvokeToIntrinsicsMap.begin(), E = InvokeToIntrinsicsMap.end();
+         I != E; ++I) {
+      std::pair<Value*, Value*> EHIntrinsics = I->second;
+      CallInst *Exn = cast<CallInst>(EHIntrinsics.first);
+      CallInst *Sel = cast<CallInst>(EHIntrinsics.second);
+      BasicBlock *Parent = Exn->getParent();
+
+      std::pair<Value*,Value*> ExnSelSlots = FnToLPadSlotMap[Parent->getParent()];
+
+      IRBuilder<> Builder(Context);
+      Builder.SetInsertPoint(Parent, Exn->getIterator());
+      LoadInst *LPExn = Builder.CreateLoad(ExnSelSlots.first, "exn.load");
+      LoadInst *LPSel = Builder.CreateLoad(ExnSelSlots.second, "sel.load");
+
+      Exn->replaceAllUsesWith(LPExn);
+      Sel->replaceAllUsesWith(LPSel);
+    }
+
+    // Remove the dead instructions.
+    for (SmallPtrSet<Instruction*, 32>::iterator
+           I = DeadInsts.begin(), E = DeadInsts.end(); I != E; ++I) {
+      Instruction *Inst = *I;
+      Inst->eraseFromParent();
+    }
+
+    // Replace calls to "llvm.eh.resume" with the 'resume' instruction. Load the
+    // exception and selector values from the stored place.
+    Function *EHResume = M->getFunction("llvm.eh.resume");
+    if (!EHResume) return;
+
+    while (!EHResume->use_empty()) {
+      CallInst *Resume = cast<CallInst>(*EHResume->use_begin());
+      BasicBlock *BB = Resume->getParent();
+
+      IRBuilder<> Builder(Context);
+      Builder.SetInsertPoint(BB, Resume->getIterator());
+
+      Value *LPadVal =
+        Builder.CreateInsertValue(UndefValue::get(LPadSlotTy),
+                                  Resume->getArgOperand(0), 0, "lpad.val");
+      LPadVal = Builder.CreateInsertValue(LPadVal, Resume->getArgOperand(1),
+                                          1, "lpad.val");
+      Builder.CreateResume(LPadVal);
+
+      // Remove all instructions after the 'resume.'
+      BasicBlock::iterator I = Resume->getIterator();
+      while (I != BB->end()) {
+        Instruction *Inst = &*I++;
+        Inst->eraseFromParent();
+      }
+    }
+  }
+
+
+  void StripDebugInfoOfFunction(Module* M, const char* name) {
+    if (Function* FuncStart = M->getFunction(name)) {
+      while (!FuncStart->use_empty()) {
+        cast<CallInst>(*FuncStart->use_begin())->eraseFromParent();
+      }
+      FuncStart->eraseFromParent();
+    }
+  }
+
+  /// This function strips all debug info intrinsics, except for llvm.dbg.declare.
+  /// If an llvm.dbg.declare intrinsic is invalid, then this function simply
+  /// strips that use.
+  void CheckDebugInfoIntrinsics(Module *M) {
+    StripDebugInfoOfFunction(M, "llvm.dbg.func.start");
+    StripDebugInfoOfFunction(M, "llvm.dbg.stoppoint");
+    StripDebugInfoOfFunction(M, "llvm.dbg.region.start");
+    StripDebugInfoOfFunction(M, "llvm.dbg.region.end");
+
+    if (Function *Declare = M->getFunction("llvm.dbg.declare")) {
+      if (!Declare->use_empty()) {
+        DbgDeclareInst *DDI = cast<DbgDeclareInst>(*Declare->use_begin());
+        if (!isa<MDNode>(ValueAsMetadata::get(DDI->getArgOperand(0))) ||
+            !isa<MDNode>(ValueAsMetadata::get(DDI->getArgOperand(1)))) {
+          while (!Declare->use_empty()) {
+            CallInst *CI = cast<CallInst>(*Declare->use_begin());
+            CI->eraseFromParent();
+          }
+          Declare->eraseFromParent();
+        }
+      }
+    }
+  }
+
+
+//===----------------------------------------------------------------------===//
+//                          BitcodeReaderValueList Class
+//===----------------------------------------------------------------------===//
+
+class BitcodeReaderValueList {
+  std::vector<WeakVH> ValuePtrs;
+
+  /// ResolveConstants - As we resolve forward-referenced constants, we add
+  /// information about them to this vector.  This allows us to resolve them in
+  /// bulk instead of resolving each reference at a time.  See the code in
+  /// ResolveConstantForwardRefs for more information about this.
+  ///
+  /// The key of this vector is the placeholder constant, the value is the slot
+  /// number that holds the resolved value.
+  typedef std::vector<std::pair<Constant*, unsigned> > ResolveConstantsTy;
+  ResolveConstantsTy ResolveConstants;
+  LLVMContext &Context;
+public:
+  explicit BitcodeReaderValueList(LLVMContext &C) : Context(C) {}
+  ~BitcodeReaderValueList() {
+    assert(ResolveConstants.empty() && "Constants not resolved?");
+  }
+
+  // vector compatibility methods
+  unsigned size() const { return ValuePtrs.size(); }
+  void resize(unsigned N) { ValuePtrs.resize(N); }
+  void push_back(Value *V) {
+    ValuePtrs.push_back(V);
+  }
+
+  void clear() {
+    assert(ResolveConstants.empty() && "Constants not resolved?");
+    ValuePtrs.clear();
+  }
+
+  Value *operator[](unsigned i) const {
+    assert(i < ValuePtrs.size());
+    return ValuePtrs[i];
+  }
+
+  Value *back() const { return ValuePtrs.back(); }
+    void pop_back() { ValuePtrs.pop_back(); }
+  bool empty() const { return ValuePtrs.empty(); }
+  void shrinkTo(unsigned N) {
+    assert(N <= size() && "Invalid shrinkTo request!");
+    ValuePtrs.resize(N);
+  }
+
+  Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
+  Value *getValueFwdRef(unsigned Idx, Type *Ty);
+
+  void AssignValue(Value *V, unsigned Idx);
+
+  /// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+  /// resolves any forward references.
+  void ResolveConstantForwardRefs();
+};
+
+
+//===----------------------------------------------------------------------===//
+//                          BitcodeReaderMDValueList Class
+//===----------------------------------------------------------------------===//
+
+class BitcodeReaderMDValueList {
+  unsigned NumFwdRefs;
+  bool AnyFwdRefs;
+  std::vector<TrackingMDRef> MDValuePtrs;
+
+  LLVMContext &Context;
+public:
+  explicit BitcodeReaderMDValueList(LLVMContext &C)
+      : NumFwdRefs(0), AnyFwdRefs(false), Context(C) {}
+
+  // vector compatibility methods
+  unsigned size() const       { return MDValuePtrs.size(); }
+  void resize(unsigned N)     { MDValuePtrs.resize(N); }
+  void push_back(Metadata *MD) { MDValuePtrs.emplace_back(MD); }
+  void clear()                { MDValuePtrs.clear();  }
+  Metadata *back() const      { return MDValuePtrs.back(); }
+  void pop_back()             { MDValuePtrs.pop_back(); }
+  bool empty() const          { return MDValuePtrs.empty(); }
+
+  Metadata *operator[](unsigned i) const {
+    assert(i < MDValuePtrs.size());
+    return MDValuePtrs[i];
+  }
+
+  void shrinkTo(unsigned N) {
+    assert(N <= size() && "Invalid shrinkTo request!");
+    MDValuePtrs.resize(N);
+  }
+
+  Metadata *getValueFwdRef(unsigned Idx);
+  void AssignValue(Metadata *MD, unsigned Idx);
+  void tryToResolveCycles();
+};
+
+class BitcodeReader : public GVMaterializer {
+  LLVMContext &Context;
+  DiagnosticHandlerFunction DiagnosticHandler;
+  Module *TheModule;
+  std::unique_ptr<MemoryBuffer> Buffer;
+  std::unique_ptr<BitstreamReader> StreamFile;
+  BitstreamCursor Stream;
+  std::unique_ptr<DataStreamer> LazyStreamer;
+  uint64_t NextUnreadBit;
+  bool SeenValueSymbolTable;
+
+  std::vector<Type*> TypeList;
+  BitcodeReaderValueList ValueList;
+  BitcodeReaderMDValueList MDValueList;
+  SmallVector<Instruction *, 64> InstructionList;
+
+  std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
+  std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
+
+  /// MAttributes - The set of attributes by index.  Index zero in the
+  /// file is for null, and is thus not represented here.  As such all indices
+  /// are off by one.
+  std::vector<AttributeSet> MAttributes;
+
+  /// \brief The set of attribute groups.
+  std::map<unsigned, AttributeSet> MAttributeGroups;
+
+  /// FunctionBBs - While parsing a function body, this is a list of the basic
+  /// blocks for the function.
+  std::vector<BasicBlock*> FunctionBBs;
+
+  // When reading the module header, this list is populated with functions that
+  // have bodies later in the file.
+  std::vector<Function*> FunctionsWithBodies;
+
+  // When intrinsic functions are encountered which require upgrading they are
+  // stored here with their replacement function.
+  typedef std::vector<std::pair<Function*, Function*> > UpgradedIntrinsicMap;
+  UpgradedIntrinsicMap UpgradedIntrinsics;
+
+  // Map the bitcode's custom MDKind ID to the Module's MDKind ID.
+  DenseMap<unsigned, unsigned> MDKindMap;
+
+  // Several operations happen after the module header has been read, but
+  // before function bodies are processed. This keeps track of whether
+  // we've done this yet.
+  bool SeenFirstFunctionBody;
+
+  /// DeferredFunctionInfo - When function bodies are initially scanned, this
+  /// map contains info about where to find deferred function body in the
+  /// stream.
+  DenseMap<Function*, uint64_t> DeferredFunctionInfo;
+
+  /// BlockAddrFwdRefs - These are blockaddr references to basic blocks.  These
+  /// are resolved lazily when functions are loaded.
+  typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy;
+  DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs;
+
+  static const std::error_category &BitcodeErrorCategory();
+
+public:
+  std::error_code Error(BitcodeError E, const Twine &Message);
+  std::error_code Error(BitcodeError E);
+  std::error_code Error(const Twine &Message);
+
+  explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C,
+                         DiagnosticHandlerFunction DiagnosticHandler);
+  ~BitcodeReader() { FreeState(); }
+
+  void FreeState();
+
+  void releaseBuffer();
+
+  bool isDematerializable(const GlobalValue *GV) const;
+  std::error_code materialize(GlobalValue *GV) override;
+  std::error_code materializeModule() override;
+  std::vector<StructType *> getIdentifiedStructTypes() const override;
+  void dematerialize(GlobalValue *GV);
+
+  /// @brief Main interface to parsing a bitcode buffer.
+  /// @returns true if an error occurred.
+  std::error_code ParseBitcodeInto(Module *M);
+
+  /// @brief Cheap mechanism to just extract module triple
+  /// @returns true if an error occurred.
+  llvm::ErrorOr<std::string> parseTriple();
+
+  static uint64_t decodeSignRotatedValue(uint64_t V);
+
+  /// Materialize any deferred Metadata block.
+  std::error_code materializeMetadata() override;
+
+  void setStripDebugInfo() override;
+
+private:
+  std::vector<StructType *> IdentifiedStructTypes;
+  StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name);
+  StructType *createIdentifiedStructType(LLVMContext &Context);
+
+  Type *getTypeByID(unsigned ID);
+  Type *getTypeByIDOrNull(unsigned ID);
+  Value *getFnValueByID(unsigned ID, Type *Ty) {
+    if (Ty && Ty->isMetadataTy())
+      return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID));
+    return ValueList.getValueFwdRef(ID, Ty);
+  }
+  Metadata *getFnMetadataByID(unsigned ID) {
+    return MDValueList.getValueFwdRef(ID);
+  }
+  BasicBlock *getBasicBlock(unsigned ID) const {
+    if (ID >= FunctionBBs.size()) return nullptr; // Invalid ID
+    return FunctionBBs[ID];
+  }
+  AttributeSet getAttributes(unsigned i) const {
+    if (i-1 < MAttributes.size())
+      return MAttributes[i-1];
+    return AttributeSet();
+  }
+
+  /// getValueTypePair - Read a value/type pair out of the specified record from
+  /// slot 'Slot'.  Increment Slot past the number of slots used in the record.
+  /// Return true on failure.
+  bool getValueTypePair(SmallVectorImpl<uint64_t> &Record, unsigned &Slot,
+                        unsigned InstNum, Value *&ResVal) {
+    if (Slot == Record.size()) return true;
+    unsigned ValNo = (unsigned)Record[Slot++];
+    if (ValNo < InstNum) {
+      // If this is not a forward reference, just return the value we already
+      // have.
+      ResVal = getFnValueByID(ValNo, nullptr);
+      return ResVal == nullptr;
+    } else if (Slot == Record.size()) {
+      return true;
+    }
+
+    unsigned TypeNo = (unsigned)Record[Slot++];
+    ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo));
+    return ResVal == nullptr;
+  }
+  bool getValue(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
+                Type *Ty, Value *&ResVal) {
+    if (Slot == Record.size()) return true;
+    unsigned ValNo = (unsigned)Record[Slot++];
+    ResVal = getFnValueByID(ValNo, Ty);
+    return ResVal == 0;
+  }
+
+
+  std::error_code ParseModule(bool Resume);
+  std::error_code ParseAttributeBlock();
+  std::error_code ParseTypeTable();
+  std::error_code ParseOldTypeTable();         // FIXME: Remove in LLVM 3.1
+  std::error_code ParseTypeTableBody();
+
+  std::error_code ParseOldTypeSymbolTable();   // FIXME: Remove in LLVM 3.1
+  std::error_code ParseValueSymbolTable();
+  std::error_code ParseConstants();
+  std::error_code RememberAndSkipFunctionBody();
+  std::error_code ParseFunctionBody(Function *F);
+  std::error_code GlobalCleanup();
+  std::error_code ResolveGlobalAndAliasInits();
+  std::error_code ParseMetadata();
+  std::error_code ParseMetadataAttachment();
+  llvm::ErrorOr<std::string> parseModuleTriple();
+  std::error_code InitStream();
+  std::error_code InitStreamFromBuffer();
+  std::error_code InitLazyStream();
+};
+
+} // end anonymous namespace
+
+static std::error_code Error(const DiagnosticHandlerFunction &DiagnosticHandler,
+                             std::error_code EC, const Twine &Message) {
+  BitcodeDiagnosticInfo DI(EC, DS_Error, Message);
+  DiagnosticHandler(DI);
+  return EC;
+}
+
+static std::error_code Error(const DiagnosticHandlerFunction &DiagnosticHandler,
+                             std::error_code EC) {
+  return Error(DiagnosticHandler, EC, EC.message());
+}
+
+std::error_code BitcodeReader::Error(BitcodeError E, const Twine &Message) {
+  return ::Error(DiagnosticHandler, make_error_code(E), Message);
+}
+
+std::error_code BitcodeReader::Error(const Twine &Message) {
+  return ::Error(DiagnosticHandler,
+                 make_error_code(BitcodeError::CorruptedBitcode), Message);
+}
+
+std::error_code BitcodeReader::Error(BitcodeError E) {
+  return ::Error(DiagnosticHandler, make_error_code(E));
+}
+
+static DiagnosticHandlerFunction getDiagHandler(DiagnosticHandlerFunction F,
+                                                LLVMContext &C) {
+  if (F)
+    return F;
+  return [&C](const DiagnosticInfo &DI) { C.diagnose(DI); };
+}
+
+BitcodeReader::BitcodeReader(MemoryBuffer *buffer, LLVMContext &C,
+                             DiagnosticHandlerFunction DiagnosticHandler)
+    : Context(C), DiagnosticHandler(getDiagHandler(DiagnosticHandler, C)),
+      TheModule(nullptr), Buffer(buffer), LazyStreamer(nullptr),
+      NextUnreadBit(0), SeenValueSymbolTable(false), ValueList(C),
+      MDValueList(C), SeenFirstFunctionBody(false) {}
+
+
+void BitcodeReader::FreeState() {
+  Buffer = nullptr;
+  std::vector<Type*>().swap(TypeList);
+  ValueList.clear();
+  MDValueList.clear();
+
+  std::vector<AttributeSet>().swap(MAttributes);
+  std::vector<BasicBlock*>().swap(FunctionBBs);
+  std::vector<Function*>().swap(FunctionsWithBodies);
+  DeferredFunctionInfo.clear();
+  MDKindMap.clear();
+}
+
+//===----------------------------------------------------------------------===//
+//  Helper functions to implement forward reference resolution, etc.
+//===----------------------------------------------------------------------===//
+
+/// ConvertToString - Convert a string from a record into an std::string, return
+/// true on failure.
+template<typename StrTy>
+static bool ConvertToString(ArrayRef<uint64_t> Record, unsigned Idx,
+                            StrTy &Result) {
+  if (Idx > Record.size())
+    return true;
+
+  for (unsigned i = Idx, e = Record.size(); i != e; ++i)
+    Result += (char)Record[i];
+  return false;
+}
+
+static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) {
+  switch (Val) {
+  default: // Map unknown/new linkages to external
+  case 0:
+    return GlobalValue::ExternalLinkage;
+  case 1:
+    return GlobalValue::WeakAnyLinkage;
+  case 2:
+    return GlobalValue::AppendingLinkage;
+  case 3:
+    return GlobalValue::InternalLinkage;
+  case 4:
+    return GlobalValue::LinkOnceAnyLinkage;
+  case 5:
+    return GlobalValue::ExternalLinkage; // Obsolete DLLImportLinkage
+  case 6:
+    return GlobalValue::ExternalLinkage; // Obsolete DLLExportLinkage
+  case 7:
+    return GlobalValue::ExternalWeakLinkage;
+  case 8:
+    return GlobalValue::CommonLinkage;
+  case 9:
+    return GlobalValue::PrivateLinkage;
+  case 10:
+    return GlobalValue::WeakODRLinkage;
+  case 11:
+    return GlobalValue::LinkOnceODRLinkage;
+  case 12:
+    return GlobalValue::AvailableExternallyLinkage;
+  case 13:
+    return GlobalValue::PrivateLinkage; // Obsolete LinkerPrivateLinkage
+  case 14:
+    return GlobalValue::ExternalWeakLinkage; // Obsolete LinkerPrivateWeakLinkage
+  //ANDROID: convert LinkOnceODRAutoHideLinkage -> LinkOnceODRLinkage
+  case 15:
+    return GlobalValue::LinkOnceODRLinkage;
+  }
+}
+
+static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) {
+  switch (Val) {
+  default: // Map unknown visibilities to default.
+  case 0: return GlobalValue::DefaultVisibility;
+  case 1: return GlobalValue::HiddenVisibility;
+  case 2: return GlobalValue::ProtectedVisibility;
+  }
+}
+
+static GlobalVariable::ThreadLocalMode GetDecodedThreadLocalMode(unsigned Val) {
+  switch (Val) {
+    case 0: return GlobalVariable::NotThreadLocal;
+    default: // Map unknown non-zero value to general dynamic.
+    case 1: return GlobalVariable::GeneralDynamicTLSModel;
+    case 2: return GlobalVariable::LocalDynamicTLSModel;
+    case 3: return GlobalVariable::InitialExecTLSModel;
+    case 4: return GlobalVariable::LocalExecTLSModel;
+  }
+}
+
+static int GetDecodedCastOpcode(unsigned Val) {
+  switch (Val) {
+  default: return -1;
+  case bitc::CAST_TRUNC   : return Instruction::Trunc;
+  case bitc::CAST_ZEXT    : return Instruction::ZExt;
+  case bitc::CAST_SEXT    : return Instruction::SExt;
+  case bitc::CAST_FPTOUI  : return Instruction::FPToUI;
+  case bitc::CAST_FPTOSI  : return Instruction::FPToSI;
+  case bitc::CAST_UITOFP  : return Instruction::UIToFP;
+  case bitc::CAST_SITOFP  : return Instruction::SIToFP;
+  case bitc::CAST_FPTRUNC : return Instruction::FPTrunc;
+  case bitc::CAST_FPEXT   : return Instruction::FPExt;
+  case bitc::CAST_PTRTOINT: return Instruction::PtrToInt;
+  case bitc::CAST_INTTOPTR: return Instruction::IntToPtr;
+  case bitc::CAST_BITCAST : return Instruction::BitCast;
+  }
+}
+static int GetDecodedBinaryOpcode(unsigned Val, Type *Ty) {
+  switch (Val) {
+  default: return -1;
+  case bitc::BINOP_ADD:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FAdd : Instruction::Add;
+  case bitc::BINOP_SUB:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FSub : Instruction::Sub;
+  case bitc::BINOP_MUL:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FMul : Instruction::Mul;
+  case bitc::BINOP_UDIV: return Instruction::UDiv;
+  case bitc::BINOP_SDIV:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FDiv : Instruction::SDiv;
+  case bitc::BINOP_UREM: return Instruction::URem;
+  case bitc::BINOP_SREM:
+    return Ty->isFPOrFPVectorTy() ? Instruction::FRem : Instruction::SRem;
+  case bitc::BINOP_SHL:  return Instruction::Shl;
+  case bitc::BINOP_LSHR: return Instruction::LShr;
+  case bitc::BINOP_ASHR: return Instruction::AShr;
+  case bitc::BINOP_AND:  return Instruction::And;
+  case bitc::BINOP_OR:   return Instruction::Or;
+  case bitc::BINOP_XOR:  return Instruction::Xor;
+  }
+}
+
+static AtomicRMWInst::BinOp GetDecodedRMWOperation(unsigned Val) {
+  switch (Val) {
+  default: return AtomicRMWInst::BAD_BINOP;
+  case bitc::RMW_XCHG: return AtomicRMWInst::Xchg;
+  case bitc::RMW_ADD: return AtomicRMWInst::Add;
+  case bitc::RMW_SUB: return AtomicRMWInst::Sub;
+  case bitc::RMW_AND: return AtomicRMWInst::And;
+  case bitc::RMW_NAND: return AtomicRMWInst::Nand;
+  case bitc::RMW_OR: return AtomicRMWInst::Or;
+  case bitc::RMW_XOR: return AtomicRMWInst::Xor;
+  case bitc::RMW_MAX: return AtomicRMWInst::Max;
+  case bitc::RMW_MIN: return AtomicRMWInst::Min;
+  case bitc::RMW_UMAX: return AtomicRMWInst::UMax;
+  case bitc::RMW_UMIN: return AtomicRMWInst::UMin;
+  }
+}
+
+static AtomicOrdering GetDecodedOrdering(unsigned Val) {
+  switch (Val) {
+  case bitc::ORDERING_NOTATOMIC: return NotAtomic;
+  case bitc::ORDERING_UNORDERED: return Unordered;
+  case bitc::ORDERING_MONOTONIC: return Monotonic;
+  case bitc::ORDERING_ACQUIRE: return Acquire;
+  case bitc::ORDERING_RELEASE: return Release;
+  case bitc::ORDERING_ACQREL: return AcquireRelease;
+  default: // Map unknown orderings to sequentially-consistent.
+  case bitc::ORDERING_SEQCST: return SequentiallyConsistent;
+  }
+}
+
+static SynchronizationScope GetDecodedSynchScope(unsigned Val) {
+  switch (Val) {
+  case bitc::SYNCHSCOPE_SINGLETHREAD: return SingleThread;
+  default: // Map unknown scopes to cross-thread.
+  case bitc::SYNCHSCOPE_CROSSTHREAD: return CrossThread;
+  }
+}
+
+namespace llvm {
+namespace {
+  /// @brief A class for maintaining the slot number definition
+  /// as a placeholder for the actual definition for forward constants defs.
+  class ConstantPlaceHolder : public ConstantExpr {
+    void operator=(const ConstantPlaceHolder &) = delete;
+  public:
+    // allocate space for exactly one operand
+    void *operator new(size_t s) {
+      return User::operator new(s, 1);
+    }
+    explicit ConstantPlaceHolder(Type *Ty, LLVMContext& Context)
+      : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
+      Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
+    }
+
+    /// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
+    static bool classof(const Value *V) {
+      return isa<ConstantExpr>(V) &&
+             cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
+    }
+
+
+    /// Provide fast operand accessors
+    DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+  };
+}
+
+// FIXME: can we inherit this from ConstantExpr?
+template <>
+struct OperandTraits<ConstantPlaceHolder> :
+  public FixedNumOperandTraits<ConstantPlaceHolder, 1> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
+}
+
+
+void BitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) {
+  if (Idx == size()) {
+    push_back(V);
+    return;
+  }
+
+  if (Idx >= size())
+    resize(Idx+1);
+
+  WeakVH &OldV = ValuePtrs[Idx];
+  if (!OldV) {
+    OldV = V;
+    return;
+  }
+
+  // Handle constants and non-constants (e.g. instrs) differently for
+  // efficiency.
+  if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
+    ResolveConstants.push_back(std::make_pair(PHC, Idx));
+    OldV = V;
+  } else {
+    // If there was a forward reference to this value, replace it.
+    Value *PrevVal = OldV;
+    OldV->replaceAllUsesWith(V);
+    delete PrevVal;
+  }
+}
+
+
+Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
+                                                    Type *Ty) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Value *V = ValuePtrs[Idx]) {
+    assert(Ty == V->getType() && "Type mismatch in constant table!");
+    return cast<Constant>(V);
+  }
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  Constant *C = new ConstantPlaceHolder(Ty, Context);
+  ValuePtrs[Idx] = C;
+  return C;
+}
+
+Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Value *V = ValuePtrs[Idx]) {
+    assert((!Ty || Ty == V->getType()) && "Type mismatch in value table!");
+    return V;
+  }
+
+  // No type specified, must be invalid reference.
+  if (!Ty) return nullptr;
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  Value *V = new Argument(Ty);
+  ValuePtrs[Idx] = V;
+  return V;
+}
+
+/// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+/// resolves any forward references.  The idea behind this is that we sometimes
+/// get constants (such as large arrays) which reference *many* forward ref
+/// constants.  Replacing each of these causes a lot of thrashing when
+/// building/reuniquing the constant.  Instead of doing this, we look at all the
+/// uses and rewrite all the place holders at once for any constant that uses
+/// a placeholder.
+void BitcodeReaderValueList::ResolveConstantForwardRefs() {
+  // Sort the values by-pointer so that they are efficient to look up with a
+  // binary search.
+  std::sort(ResolveConstants.begin(), ResolveConstants.end());
+
+  SmallVector<Constant*, 64> NewOps;
+
+  while (!ResolveConstants.empty()) {
+    Value *RealVal = operator[](ResolveConstants.back().second);
+    Constant *Placeholder = ResolveConstants.back().first;
+    ResolveConstants.pop_back();
+
+    // Loop over all users of the placeholder, updating them to reference the
+    // new value.  If they reference more than one placeholder, update them all
+    // at once.
+    while (!Placeholder->use_empty()) {
+      auto UI = Placeholder->user_begin();
+      User *U = *UI;
+
+      // If the using object isn't uniqued, just update the operands.  This
+      // handles instructions and initializers for global variables.
+      if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
+        UI.getUse().set(RealVal);
+        continue;
+      }
+
+      // Otherwise, we have a constant that uses the placeholder.  Replace that
+      // constant with a new constant that has *all* placeholder uses updated.
+      Constant *UserC = cast<Constant>(U);
+      for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end();
+           I != E; ++I) {
+        Value *NewOp;
+        if (!isa<ConstantPlaceHolder>(*I)) {
+          // Not a placeholder reference.
+          NewOp = *I;
+        } else if (*I == Placeholder) {
+          // Common case is that it just references this one placeholder.
+          NewOp = RealVal;
+        } else {
+          // Otherwise, look up the placeholder in ResolveConstants.
+          ResolveConstantsTy::iterator It =
+            std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(),
+                             std::pair<Constant*, unsigned>(cast<Constant>(*I),
+                                                            0));
+          assert(It != ResolveConstants.end() && It->first == *I);
+          NewOp = operator[](It->second);
+        }
+
+        NewOps.push_back(cast<Constant>(NewOp));
+      }
+
+      // Make the new constant.
+      Constant *NewC;
+      if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
+        NewC = ConstantArray::get(UserCA->getType(), NewOps);
+      } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
+        NewC = ConstantStruct::get(UserCS->getType(), NewOps);
+      } else if (isa<ConstantVector>(UserC)) {
+        NewC = ConstantVector::get(NewOps);
+      } else {
+        assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
+        NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
+      }
+
+      UserC->replaceAllUsesWith(NewC);
+      UserC->destroyConstant();
+      NewOps.clear();
+    }
+
+    // Update all ValueHandles, they should be the only users at this point.
+    Placeholder->replaceAllUsesWith(RealVal);
+    delete Placeholder;
+  }
+}
+
+void BitcodeReaderMDValueList::AssignValue(Metadata *MD, unsigned Idx) {
+  if (Idx == size()) {
+    push_back(MD);
+    return;
+  }
+
+  if (Idx >= size())
+    resize(Idx+1);
+
+  TrackingMDRef &OldMD = MDValuePtrs[Idx];
+  if (!OldMD) {
+    OldMD.reset(MD);
+    return;
+  }
+
+  // If there was a forward reference to this value, replace it.
+  TempMDTuple PrevMD(cast<MDTuple>(OldMD.get()));
+  PrevMD->replaceAllUsesWith(MD);
+  --NumFwdRefs;
+}
+
+Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
+  if (Idx >= size())
+    resize(Idx + 1);
+
+  if (Metadata *MD = MDValuePtrs[Idx])
+    return MD;
+
+  // Create and return a placeholder, which will later be RAUW'd.
+  AnyFwdRefs = true;
+  ++NumFwdRefs;
+  Metadata *MD = MDNode::getTemporary(Context, None).release();
+  MDValuePtrs[Idx].reset(MD);
+  return MD;
+}
+
+void BitcodeReaderMDValueList::tryToResolveCycles() {
+  if (!AnyFwdRefs)
+    // Nothing to do.
+    return;
+
+  if (NumFwdRefs)
+    // Still forward references... can't resolve cycles.
+    return;
+
+  // Resolve any cycles.
+  for (auto &MD : MDValuePtrs) {
+    auto *N = dyn_cast_or_null<MDNode>(MD);
+    if (!N)
+      continue;
+
+    assert(!N->isTemporary() && "Unexpected forward reference");
+    N->resolveCycles();
+  }
+}
+
+Type *BitcodeReader::getTypeByID(unsigned ID) {
+  // The type table size is always specified correctly.
+  if (ID >= TypeList.size())
+    return nullptr;
+
+  if (Type *Ty = TypeList[ID])
+    return Ty;
+
+  // If we have a forward reference, the only possible case is when it is to a
+  // named struct.  Just create a placeholder for now.
+  return TypeList[ID] = createIdentifiedStructType(Context);
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context,
+                                                      StringRef Name) {
+  auto *Ret = StructType::create(Context, Name);
+  IdentifiedStructTypes.push_back(Ret);
+  return Ret;
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context) {
+  auto *Ret = StructType::create(Context);
+  IdentifiedStructTypes.push_back(Ret);
+  return Ret;
+}
+
+
+/// FIXME: Remove in LLVM 3.1, only used by ParseOldTypeTable.
+Type *BitcodeReader::getTypeByIDOrNull(unsigned ID) {
+  if (ID >= TypeList.size())
+    TypeList.resize(ID+1);
+
+  return TypeList[ID];
+}
+
+//===----------------------------------------------------------------------===//
+//  Functions for parsing blocks from the bitcode file
+//===----------------------------------------------------------------------===//
+
+
+/// \brief This fills an AttrBuilder object with the LLVM attributes that have
+/// been decoded from the given integer. This function must stay in sync with
+/// 'encodeLLVMAttributesForBitcode'.
+static void decodeLLVMAttributesForBitcode(AttrBuilder &B,
+                                           uint64_t EncodedAttrs) {
+  // FIXME: Remove in 4.0.
+
+  // The alignment is stored as a 16-bit raw value from bits 31--16.  We shift
+  // the bits above 31 down by 11 bits.
+  unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
+  assert((!Alignment || isPowerOf2_32(Alignment)) &&
+         "Alignment must be a power of two.");
+
+  if (Alignment)
+    B.addAlignmentAttr(Alignment);
+  B.addRawValue(((EncodedAttrs & (0xfffffULL << 32)) >> 11) |
+                (EncodedAttrs & 0xffff));
+}
+
+std::error_code BitcodeReader::ParseAttributeBlock() {
+  if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
+    return Error("Invalid record");
+
+  if (!MAttributes.empty())
+    return Error("Invalid multiple blocks");
+
+  SmallVector<uint64_t, 64> Record;
+
+  SmallVector<AttributeSet, 8> Attrs;
+
+  // Read all the records.
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::PARAMATTR_CODE_ENTRY_OLD: { // ENTRY: [paramidx0, attr0, ...]
+      // FIXME: Remove in 4.0.
+      if (Record.size() & 1)
+        return Error("Invalid record");
+
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        AttrBuilder B;
+        decodeLLVMAttributesForBitcode(B, Record[i+1]);
+        Attrs.push_back(AttributeSet::get(Context, Record[i], B));
+      }
+
+      MAttributes.push_back(AttributeSet::get(Context, Attrs));
+      Attrs.clear();
+      break;
+    }
+    case bitc::PARAMATTR_CODE_ENTRY: { // ENTRY: [attrgrp0, attrgrp1, ...]
+      for (unsigned i = 0, e = Record.size(); i != e; ++i)
+        Attrs.push_back(MAttributeGroups[Record[i]]);
+
+      MAttributes.push_back(AttributeSet::get(Context, Attrs));
+      Attrs.clear();
+      break;
+    }
+    }
+  }
+}
+
+
+std::error_code BitcodeReader::ParseTypeTable() {
+  if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
+    return Error("Invalid record");
+
+  return ParseTypeTableBody();
+}
+
+std::error_code BitcodeReader::ParseTypeTableBody() {
+  if (!TypeList.empty())
+    return Error("Invalid multiple blocks");
+
+  SmallVector<uint64_t, 64> Record;
+  unsigned NumRecords = 0;
+
+  SmallString<64> TypeName;
+
+  // Read all the records for this type table.
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      if (NumRecords != TypeList.size())
+        return Error("Malformed block");
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    Record.clear();
+    Type *ResultTy = nullptr;
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default:
+      return Error("Invalid value");
+    case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+      // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+      // type list.  This allows us to reserve space.
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      TypeList.resize(Record[0]);
+      continue;
+    case bitc::TYPE_CODE_VOID:      // VOID
+      ResultTy = Type::getVoidTy(Context);
+      break;
+    case bitc::TYPE_CODE_HALF:     // HALF
+      ResultTy = Type::getHalfTy(Context);
+      break;
+    case bitc::TYPE_CODE_FLOAT:     // FLOAT
+      ResultTy = Type::getFloatTy(Context);
+      break;
+    case bitc::TYPE_CODE_DOUBLE:    // DOUBLE
+      ResultTy = Type::getDoubleTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_FP80:  // X86_FP80
+      ResultTy = Type::getX86_FP80Ty(Context);
+      break;
+    case bitc::TYPE_CODE_FP128:     // FP128
+      ResultTy = Type::getFP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+      ResultTy = Type::getPPC_FP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_LABEL:     // LABEL
+      ResultTy = Type::getLabelTy(Context);
+      break;
+    case bitc::TYPE_CODE_METADATA:  // METADATA
+      ResultTy = Type::getMetadataTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_MMX:   // X86_MMX
+      ResultTy = Type::getX86_MMXTy(Context);
+      break;
+    case bitc::TYPE_CODE_INTEGER:   // INTEGER: [width]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+
+      ResultTy = IntegerType::get(Context, Record[0]);
+      break;
+    case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+                                    //          [pointee type, address space]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      unsigned AddressSpace = 0;
+      if (Record.size() == 2)
+        AddressSpace = Record[1];
+      ResultTy = getTypeByID(Record[0]);
+      if (!ResultTy)
+        return Error("Invalid type");
+      ResultTy = PointerType::get(ResultTy, AddressSpace);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
+      // FIXME: attrid is dead, remove it in LLVM 4.0
+      // FUNCTION: [vararg, attrid, retty, paramty x N]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      SmallVector<Type*, 8> ArgTys;
+      for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          ArgTys.push_back(T);
+        else
+          break;
+      }
+
+      ResultTy = getTypeByID(Record[2]);
+      if (!ResultTy || ArgTys.size() < Record.size()-3)
+        return Error("Invalid type");
+
+      ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION: {
+      // FUNCTION: [vararg, retty, paramty x N]
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      SmallVector<Type*, 8> ArgTys;
+      for (unsigned i = 2, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          ArgTys.push_back(T);
+        else
+          break;
+      }
+
+      ResultTy = getTypeByID(Record[1]);
+      if (!ResultTy || ArgTys.size() < Record.size()-2)
+        return Error("Invalid type");
+
+      ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_STRUCT_ANON: {  // STRUCT: [ispacked, eltty x N]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      SmallVector<Type*, 8> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          EltTys.push_back(T);
+        else
+          break;
+      }
+      if (EltTys.size() != Record.size()-1)
+        return Error("Invalid type");
+      ResultTy = StructType::get(Context, EltTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_STRUCT_NAME:   // STRUCT_NAME: [strchr x N]
+      if (ConvertToString(Record, 0, TypeName))
+        return Error("Invalid record");
+      continue;
+
+    case bitc::TYPE_CODE_STRUCT_NAMED: { // STRUCT: [ispacked, eltty x N]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+
+      if (NumRecords >= TypeList.size())
+        return Error("Invalid TYPE table");
+
+      // Check to see if this was forward referenced, if so fill in the temp.
+      StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+      if (Res) {
+        Res->setName(TypeName);
+        TypeList[NumRecords] = nullptr;
+      } else  // Otherwise, create a new struct.
+        Res = createIdentifiedStructType(Context, TypeName);
+      TypeName.clear();
+
+      SmallVector<Type*, 8> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *T = getTypeByID(Record[i]))
+          EltTys.push_back(T);
+        else
+          break;
+      }
+      if (EltTys.size() != Record.size()-1)
+        return Error("Invalid record");
+      Res->setBody(EltTys, Record[0]);
+      ResultTy = Res;
+      break;
+    }
+    case bitc::TYPE_CODE_OPAQUE: {       // OPAQUE: []
+      if (Record.size() != 1)
+        return Error("Invalid record");
+
+      if (NumRecords >= TypeList.size())
+        return Error("Invalid TYPE table");
+
+      // Check to see if this was forward referenced, if so fill in the temp.
+      StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+      if (Res) {
+        Res->setName(TypeName);
+        TypeList[NumRecords] = nullptr;
+      } else  // Otherwise, create a new struct with no body.
+        Res = createIdentifiedStructType(Context, TypeName);
+      TypeName.clear();
+      ResultTy = Res;
+      break;
+    }
+    case bitc::TYPE_CODE_ARRAY:     // ARRAY: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      if ((ResultTy = getTypeByID(Record[1])))
+        ResultTy = ArrayType::get(ResultTy, Record[0]);
+      else
+        return Error("Invalid type");
+      break;
+    case bitc::TYPE_CODE_VECTOR:    // VECTOR: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      if ((ResultTy = getTypeByID(Record[1])))
+        ResultTy = VectorType::get(ResultTy, Record[0]);
+      else
+        return Error("Invalid type");
+      break;
+    }
+
+    if (NumRecords >= TypeList.size())
+      return Error("Invalid TYPE table");
+    assert(ResultTy && "Didn't read a type?");
+    assert(!TypeList[NumRecords] && "Already read type?");
+    TypeList[NumRecords++] = ResultTy;
+  }
+}
+
+// FIXME: Remove in LLVM 3.1
+std::error_code BitcodeReader::ParseOldTypeTable() {
+  if (Stream.EnterSubBlock(TYPE_BLOCK_ID_OLD_3_0))
+    return Error("Malformed block");
+
+  if (!TypeList.empty())
+    return Error("Invalid TYPE table");
+
+
+  // While horrible, we have no good ordering of types in the bc file.  Just
+  // iteratively parse types out of the bc file in multiple passes until we get
+  // them all.  Do this by saving a cursor for the start of the type block.
+  BitstreamCursor StartOfTypeBlockCursor(Stream);
+
+  unsigned NumTypesRead = 0;
+
+  SmallVector<uint64_t, 64> Record;
+RestartScan:
+  unsigned NextTypeID = 0;
+  bool ReadAnyTypes = false;
+
+  // Read all the records for this type table.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (NextTypeID != TypeList.size())
+        return Error("Invalid TYPE table");
+
+      // If we haven't read all of the types yet, iterate again.
+      if (NumTypesRead != TypeList.size()) {
+        // If we didn't successfully read any types in this pass, then we must
+        // have an unhandled forward reference.
+        if (!ReadAnyTypes)
+          return Error("Invalid TYPE table");
+
+        Stream = StartOfTypeBlockCursor;
+        goto RestartScan;
+      }
+
+      if (Stream.ReadBlockEnd())
+        return Error("Invalid TYPE table");
+      return std::error_code();
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Type *ResultTy = nullptr;
+    switch (Stream.readRecord(Code, Record)) {
+    default: return Error("Invalid TYPE table");
+    case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+      // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+      // type list.  This allows us to reserve space.
+      if (Record.size() < 1)
+        return Error("Invalid TYPE table");
+      TypeList.resize(Record[0]);
+      continue;
+    case bitc::TYPE_CODE_VOID:      // VOID
+      ResultTy = Type::getVoidTy(Context);
+      break;
+    case bitc::TYPE_CODE_FLOAT:     // FLOAT
+      ResultTy = Type::getFloatTy(Context);
+      break;
+    case bitc::TYPE_CODE_DOUBLE:    // DOUBLE
+      ResultTy = Type::getDoubleTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_FP80:  // X86_FP80
+      ResultTy = Type::getX86_FP80Ty(Context);
+      break;
+    case bitc::TYPE_CODE_FP128:     // FP128
+      ResultTy = Type::getFP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+      ResultTy = Type::getPPC_FP128Ty(Context);
+      break;
+    case bitc::TYPE_CODE_LABEL:     // LABEL
+      ResultTy = Type::getLabelTy(Context);
+      break;
+    case bitc::TYPE_CODE_METADATA:  // METADATA
+      ResultTy = Type::getMetadataTy(Context);
+      break;
+    case bitc::TYPE_CODE_X86_MMX:   // X86_MMX
+      ResultTy = Type::getX86_MMXTy(Context);
+      break;
+    case bitc::TYPE_CODE_INTEGER:   // INTEGER: [width]
+      if (Record.size() < 1)
+        return Error("Invalid TYPE table");
+      ResultTy = IntegerType::get(Context, Record[0]);
+      break;
+    case bitc::TYPE_CODE_OPAQUE:    // OPAQUE
+      if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0)
+        ResultTy = StructType::create(Context, "");
+      break;
+    case TYPE_CODE_STRUCT_OLD_3_0: {// STRUCT_OLD
+      if (NextTypeID >= TypeList.size()) break;
+      // If we already read it, don't reprocess.
+      if (TypeList[NextTypeID] &&
+          !cast<StructType>(TypeList[NextTypeID])->isOpaque())
+        break;
+
+      // Set a type.
+      if (TypeList[NextTypeID] == 0)
+        TypeList[NextTypeID] = StructType::create(Context, "");
+
+      std::vector<Type*> EltTys;
+      for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          EltTys.push_back(Elt);
+        else
+          break;
+      }
+
+      if (EltTys.size() != Record.size()-1)
+        break;      // Not all elements are ready.
+
+      cast<StructType>(TypeList[NextTypeID])->setBody(EltTys, Record[0]);
+      ResultTy = TypeList[NextTypeID];
+      TypeList[NextTypeID] = 0;
+      break;
+    }
+    case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+      //          [pointee type, address space]
+      if (Record.size() < 1)
+        return Error("Invalid TYPE table");
+      unsigned AddressSpace = 0;
+      if (Record.size() == 2)
+        AddressSpace = Record[1];
+      if ((ResultTy = getTypeByIDOrNull(Record[0])))
+        ResultTy = PointerType::get(ResultTy, AddressSpace);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION_OLD: {
+      // FIXME: attrid is dead, remove it in LLVM 3.0
+      // FUNCTION: [vararg, attrid, retty, paramty x N]
+      if (Record.size() < 3)
+        return Error("Invalid TYPE table");
+      std::vector<Type*> ArgTys;
+      for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          ArgTys.push_back(Elt);
+        else
+          break;
+      }
+      if (ArgTys.size()+3 != Record.size())
+        break;  // Something was null.
+      if ((ResultTy = getTypeByIDOrNull(Record[2])))
+        ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_FUNCTION: {
+      // FUNCTION: [vararg, retty, paramty x N]
+      if (Record.size() < 2)
+        return Error("Invalid TYPE table");
+      std::vector<Type*> ArgTys;
+      for (unsigned i = 2, e = Record.size(); i != e; ++i) {
+        if (Type *Elt = getTypeByIDOrNull(Record[i]))
+          ArgTys.push_back(Elt);
+        else
+          break;
+      }
+      if (ArgTys.size()+2 != Record.size())
+        break;  // Something was null.
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+      break;
+    }
+    case bitc::TYPE_CODE_ARRAY:     // ARRAY: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid TYPE table");
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = ArrayType::get(ResultTy, Record[0]);
+      break;
+    case bitc::TYPE_CODE_VECTOR:    // VECTOR: [numelts, eltty]
+      if (Record.size() < 2)
+        return Error("Invalid TYPE table");
+      if ((ResultTy = getTypeByIDOrNull(Record[1])))
+        ResultTy = VectorType::get(ResultTy, Record[0]);
+      break;
+    }
+
+    if (NextTypeID >= TypeList.size())
+      return Error("Invalid TYPE table");
+
+    if (ResultTy && TypeList[NextTypeID] == 0) {
+      ++NumTypesRead;
+      ReadAnyTypes = true;
+
+      TypeList[NextTypeID] = ResultTy;
+    }
+
+    ++NextTypeID;
+  }
+}
+
+
+std::error_code BitcodeReader::ParseOldTypeSymbolTable() {
+  if (Stream.EnterSubBlock(TYPE_SYMTAB_BLOCK_ID_OLD_3_0))
+    return Error("Malformed block");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this type table.
+  std::string TypeName;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      return std::error_code();
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.readRecord(Code, Record)) {
+    default:  // Default behavior: unknown type.
+      break;
+    case bitc::TST_CODE_ENTRY:    // TST_ENTRY: [typeid, namechar x N]
+      if (ConvertToString(Record, 1, TypeName))
+        return Error("Invalid record");
+      unsigned TypeID = Record[0];
+      if (TypeID >= TypeList.size())
+        return Error("Invalid record");
+
+      // Only apply the type name to a struct type with no name.
+      if (StructType *STy = dyn_cast<StructType>(TypeList[TypeID]))
+        if (!STy->isLiteral() && !STy->hasName())
+          STy->setName(TypeName);
+      TypeName.clear();
+      break;
+    }
+  }
+}
+
+std::error_code BitcodeReader::ParseValueSymbolTable() {
+  if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this value table.
+  SmallString<128> ValueName;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      return std::error_code();
+    }
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    switch (Stream.readRecord(Code, Record)) {
+    default:  // Default behavior: unknown type.
+      break;
+    case bitc::VST_CODE_ENTRY: {  // VST_ENTRY: [valueid, namechar x N]
+      if (ConvertToString(Record, 1, ValueName))
+        return Error("Invalid record");
+      unsigned ValueID = Record[0];
+      if (ValueID >= ValueList.size())
+        return Error("Invalid record");
+      Value *V = ValueList[ValueID];
+
+      V->setName(StringRef(ValueName.data(), ValueName.size()));
+      ValueName.clear();
+      break;
+    }
+    case bitc::VST_CODE_BBENTRY: {
+      if (ConvertToString(Record, 1, ValueName))
+        return Error("Invalid record");
+      BasicBlock *BB = getBasicBlock(Record[0]);
+      if (!BB)
+        return Error("Invalid record");
+
+      BB->setName(StringRef(ValueName.data(), ValueName.size()));
+      ValueName.clear();
+      break;
+    }
+    }
+  }
+}
+
+std::error_code BitcodeReader::ParseMetadata() {
+  unsigned NextMDValueNo = MDValueList.size();
+
+  if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records.
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      return std::error_code();
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    bool IsFunctionLocal = false;
+    // Read a record.
+    Record.clear();
+    Code = Stream.readRecord(Code, Record);
+    switch (Code) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::METADATA_NAME: {
+      // Read name of the named metadata.
+      SmallString<8> Name(Record.begin(), Record.end());
+      Record.clear();
+      Code = Stream.ReadCode();
+
+      // METADATA_NAME is always followed by METADATA_NAMED_NODE.
+      unsigned NextBitCode = Stream.readRecord(Code, Record);
+      assert(NextBitCode == bitc::METADATA_NAMED_NODE); (void)NextBitCode;
+
+      // Read named metadata elements.
+      unsigned Size = Record.size();
+      NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata(Name);
+      for (unsigned i = 0; i != Size; ++i) {
+        MDNode *MD = dyn_cast_or_null<MDNode>(MDValueList.getValueFwdRef(Record[i]));
+        if (!MD)
+          return Error("Invalid record");
+        NMD->addOperand(MD);
+      }
+      break;
+    }
+    case bitc::METADATA_OLD_FN_NODE:
+      IsFunctionLocal = true;
+      // fall-through
+    case bitc::METADATA_OLD_NODE: {
+      if (Record.size() % 2 == 1)
+        return Error("Invalid record");
+
+      unsigned Size = Record.size();
+      SmallVector<Metadata *, 8> Elts;
+      for (unsigned i = 0; i != Size; i += 2) {
+        Type *Ty = getTypeByID(Record[i]);
+        if (!Ty)
+          return Error("Invalid record");
+        if (Ty->isMetadataTy())
+          Elts.push_back(MDValueList.getValueFwdRef(Record[i+1]));
+        else if (!Ty->isVoidTy()) {
+          auto *MD =
+              ValueAsMetadata::get(ValueList.getValueFwdRef(Record[i + 1], Ty));
+          assert(isa<ConstantAsMetadata>(MD) &&
+                 "Expected non-function-local metadata");
+          Elts.push_back(MD);
+        } else
+          Elts.push_back(nullptr);
+      }
+      MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++);
+      break;
+    }
+    case bitc::METADATA_STRING: {
+      std::string String(Record.begin(), Record.end());
+      llvm::UpgradeMDStringConstant(String);
+      Metadata *MD = MDString::get(Context, String);
+      MDValueList.AssignValue(MD, NextMDValueNo++);
+      break;
+    }
+    case bitc::METADATA_KIND: {
+      if (Record.size() < 2)
+        return Error("Invalid record");
+
+      unsigned Kind = Record[0];
+      SmallString<8> Name(Record.begin()+1, Record.end());
+
+      unsigned NewKind = TheModule->getMDKindID(Name.str());
+      if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
+        return Error("Conflicting METADATA_KIND records");
+      break;
+    }
+    }
+  }
+}
+
+/// decodeSignRotatedValue - Decode a signed value stored with the sign bit in
+/// the LSB for dense VBR encoding.
+uint64_t BitcodeReader::decodeSignRotatedValue(uint64_t V) {
+  if ((V & 1) == 0)
+    return V >> 1;
+  if (V != 1)
+    return -(V >> 1);
+  // There is no such thing as -0 with integers.  "-0" really means MININT.
+  return 1ULL << 63;
+}
+
+// FIXME: Delete this in LLVM 4.0 and just assert that the aliasee is a
+// GlobalObject.
+static GlobalObject &
+getGlobalObjectInExpr(const DenseMap<GlobalAlias *, Constant *> &Map,
+                      Constant &C) {
+  auto *GO = dyn_cast<GlobalObject>(&C);
+  if (GO)
+    return *GO;
+
+  auto *GA = dyn_cast<GlobalAlias>(&C);
+  if (GA)
+    return getGlobalObjectInExpr(Map, *Map.find(GA)->second);
+
+  auto &CE = cast<ConstantExpr>(C);
+  assert(CE.getOpcode() == Instruction::BitCast ||
+         CE.getOpcode() == Instruction::GetElementPtr ||
+         CE.getOpcode() == Instruction::AddrSpaceCast);
+  if (CE.getOpcode() == Instruction::GetElementPtr)
+    assert(cast<GEPOperator>(CE).hasAllZeroIndices());
+  return getGlobalObjectInExpr(Map, *CE.getOperand(0));
+}
+
+/// ResolveGlobalAndAliasInits - Resolve all of the initializers for global
+/// values and aliases that we can.
+std::error_code BitcodeReader::ResolveGlobalAndAliasInits() {
+  std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
+  std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
+
+  GlobalInitWorklist.swap(GlobalInits);
+  AliasInitWorklist.swap(AliasInits);
+
+  while (!GlobalInitWorklist.empty()) {
+    unsigned ValID = GlobalInitWorklist.back().second;
+    if (ValID >= ValueList.size()) {
+      // Not ready to resolve this yet, it requires something later in the file.
+      GlobalInits.push_back(GlobalInitWorklist.back());
+    } else {
+      if (Constant *C = dyn_cast_or_null<Constant>(ValueList[ValID]))
+        GlobalInitWorklist.back().first->setInitializer(C);
+      else
+        return Error("Expected a constant");
+    }
+    GlobalInitWorklist.pop_back();
+  }
+
+  // FIXME: Delete this in LLVM 4.0
+  // Older versions of llvm could write an alias pointing to another. We cannot
+  // construct those aliases, so we first collect an alias to aliasee expression
+  // and then compute the actual aliasee.
+  DenseMap<GlobalAlias *, Constant *> AliasInit;
+
+  while (!AliasInitWorklist.empty()) {
+    unsigned ValID = AliasInitWorklist.back().second;
+    if (ValID >= ValueList.size()) {
+      AliasInits.push_back(AliasInitWorklist.back());
+    } else {
+      if (Constant *C = dyn_cast_or_null<Constant>(ValueList[ValID]))
+        AliasInit.insert(std::make_pair(AliasInitWorklist.back().first, C));
+      else
+        return Error("Expected a constant");
+    }
+    AliasInitWorklist.pop_back();
+  }
+
+  for (auto &Pair : AliasInit) {
+    auto &GO = getGlobalObjectInExpr(AliasInit, *Pair.second);
+    Pair.first->setAliasee(&GO);
+  }
+
+  return std::error_code();
+}
+
+static APInt ReadWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
+  SmallVector<uint64_t, 8> Words(Vals.size());
+  std::transform(Vals.begin(), Vals.end(), Words.begin(),
+                 BitcodeReader::decodeSignRotatedValue);
+
+  return APInt(TypeBits, Words);
+}
+
+std::error_code BitcodeReader::ParseConstants() {
+  if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  // Read all the records for this value table.
+  Type *CurTy = Type::getInt32Ty(Context);
+  unsigned NextCstNo = ValueList.size();
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      if (NextCstNo != ValueList.size())
+        return Error("Invalid constant reference");
+
+      // Once all the constants have been read, go through and resolve forward
+      // references.
+      ValueList.ResolveConstantForwardRefs();
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    Record.clear();
+    Value *V = nullptr;
+    unsigned BitCode = Stream.readRecord(Entry.ID, Record);
+    switch (BitCode) {
+    default:  // Default behavior: unknown constant
+    case bitc::CST_CODE_UNDEF:     // UNDEF
+      V = UndefValue::get(CurTy);
+      break;
+    case bitc::CST_CODE_SETTYPE:   // SETTYPE: [typeid]
+      if (Record.empty())
+        return Error("Invalid record");
+      if (Record[0] >= TypeList.size())
+        return Error("Invalid record");
+      CurTy = TypeList[Record[0]];
+      continue;  // Skip the ValueList manipulation.
+    case bitc::CST_CODE_NULL:      // NULL
+      V = Constant::getNullValue(CurTy);
+      break;
+    case bitc::CST_CODE_INTEGER:   // INTEGER: [intval]
+      if (!CurTy->isIntegerTy() || Record.empty())
+        return Error("Invalid record");
+      V = ConstantInt::get(CurTy, decodeSignRotatedValue(Record[0]));
+      break;
+    case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval]
+      if (!CurTy->isIntegerTy() || Record.empty())
+        return Error("Invalid record");
+
+      APInt VInt = ReadWideAPInt(Record,
+                                 cast<IntegerType>(CurTy)->getBitWidth());
+      V = ConstantInt::get(Context, VInt);
+
+      break;
+    }
+    case bitc::CST_CODE_FLOAT: {    // FLOAT: [fpval]
+      if (Record.empty())
+        return Error("Invalid record");
+      if (CurTy->isHalfTy())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEhalf,
+                                             APInt(16, (uint16_t)Record[0])));
+      else if (CurTy->isFloatTy())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEsingle,
+                                             APInt(32, (uint32_t)Record[0])));
+      else if (CurTy->isDoubleTy())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEdouble,
+                                             APInt(64, Record[0])));
+      else if (CurTy->isX86_FP80Ty()) {
+        // Bits are not stored the same way as a normal i80 APInt, compensate.
+        uint64_t Rearrange[2];
+        Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16);
+        Rearrange[1] = Record[0] >> 48;
+        V = ConstantFP::get(Context, APFloat(APFloat::x87DoubleExtended,
+                                             APInt(80, Rearrange)));
+      } else if (CurTy->isFP128Ty())
+        V = ConstantFP::get(Context, APFloat(APFloat::IEEEquad,
+                                             APInt(128, Record)));
+      else if (CurTy->isPPC_FP128Ty())
+        V = ConstantFP::get(Context, APFloat(APFloat::PPCDoubleDouble,
+                                             APInt(128, Record)));
+      else
+        V = UndefValue::get(CurTy);
+      break;
+    }
+
+    case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number]
+      if (Record.empty())
+        return Error("Invalid record");
+
+      unsigned Size = Record.size();
+      SmallVector<Constant*, 16> Elts;
+
+      if (StructType *STy = dyn_cast<StructType>(CurTy)) {
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i],
+                                                     STy->getElementType(i)));
+        V = ConstantStruct::get(STy, Elts);
+      } else if (ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {
+        Type *EltTy = ATy->getElementType();
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+        V = ConstantArray::get(ATy, Elts);
+      } else if (VectorType *VTy = dyn_cast<VectorType>(CurTy)) {
+        Type *EltTy = VTy->getElementType();
+        for (unsigned i = 0; i != Size; ++i)
+          Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
+        V = ConstantVector::get(Elts);
+      } else {
+        V = UndefValue::get(CurTy);
+      }
+      break;
+    }
+    case bitc::CST_CODE_STRING: { // STRING: [values]
+      if (Record.empty())
+        return Error("Invalid record");
+
+      ArrayType *ATy = cast<ArrayType>(CurTy);
+      Type *EltTy = ATy->getElementType();
+
+      unsigned Size = Record.size();
+      std::vector<Constant*> Elts;
+      for (unsigned i = 0; i != Size; ++i)
+        Elts.push_back(ConstantInt::get(EltTy, Record[i]));
+      V = ConstantArray::get(ATy, Elts);
+      break;
+    }
+    case bitc::CST_CODE_CSTRING: { // CSTRING: [values]
+      if (Record.empty())
+        return Error("Invalid record");
+
+      ArrayType *ATy = cast<ArrayType>(CurTy);
+      Type *EltTy = ATy->getElementType();
+
+      unsigned Size = Record.size();
+      std::vector<Constant*> Elts;
+      for (unsigned i = 0; i != Size; ++i)
+        Elts.push_back(ConstantInt::get(EltTy, Record[i]));
+      Elts.push_back(Constant::getNullValue(EltTy));
+      V = ConstantArray::get(ATy, Elts);
+      break;
+    }
+    case bitc::CST_CODE_CE_BINOP: {  // CE_BINOP: [opcode, opval, opval]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      int Opc = GetDecodedBinaryOpcode(Record[0], CurTy);
+      if (Opc < 0) {
+        V = UndefValue::get(CurTy);  // Unknown binop.
+      } else {
+        Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
+        Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
+        unsigned Flags = 0;
+        if (Record.size() >= 4) {
+          if (Opc == Instruction::Add ||
+              Opc == Instruction::Sub ||
+              Opc == Instruction::Mul ||
+              Opc == Instruction::Shl) {
+            if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
+              Flags |= OverflowingBinaryOperator::NoSignedWrap;
+            if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
+              Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
+          } else if (Opc == Instruction::SDiv ||
+                     Opc == Instruction::UDiv ||
+                     Opc == Instruction::LShr ||
+                     Opc == Instruction::AShr) {
+            if (Record[3] & (1 << bitc::PEO_EXACT))
+              Flags |= SDivOperator::IsExact;
+          }
+        }
+        V = ConstantExpr::get(Opc, LHS, RHS, Flags);
+      }
+      break;
+    }
+    case bitc::CST_CODE_CE_CAST: {  // CE_CAST: [opcode, opty, opval]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      int Opc = GetDecodedCastOpcode(Record[0]);
+      if (Opc < 0) {
+        V = UndefValue::get(CurTy);  // Unknown cast.
+      } else {
+        Type *OpTy = getTypeByID(Record[1]);
+        if (!OpTy)
+          return Error("Invalid record");
+        Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy);
+        V = ConstantExpr::getCast(Opc, Op, CurTy);
+      }
+      break;
+    }
+    case bitc::CST_CODE_CE_INBOUNDS_GEP:
+    case bitc::CST_CODE_CE_GEP: {  // CE_GEP:        [n x operands]
+      Type *PointeeType = nullptr;
+      if (Record.size() & 1)
+        return Error("Invalid record");
+      SmallVector<Constant*, 16> Elts;
+      for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        Type *ElTy = getTypeByID(Record[i]);
+        if (!ElTy)
+          return Error("Invalid record");
+        Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
+      }
+      ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
+      V = ConstantExpr::getGetElementPtr(PointeeType, Elts[0], Indices,
+                                         BitCode ==
+                                           bitc::CST_CODE_CE_INBOUNDS_GEP);
+      break;
+    }
+    case bitc::CST_CODE_CE_SELECT:  // CE_SELECT: [opval#, opval#, opval#]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0],
+                                                              Type::getInt1Ty(Context)),
+                                  ValueList.getConstantFwdRef(Record[1],CurTy),
+                                  ValueList.getConstantFwdRef(Record[2],CurTy));
+      break;
+    case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      VectorType *OpTy =
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (!OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
+      V = ConstantExpr::getExtractElement(Op0, Op1);
+      break;
+    }
+    case bitc::CST_CODE_CE_INSERTELT: { // CE_INSERTELT: [opval, opval, opval]
+      VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+      if (Record.size() < 3 || !OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[1],
+                                                  OpTy->getElementType());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
+      V = ConstantExpr::getInsertElement(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval]
+      VectorType *OpTy = dyn_cast<VectorType>(CurTy);
+      if (Record.size() < 3 || !OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+                                                 OpTy->getNumElements());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy);
+      V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval]
+      VectorType *RTy = dyn_cast<VectorType>(CurTy);
+      VectorType *OpTy =
+        dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
+      if (Record.size() < 4 || !RTy || !OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+      Type *ShufTy = VectorType::get(Type::getInt32Ty(Context),
+                                                 RTy->getNumElements());
+      Constant *Op2 = ValueList.getConstantFwdRef(Record[3], ShufTy);
+      V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+      break;
+    }
+    case bitc::CST_CODE_CE_CMP: {     // CE_CMP: [opty, opval, opval, pred]
+      if (Record.size() < 4)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      if (!OpTy)
+        return Error("Invalid record");
+      Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
+      Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
+
+      if (OpTy->isFPOrFPVectorTy())
+        V = ConstantExpr::getFCmp(Record[3], Op0, Op1);
+      else
+        V = ConstantExpr::getICmp(Record[3], Op0, Op1);
+      break;
+    }
+    case bitc::CST_CODE_INLINEASM:
+    case bitc::CST_CODE_INLINEASM_OLD: {
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      std::string AsmStr, ConstrStr;
+      bool HasSideEffects = Record[0] & 1;
+      bool IsAlignStack = Record[0] >> 1;
+      unsigned AsmStrSize = Record[1];
+      if (2+AsmStrSize >= Record.size())
+        return Error("Invalid record");
+      unsigned ConstStrSize = Record[2+AsmStrSize];
+      if (3+AsmStrSize+ConstStrSize > Record.size())
+        return Error("Invalid record");
+
+      for (unsigned i = 0; i != AsmStrSize; ++i)
+        AsmStr += (char)Record[2+i];
+      for (unsigned i = 0; i != ConstStrSize; ++i)
+        ConstrStr += (char)Record[3+AsmStrSize+i];
+      PointerType *PTy = cast<PointerType>(CurTy);
+      V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
+                         AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
+      break;
+    }
+    case bitc::CST_CODE_BLOCKADDRESS:{
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      Type *FnTy = getTypeByID(Record[0]);
+      if (!FnTy)
+        return Error("Invalid record");
+      Function *Fn =
+        dyn_cast_or_null<Function>(ValueList.getConstantFwdRef(Record[1],FnTy));
+      if (!Fn)
+        return Error("Invalid record");
+
+      GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(),
+                                                  Type::getInt8Ty(Context),
+                                            false, GlobalValue::InternalLinkage,
+                                                  0, "");
+      BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef));
+      V = FwdRef;
+      break;
+    }
+    }
+
+    ValueList.AssignValue(V, NextCstNo);
+    ++NextCstNo;
+  }
+
+  if (NextCstNo != ValueList.size())
+    return Error("Invalid constant reference");
+
+  if (Stream.ReadBlockEnd())
+    return Error("Expected a constant");
+
+  // Once all the constants have been read, go through and resolve forward
+  // references.
+  ValueList.ResolveConstantForwardRefs();
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::materializeMetadata() {
+  return std::error_code();
+}
+
+void BitcodeReader::setStripDebugInfo() { }
+
+/// RememberAndSkipFunctionBody - When we see the block for a function body,
+/// remember where it is and then skip it.  This lets us lazily deserialize the
+/// functions.
+std::error_code BitcodeReader::RememberAndSkipFunctionBody() {
+  // Get the function we are talking about.
+  if (FunctionsWithBodies.empty())
+    return Error("Insufficient function protos");
+
+  Function *Fn = FunctionsWithBodies.back();
+  FunctionsWithBodies.pop_back();
+
+  // Save the current stream state.
+  uint64_t CurBit = Stream.GetCurrentBitNo();
+  DeferredFunctionInfo[Fn] = CurBit;
+
+  // Skip over the function block for now.
+  if (Stream.SkipBlock())
+    return Error("Invalid record");
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::GlobalCleanup() {
+  // Patch the initializers for globals and aliases up.
+  ResolveGlobalAndAliasInits();
+  if (!GlobalInits.empty() || !AliasInits.empty())
+    return Error("Malformed global initializer set");
+
+  // Look for intrinsic functions which need to be upgraded at some point
+  for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
+       FI != FE; ++FI) {
+    Function *NewFn;
+    if (UpgradeIntrinsicFunction(&*FI, NewFn))
+      UpgradedIntrinsics.push_back(std::make_pair(&*FI, NewFn));
+  }
+
+  // Look for global variables which need to be renamed.
+  for (Module::global_iterator
+         GI = TheModule->global_begin(), GE = TheModule->global_end();
+       GI != GE; GI++) {
+    GlobalVariable *GV = &*GI;
+    UpgradeGlobalVariable(GV);
+  }
+
+  // Force deallocation of memory for these vectors to favor the client that
+  // want lazy deserialization.
+  std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits);
+  std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits);
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::ParseModule(bool Resume) {
+  if (Resume)
+    Stream.JumpToBit(NextUnreadBit);
+  else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+  std::vector<std::string> SectionTable;
+  std::vector<std::string> GCTable;
+
+  // Read all the records for this module.
+  while (1) {
+    BitstreamEntry Entry = Stream.advance();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return GlobalCleanup();
+
+    case BitstreamEntry::SubBlock:
+      switch (Entry.ID) {
+      default:  // Skip unknown content.
+        if (Stream.SkipBlock())
+          return Error("Invalid record");
+        break;
+      case bitc::BLOCKINFO_BLOCK_ID:
+        if (Stream.ReadBlockInfoBlock())
+          return Error("Malformed block");
+        break;
+      case bitc::PARAMATTR_BLOCK_ID:
+        if (std::error_code EC = ParseAttributeBlock())
+          return EC;
+        break;
+      case bitc::TYPE_BLOCK_ID_NEW:
+        if (std::error_code EC = ParseTypeTable())
+          return EC;
+        break;
+      case TYPE_BLOCK_ID_OLD_3_0:
+        if (std::error_code EC = ParseOldTypeTable())
+          return EC;
+        break;
+      case TYPE_SYMTAB_BLOCK_ID_OLD_3_0:
+        if (std::error_code EC = ParseOldTypeSymbolTable())
+          return EC;
+        break;
+      case bitc::VALUE_SYMTAB_BLOCK_ID:
+        if (std::error_code EC = ParseValueSymbolTable())
+          return EC;
+        SeenValueSymbolTable = true;
+        break;
+      case bitc::CONSTANTS_BLOCK_ID:
+        if (std::error_code EC = ParseConstants())
+          return EC;
+        if (std::error_code EC = ResolveGlobalAndAliasInits())
+          return EC;
+        break;
+      case bitc::METADATA_BLOCK_ID:
+        if (std::error_code EC = ParseMetadata())
+          return EC;
+        break;
+      case bitc::FUNCTION_BLOCK_ID:
+        // If this is the first function body we've seen, reverse the
+        // FunctionsWithBodies list.
+        if (!SeenFirstFunctionBody) {
+          std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
+          if (std::error_code EC = GlobalCleanup())
+            return EC;
+          SeenFirstFunctionBody = true;
+        }
+
+        if (std::error_code EC = RememberAndSkipFunctionBody())
+          return EC;
+        // For streaming bitcode, suspend parsing when we reach the function
+        // bodies. Subsequent materialization calls will resume it when
+        // necessary. For streaming, the function bodies must be at the end of
+        // the bitcode. If the bitcode file is old, the symbol table will be
+        // at the end instead and will not have been seen yet. In this case,
+        // just finish the parse now.
+        if (LazyStreamer && SeenValueSymbolTable) {
+          NextUnreadBit = Stream.GetCurrentBitNo();
+          return std::error_code();
+        }
+        break;
+        break;
+      }
+      continue;
+
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+
+    // Read a record.
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default: break;  // Default behavior, ignore unknown content.
+    case bitc::MODULE_CODE_VERSION: {  // VERSION: [version#]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      // Only version #0 is supported so far.
+      if (Record[0] != 0)
+        return Error("Invalid value");
+      break;
+    }
+    case bitc::MODULE_CODE_TRIPLE: {  // TRIPLE: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      TheModule->setTargetTriple(S);
+      break;
+    }
+    case bitc::MODULE_CODE_DATALAYOUT: {  // DATALAYOUT: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      TheModule->setDataLayout(S);
+      break;
+    }
+    case bitc::MODULE_CODE_ASM: {  // ASM: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      TheModule->setModuleInlineAsm(S);
+      break;
+    }
+    case bitc::MODULE_CODE_DEPLIB: {  // DEPLIB: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      // ANDROID: Ignore value, since we never used it anyways.
+      // TheModule->addLibrary(S);
+      break;
+    }
+    case bitc::MODULE_CODE_SECTIONNAME: {  // SECTIONNAME: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      SectionTable.push_back(S);
+      break;
+    }
+    case bitc::MODULE_CODE_GCNAME: {  // SECTIONNAME: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      GCTable.push_back(S);
+      break;
+    }
+    // GLOBALVAR: [pointer type, isconst, initid,
+    //             linkage, alignment, section, visibility, threadlocal,
+    //             unnamed_addr]
+    case bitc::MODULE_CODE_GLOBALVAR: {
+      if (Record.size() < 6)
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+      if (!Ty->isPointerTy())
+        return Error("Invalid type for value");
+      unsigned AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
+      Ty = cast<PointerType>(Ty)->getElementType();
+
+      bool isConstant = Record[1];
+      uint64_t RawLinkage = Record[3];
+      GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
+      unsigned Alignment = (1 << Record[4]) >> 1;
+      std::string Section;
+      if (Record[5]) {
+        if (Record[5]-1 >= SectionTable.size())
+          return Error("Invalid ID");
+        Section = SectionTable[Record[5]-1];
+      }
+      GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility;
+      if (Record.size() > 6)
+        Visibility = GetDecodedVisibility(Record[6]);
+
+      GlobalVariable::ThreadLocalMode TLM = GlobalVariable::NotThreadLocal;
+      if (Record.size() > 7)
+        TLM = GetDecodedThreadLocalMode(Record[7]);
+
+      bool UnnamedAddr = false;
+      if (Record.size() > 8)
+        UnnamedAddr = Record[8];
+
+      GlobalVariable *NewGV =
+        new GlobalVariable(*TheModule, Ty, isConstant, Linkage, nullptr, "", nullptr,
+                           TLM, AddressSpace);
+      NewGV->setAlignment(Alignment);
+      if (!Section.empty())
+        NewGV->setSection(Section);
+      NewGV->setVisibility(Visibility);
+      NewGV->setUnnamedAddr(UnnamedAddr);
+
+      ValueList.push_back(NewGV);
+
+      // Remember which value to use for the global initializer.
+      if (unsigned InitID = Record[2])
+        GlobalInits.push_back(std::make_pair(NewGV, InitID-1));
+      break;
+    }
+    // FUNCTION:  [type, callingconv, isproto, linkage, paramattr,
+    //             alignment, section, visibility, gc, unnamed_addr]
+    case bitc::MODULE_CODE_FUNCTION: {
+      if (Record.size() < 8)
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+      if (!Ty->isPointerTy())
+        return Error("Invalid type for value");
+      FunctionType *FTy =
+        dyn_cast<FunctionType>(cast<PointerType>(Ty)->getElementType());
+      if (!FTy)
+        return Error("Invalid type for value");
+
+      Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
+                                        "", TheModule);
+
+      Func->setCallingConv(static_cast<CallingConv::ID>(Record[1]));
+      bool isProto = Record[2];
+      uint64_t RawLinkage = Record[3];
+      Func->setLinkage(getDecodedLinkage(RawLinkage));
+      Func->setAttributes(getAttributes(Record[4]));
+
+      Func->setAlignment((1 << Record[5]) >> 1);
+      if (Record[6]) {
+        if (Record[6]-1 >= SectionTable.size())
+          return Error("Invalid ID");
+        Func->setSection(SectionTable[Record[6]-1]);
+      }
+      Func->setVisibility(GetDecodedVisibility(Record[7]));
+      if (Record.size() > 8 && Record[8]) {
+        if (Record[8]-1 > GCTable.size())
+          return Error("Invalid ID");
+        Func->setGC(GCTable[Record[8]-1].c_str());
+      }
+      bool UnnamedAddr = false;
+      if (Record.size() > 9)
+        UnnamedAddr = Record[9];
+      Func->setUnnamedAddr(UnnamedAddr);
+      ValueList.push_back(Func);
+
+      // If this is a function with a body, remember the prototype we are
+      // creating now, so that we can match up the body with them later.
+      if (!isProto) {
+        Func->setIsMaterializable(true);
+        FunctionsWithBodies.push_back(Func);
+        if (LazyStreamer)
+          DeferredFunctionInfo[Func] = 0;
+      }
+      break;
+    }
+    // ALIAS: [alias type, aliasee val#, linkage]
+    // ALIAS: [alias type, aliasee val#, linkage, visibility]
+    case bitc::MODULE_CODE_ALIAS_OLD: {
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+      auto *PTy = dyn_cast<PointerType>(Ty);
+      if (!PTy)
+        return Error("Invalid type for value");
+
+      auto *NewGA =
+          GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
+                              getDecodedLinkage(Record[2]), "", TheModule);
+      // Old bitcode files didn't have visibility field.
+      if (Record.size() > 3)
+        NewGA->setVisibility(GetDecodedVisibility(Record[3]));
+      ValueList.push_back(NewGA);
+      AliasInits.push_back(std::make_pair(NewGA, Record[1]));
+      break;
+    }
+    /// MODULE_CODE_PURGEVALS: [numvals]
+    case bitc::MODULE_CODE_PURGEVALS:
+      // Trim down the value list to the specified size.
+      if (Record.size() < 1 || Record[0] > ValueList.size())
+        return Error("Invalid record");
+      ValueList.shrinkTo(Record[0]);
+      break;
+    }
+    Record.clear();
+  }
+}
+
+std::error_code BitcodeReader::ParseBitcodeInto(Module *M) {
+  TheModule = nullptr;
+
+  if (std::error_code EC = InitStream())
+    return EC;
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'B' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(4) != 0x0 ||
+      Stream.Read(4) != 0xC ||
+      Stream.Read(4) != 0xE ||
+      Stream.Read(4) != 0xD)
+    return Error("Invalid bitcode signature");
+
+  // We expect a number of well-defined blocks, though we don't necessarily
+  // need to understand them all.
+  while (1) {
+    if (Stream.AtEndOfStream())
+      return std::error_code();
+
+    BitstreamEntry Entry =
+      Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+
+    case BitstreamEntry::SubBlock:
+      switch (Entry.ID) {
+      case bitc::BLOCKINFO_BLOCK_ID:
+        if (Stream.ReadBlockInfoBlock())
+          return Error("Malformed block");
+        break;
+      case bitc::MODULE_BLOCK_ID:
+        // Reject multiple MODULE_BLOCK's in a single bitstream.
+        if (TheModule)
+          return Error("Invalid multiple blocks");
+        TheModule = M;
+        if (std::error_code EC = ParseModule(false))
+          return EC;
+        if (LazyStreamer)
+          return std::error_code();
+        break;
+      default:
+        if (Stream.SkipBlock())
+          return Error("Invalid record");
+        break;
+      }
+      continue;
+    case BitstreamEntry::Record:
+      // There should be no records in the top-level of blocks.
+
+      // The ranlib in Xcode 4 will align archive members by appending newlines
+      // to the end of them. If this file size is a multiple of 4 but not 8, we
+      // have to read and ignore these final 4 bytes :-(
+      if (Stream.getAbbrevIDWidth() == 2 && Entry.ID == 2 &&
+          Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a &&
+          Stream.AtEndOfStream())
+        return std::error_code();
+
+      return Error("Invalid record");
+    }
+  }
+}
+
+llvm::ErrorOr<std::string> BitcodeReader::parseModuleTriple() {
+  if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+
+  std::string Triple;
+  // Read all the records for this module.
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return Triple;
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a record.
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default: break;  // Default behavior, ignore unknown content.
+    case bitc::MODULE_CODE_VERSION:  // VERSION: [version#]
+      if (Record.size() < 1)
+        return Error("Invalid record");
+      // Only version #0 is supported so far.
+      if (Record[0] != 0)
+        return Error("Invalid record");
+      break;
+    case bitc::MODULE_CODE_TRIPLE: {  // TRIPLE: [strchr x N]
+      std::string S;
+      if (ConvertToString(Record, 0, S))
+        return Error("Invalid record");
+      Triple = S;
+      break;
+    }
+    }
+    Record.clear();
+  }
+
+  return Error("Invalid bitcode signature");
+}
+
+llvm::ErrorOr<std::string> BitcodeReader::parseTriple() {
+  if (std::error_code EC = InitStream())
+    return EC;
+
+  // Sniff for the signature.
+  if (Stream.Read(8) != 'B' ||
+      Stream.Read(8) != 'C' ||
+      Stream.Read(4) != 0x0 ||
+      Stream.Read(4) != 0xC ||
+      Stream.Read(4) != 0xE ||
+      Stream.Read(4) != 0xD)
+    return Error("Invalid bitcode signature");
+
+  // We expect a number of well-defined blocks, though we don't necessarily
+  // need to understand them all.
+  while (1) {
+    BitstreamEntry Entry = Stream.advance();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+
+    case BitstreamEntry::SubBlock:
+      if (Entry.ID == bitc::MODULE_BLOCK_ID)
+        return parseModuleTriple();
+
+      // Ignore other sub-blocks.
+      if (Stream.SkipBlock())
+        return Error("Malformed block");
+      continue;
+
+    case BitstreamEntry::Record:
+      Stream.skipRecord(Entry.ID);
+      continue;
+    }
+  }
+}
+
+/// ParseMetadataAttachment - Parse metadata attachments.
+std::error_code BitcodeReader::ParseMetadataAttachment() {
+  if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
+    return Error("Invalid record");
+
+  SmallVector<uint64_t, 64> Record;
+  while (1) {
+    BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+    switch (Entry.Kind) {
+    case BitstreamEntry::SubBlock: // Handled for us already.
+    case BitstreamEntry::Error:
+      return Error("Malformed block");
+    case BitstreamEntry::EndBlock:
+      return std::error_code();
+    case BitstreamEntry::Record:
+      // The interesting case.
+      break;
+    }
+
+    // Read a metadata attachment record.
+    Record.clear();
+    switch (Stream.readRecord(Entry.ID, Record)) {
+    default:  // Default behavior: ignore.
+      break;
+    case bitc::METADATA_ATTACHMENT: {
+      unsigned RecordLength = Record.size();
+      if (Record.empty() || (RecordLength - 1) % 2 == 1)
+        return Error("Invalid record");
+      Instruction *Inst = InstructionList[Record[0]];
+      for (unsigned i = 1; i != RecordLength; i = i+2) {
+        unsigned Kind = Record[i];
+        DenseMap<unsigned, unsigned>::iterator I =
+          MDKindMap.find(Kind);
+        if (I == MDKindMap.end())
+          return Error("Invalid ID");
+        Metadata *Node = MDValueList.getValueFwdRef(Record[i + 1]);
+        Inst->setMetadata(I->second, cast<MDNode>(Node));
+      }
+      break;
+    }
+    }
+  }
+}
+
+/// ParseFunctionBody - Lazily parse the specified function body block.
+std::error_code BitcodeReader::ParseFunctionBody(Function *F) {
+  if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
+    return Error("Invalid record");
+
+  InstructionList.clear();
+  unsigned ModuleValueListSize = ValueList.size();
+  unsigned ModuleMDValueListSize = MDValueList.size();
+
+  // Add all the function arguments to the value table.
+  for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
+    ValueList.push_back(&*I);
+
+  unsigned NextValueNo = ValueList.size();
+  BasicBlock *CurBB = nullptr;
+  unsigned CurBBNo = 0;
+
+  DebugLoc LastLoc;
+
+  // Read all the records.
+  SmallVector<uint64_t, 64> Record;
+  while (1) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd())
+        return Error("Malformed block");
+      break;
+    }
+
+    if (Code == bitc::ENTER_SUBBLOCK) {
+      switch (Stream.ReadSubBlockID()) {
+      default:  // Skip unknown content.
+        if (Stream.SkipBlock())
+          return Error("Invalid record");
+        break;
+      case bitc::CONSTANTS_BLOCK_ID:
+        if (std::error_code EC = ParseConstants())
+          return EC;
+        NextValueNo = ValueList.size();
+        break;
+      case bitc::VALUE_SYMTAB_BLOCK_ID:
+        if (std::error_code EC = ParseValueSymbolTable())
+          return EC;
+        break;
+      case bitc::METADATA_ATTACHMENT_ID:
+        if (std::error_code EC = ParseMetadataAttachment())
+          return EC;
+        break;
+      case bitc::METADATA_BLOCK_ID:
+        if (std::error_code EC = ParseMetadata())
+          return EC;
+        break;
+      }
+      continue;
+    }
+
+    if (Code == bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read a record.
+    Record.clear();
+    Instruction *I = nullptr;
+    unsigned BitCode = Stream.readRecord(Code, Record);
+    switch (BitCode) {
+    default: // Default behavior: reject
+      return Error("Invalid value");
+    case bitc::FUNC_CODE_DECLAREBLOCKS:     // DECLAREBLOCKS: [nblocks]
+      if (Record.size() < 1 || Record[0] == 0)
+        return Error("Invalid record");
+      // Create all the basic blocks for the function.
+      FunctionBBs.resize(Record[0]);
+      for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i)
+        FunctionBBs[i] = BasicBlock::Create(Context, "", F);
+      CurBB = FunctionBBs[0];
+      continue;
+
+    case bitc::FUNC_CODE_DEBUG_LOC_AGAIN:  // DEBUG_LOC_AGAIN
+      // This record indicates that the last instruction is at the same
+      // location as the previous instruction with a location.
+      I = nullptr;
+
+      // Get the last instruction emitted.
+      if (CurBB && !CurBB->empty())
+        I = &CurBB->back();
+      else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+               !FunctionBBs[CurBBNo-1]->empty())
+        I = &FunctionBBs[CurBBNo-1]->back();
+
+      if (!I)
+        return Error("Invalid record");
+      I->setDebugLoc(LastLoc);
+      I = nullptr;
+      continue;
+
+    case bitc::FUNC_CODE_DEBUG_LOC: {      // DEBUG_LOC: [line, col, scope, ia]
+      I = nullptr;     // Get the last instruction emitted.
+      if (CurBB && !CurBB->empty())
+        I = &CurBB->back();
+      else if (CurBBNo && FunctionBBs[CurBBNo-1] &&
+               !FunctionBBs[CurBBNo-1]->empty())
+        I = &FunctionBBs[CurBBNo-1]->back();
+      if (!I || Record.size() < 4)
+        return Error("Invalid record");
+
+      unsigned Line = Record[0], Col = Record[1];
+      unsigned ScopeID = Record[2], IAID = Record[3];
+
+      MDNode *Scope = nullptr, *IA = nullptr;
+      if (ScopeID) Scope = cast<MDNode>(MDValueList.getValueFwdRef(ScopeID-1));
+      if (IAID)    IA = cast<MDNode>(MDValueList.getValueFwdRef(IAID-1));
+      LastLoc = DebugLoc::get(Line, Col, Scope, IA);
+      I->setDebugLoc(LastLoc);
+      I = nullptr;
+      continue;
+    }
+
+    case bitc::FUNC_CODE_INST_BINOP: {    // BINOP: [opval, ty, opval, opcode]
+      unsigned OpNum = 0;
+      Value *LHS, *RHS;
+      if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+          getValue(Record, OpNum, LHS->getType(), RHS) ||
+          OpNum+1 > Record.size())
+        return Error("Invalid record");
+
+      int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
+      if (Opc == -1)
+        return Error("Invalid record");
+      I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
+      InstructionList.push_back(I);
+      if (OpNum < Record.size()) {
+        if (Opc == Instruction::Add ||
+            Opc == Instruction::Sub ||
+            Opc == Instruction::Mul ||
+            Opc == Instruction::Shl) {
+          if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP))
+            cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
+          if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
+            cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
+        } else if (Opc == Instruction::SDiv ||
+                   Opc == Instruction::UDiv ||
+                   Opc == Instruction::LShr ||
+                   Opc == Instruction::AShr) {
+          if (Record[OpNum] & (1 << bitc::PEO_EXACT))
+            cast<BinaryOperator>(I)->setIsExact(true);
+        }
+      }
+      break;
+    }
+    case bitc::FUNC_CODE_INST_CAST: {    // CAST: [opval, opty, destty, castopc]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid record");
+
+      Type *ResTy = getTypeByID(Record[OpNum]);
+      int Opc = GetDecodedCastOpcode(Record[OpNum+1]);
+      if (Opc == -1 || !ResTy)
+        return Error("Invalid record");
+      I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD:
+    case bitc::FUNC_CODE_INST_GEP_OLD: // GEP: [n x operands]
+    case bitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands]
+      unsigned OpNum = 0;
+
+      Type *Ty;
+      bool InBounds;
+
+      if (BitCode == bitc::FUNC_CODE_INST_GEP) {
+        InBounds = Record[OpNum++];
+        Ty = getTypeByID(Record[OpNum++]);
+      } else {
+        InBounds = BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD;
+        Ty = nullptr;
+      }
+
+      Value *BasePtr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr))
+        return Error("Invalid record");
+
+      if (Ty &&
+          Ty !=
+              cast<SequentialType>(BasePtr->getType()->getScalarType())
+                  ->getElementType())
+        return Error(
+            "Explicit gep type does not match pointee type of pointer operand");
+
+      SmallVector<Value*, 16> GEPIdx;
+      while (OpNum != Record.size()) {
+        Value *Op;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid record");
+        GEPIdx.push_back(Op);
+      }
+
+      I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx);
+
+      InstructionList.push_back(I);
+      if (InBounds)
+        cast<GetElementPtrInst>(I)->setIsInBounds(true);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_EXTRACTVAL: {
+                                       // EXTRACTVAL: [opty, opval, n x indices]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid record");
+
+      SmallVector<unsigned, 4> EXTRACTVALIdx;
+      for (unsigned RecSize = Record.size();
+           OpNum != RecSize; ++OpNum) {
+        uint64_t Index = Record[OpNum];
+        if ((unsigned)Index != Index)
+          return Error("Invalid value");
+        EXTRACTVALIdx.push_back((unsigned)Index);
+      }
+
+      I = ExtractValueInst::Create(Agg, EXTRACTVALIdx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INSERTVAL: {
+                           // INSERTVAL: [opty, opval, opty, opval, n x indices]
+      unsigned OpNum = 0;
+      Value *Agg;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+        return Error("Invalid record");
+      Value *Val;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Val))
+        return Error("Invalid record");
+
+      SmallVector<unsigned, 4> INSERTVALIdx;
+      for (unsigned RecSize = Record.size();
+           OpNum != RecSize; ++OpNum) {
+        uint64_t Index = Record[OpNum];
+        if ((unsigned)Index != Index)
+          return Error("Invalid value");
+        INSERTVALIdx.push_back((unsigned)Index);
+      }
+
+      I = InsertValueInst::Create(Agg, Val, INSERTVALIdx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval]
+      // obsolete form of select
+      // handles select i1 ... in old bitcode
+      unsigned OpNum = 0;
+      Value *TrueVal, *FalseVal, *Cond;
+      if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+          getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
+          getValue(Record, OpNum, Type::getInt1Ty(Context), Cond))
+        return Error("Invalid record");
+
+      I = SelectInst::Create(Cond, TrueVal, FalseVal);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [ty,opval,opval,predty,pred]
+      // new form of select
+      // handles select i1 or select [N x i1]
+      unsigned OpNum = 0;
+      Value *TrueVal, *FalseVal, *Cond;
+      if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+          getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
+          getValueTypePair(Record, OpNum, NextValueNo, Cond))
+        return Error("Invalid record");
+
+      // select condition can be either i1 or [N x i1]
+      if (VectorType* vector_type =
+          dyn_cast<VectorType>(Cond->getType())) {
+        // expect <n x i1>
+        if (vector_type->getElementType() != Type::getInt1Ty(Context))
+          return Error("Invalid type for value");
+      } else {
+        // expect i1
+        if (Cond->getType() != Type::getInt1Ty(Context))
+          return Error("Invalid type for value");
+      }
+
+      I = SelectInst::Create(Cond, TrueVal, FalseVal);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval]
+      unsigned OpNum = 0;
+      Value *Vec, *Idx;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+          getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+        return Error("Invalid record");
+      I = ExtractElementInst::Create(Vec, Idx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval]
+      unsigned OpNum = 0;
+      Value *Vec, *Elt, *Idx;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+          getValue(Record, OpNum,
+                   cast<VectorType>(Vec->getType())->getElementType(), Elt) ||
+          getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+        return Error("Invalid record");
+      I = InsertElementInst::Create(Vec, Elt, Idx);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval]
+      unsigned OpNum = 0;
+      Value *Vec1, *Vec2, *Mask;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) ||
+          getValue(Record, OpNum, Vec1->getType(), Vec2))
+        return Error("Invalid record");
+
+      if (getValueTypePair(Record, OpNum, NextValueNo, Mask))
+        return Error("Invalid record");
+      I = new ShuffleVectorInst(Vec1, Vec2, Mask);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_CMP:   // CMP: [opty, opval, opval, pred]
+      // Old form of ICmp/FCmp returning bool
+      // Existed to differentiate between icmp/fcmp and vicmp/vfcmp which were
+      // both legal on vectors but had different behaviour.
+    case bitc::FUNC_CODE_INST_CMP2: { // CMP2: [opty, opval, opval, pred]
+      // FCmp/ICmp returning bool or vector of bool
+
+      unsigned OpNum = 0;
+      Value *LHS, *RHS;
+      if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+          getValue(Record, OpNum, LHS->getType(), RHS) ||
+          OpNum+1 != Record.size())
+        return Error("Invalid record");
+
+      if (LHS->getType()->isFPOrFPVectorTy())
+        I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS);
+      else
+        I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS);
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_RET: // RET: [opty,opval<optional>]
+      {
+        unsigned Size = Record.size();
+        if (Size == 0) {
+          I = ReturnInst::Create(Context);
+          InstructionList.push_back(I);
+          break;
+        }
+
+        unsigned OpNum = 0;
+        Value *Op = nullptr;
+        if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+          return Error("Invalid record");
+        if (OpNum != Record.size())
+          return Error("Invalid record");
+
+        I = ReturnInst::Create(Context, Op);
+        InstructionList.push_back(I);
+        break;
+      }
+    case bitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#]
+      if (Record.size() != 1 && Record.size() != 3)
+        return Error("Invalid record");
+      BasicBlock *TrueDest = getBasicBlock(Record[0]);
+      if (!TrueDest)
+        return Error("Invalid record");
+
+      if (Record.size() == 1) {
+        I = BranchInst::Create(TrueDest);
+        InstructionList.push_back(I);
+      }
+      else {
+        BasicBlock *FalseDest = getBasicBlock(Record[1]);
+        Value *Cond = getFnValueByID(Record[2], Type::getInt1Ty(Context));
+        if (!FalseDest || !Cond)
+          return Error("Invalid record");
+        I = BranchInst::Create(TrueDest, FalseDest, Cond);
+        InstructionList.push_back(I);
+      }
+      break;
+    }
+    case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
+      if (Record.size() < 3 || (Record.size() & 1) == 0)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Cond = getFnValueByID(Record[1], OpTy);
+      BasicBlock *Default = getBasicBlock(Record[2]);
+      if (!OpTy || !Cond || !Default)
+        return Error("Invalid record");
+      unsigned NumCases = (Record.size()-3)/2;
+      SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
+      InstructionList.push_back(SI);
+      for (unsigned i = 0, e = NumCases; i != e; ++i) {
+        ConstantInt *CaseVal =
+          dyn_cast_or_null<ConstantInt>(getFnValueByID(Record[3+i*2], OpTy));
+        BasicBlock *DestBB = getBasicBlock(Record[1+3+i*2]);
+        if (!CaseVal || !DestBB) {
+          delete SI;
+          return Error("Invalid record");
+        }
+        SI->addCase(CaseVal, DestBB);
+      }
+      I = SI;
+      break;
+    }
+    case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...]
+      if (Record.size() < 2)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Address = getFnValueByID(Record[1], OpTy);
+      if (!OpTy || !Address)
+        return Error("Invalid record");
+      unsigned NumDests = Record.size()-2;
+      IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests);
+      InstructionList.push_back(IBI);
+      for (unsigned i = 0, e = NumDests; i != e; ++i) {
+        if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) {
+          IBI->addDestination(DestBB);
+        } else {
+          delete IBI;
+          return Error("Invalid record");
+        }
+      }
+      I = IBI;
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_INVOKE: {
+      // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
+      if (Record.size() < 4)
+        return Error("Invalid record");
+      AttributeSet PAL = getAttributes(Record[0]);
+      unsigned CCInfo = Record[1];
+      BasicBlock *NormalBB = getBasicBlock(Record[2]);
+      BasicBlock *UnwindBB = getBasicBlock(Record[3]);
+
+      unsigned OpNum = 4;
+      Value *Callee;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+        return Error("Invalid record");
+
+      PointerType *CalleeTy = dyn_cast<PointerType>(Callee->getType());
+      FunctionType *FTy = !CalleeTy ? nullptr :
+        dyn_cast<FunctionType>(CalleeTy->getElementType());
+
+      // Check that the right number of fixed parameters are here.
+      if (!FTy || !NormalBB || !UnwindBB ||
+          Record.size() < OpNum+FTy->getNumParams())
+        return Error("Invalid record");
+
+      SmallVector<Value*, 16> Ops;
+      for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+        Ops.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+        if (!Ops.back())
+          return Error("Invalid record");
+      }
+
+      if (!FTy->isVarArg()) {
+        if (Record.size() != OpNum)
+          return Error("Invalid record");
+      } else {
+        // Read type/value pairs for varargs params.
+        while (OpNum != Record.size()) {
+          Value *Op;
+          if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+            return Error("Invalid record");
+          Ops.push_back(Op);
+        }
+      }
+
+      I = InvokeInst::Create(Callee, NormalBB, UnwindBB, Ops);
+      InstructionList.push_back(I);
+      cast<InvokeInst>(I)->setCallingConv(
+        static_cast<CallingConv::ID>(CCInfo));
+      cast<InvokeInst>(I)->setAttributes(PAL);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval]
+      unsigned Idx = 0;
+      Value *Val = nullptr;
+      if (getValueTypePair(Record, Idx, NextValueNo, Val))
+        return Error("Invalid record");
+      I = ResumeInst::Create(Val);
+      InstructionList.push_back(I);
+      break;
+    }
+    case FUNC_CODE_INST_UNWIND_2_7: { // UNWIND_OLD
+      // 'unwind' instruction has been removed in LLVM 3.1
+      // Replace 'unwind' with 'landingpad' and 'resume'.
+      Type *ExnTy = StructType::get(Type::getInt8PtrTy(Context),
+                                    Type::getInt32Ty(Context), nullptr);
+
+      LandingPadInst *LP = LandingPadInst::Create(ExnTy, 1);
+      LP->setCleanup(true);
+
+      CurBB->getInstList().push_back(LP);
+      I = ResumeInst::Create(LP);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
+      I = new UnreachableInst(Context);
+      InstructionList.push_back(I);
+      break;
+    case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
+      if (Record.size() < 1 || ((Record.size()-1)&1))
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[0]);
+      if (!Ty)
+        return Error("Invalid record");
+
+      PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2);
+      InstructionList.push_back(PN);
+
+      for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) {
+        Value *V = getFnValueByID(Record[1+i], Ty);
+        BasicBlock *BB = getBasicBlock(Record[2+i]);
+        if (!V || !BB)
+          return Error("Invalid record");
+        PN->addIncoming(V, BB);
+      }
+      I = PN;
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_LANDINGPAD_OLD: {
+      // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?]
+      unsigned Idx = 0;
+      if (Record.size() < 4)
+        return Error("Invalid record");
+      Type *Ty = getTypeByID(Record[Idx++]);
+      if (!Ty)
+        return Error("Invalid record");
+      Value *PersFn = nullptr;
+      if (getValueTypePair(Record, Idx, NextValueNo, PersFn))
+        return Error("Invalid record");
+
+      bool IsCleanup = !!Record[Idx++];
+      unsigned NumClauses = Record[Idx++];
+      LandingPadInst *LP = LandingPadInst::Create(Ty, NumClauses);
+      LP->setCleanup(IsCleanup);
+      for (unsigned J = 0; J != NumClauses; ++J) {
+        LandingPadInst::ClauseType CT =
+          LandingPadInst::ClauseType(Record[Idx++]); (void)CT;
+        Value *Val;
+
+        if (getValueTypePair(Record, Idx, NextValueNo, Val)) {
+          delete LP;
+          return Error("Invalid record");
+        }
+
+        assert((CT != LandingPadInst::Catch ||
+                !isa<ArrayType>(Val->getType())) &&
+               "Catch clause has a invalid type!");
+        assert((CT != LandingPadInst::Filter ||
+                isa<ArrayType>(Val->getType())) &&
+               "Filter clause has invalid type!");
+        LP->addClause(cast<Constant>(Val));
+      }
+
+      I = LP;
+      InstructionList.push_back(I);
+      break;
+    }
+
+    case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align]
+      if (Record.size() != 4)
+        return Error("Invalid record");
+      PointerType *Ty =
+        dyn_cast_or_null<PointerType>(getTypeByID(Record[0]));
+      Type *OpTy = getTypeByID(Record[1]);
+      Value *Size = getFnValueByID(Record[2], OpTy);
+      unsigned Align = Record[3];
+      if (!Ty || !Size)
+        return Error("Invalid record");
+      I = new AllocaInst(Ty->getElementType(), Size, (1 << Align) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid record");
+
+      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_LOADATOMIC: {
+       // LOADATOMIC: [opty, op, align, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Op;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+          OpNum+4 != Record.size())
+        return Error("Invalid record");
+
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+      if (Ordering == NotAtomic || Ordering == Release ||
+          Ordering == AcquireRelease)
+        return Error("Invalid record");
+      if (Ordering != NotAtomic && Record[OpNum] == 0)
+        return Error("Invalid record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+
+      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1,
+                       Ordering, SynchScope);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_STORE_OLD: { // STORE2:[ptrty, ptr, val, align, vol]
+      unsigned OpNum = 0;
+      Value *Val, *Ptr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+          OpNum+2 != Record.size())
+        return Error("Invalid record");
+
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_STOREATOMIC: {
+      // STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Val, *Ptr;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+          OpNum+4 != Record.size())
+        return Error("Invalid record");
+
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+      if (Ordering == NotAtomic || Ordering == Acquire ||
+          Ordering == AcquireRelease)
+        return Error("Invalid record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+      if (Ordering != NotAtomic && Record[OpNum] == 0)
+        return Error("Invalid record");
+
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1,
+                        Ordering, SynchScope);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_CMPXCHG: {
+      // CMPXCHG:[ptrty, ptr, cmp, new, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Ptr, *Cmp, *New;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Cmp) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), New) ||
+          OpNum+3 != Record.size())
+        return Error("Invalid record");
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+1]);
+      if (Ordering == NotAtomic || Ordering == Unordered)
+        return Error("Invalid record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]);
+      I = new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, Ordering, SynchScope);
+      cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_ATOMICRMW: {
+      // ATOMICRMW:[ptrty, ptr, val, op, vol, ordering, synchscope]
+      unsigned OpNum = 0;
+      Value *Ptr, *Val;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+          getValue(Record, OpNum,
+                    cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
+          OpNum+4 != Record.size())
+        return Error("Invalid record");
+      AtomicRMWInst::BinOp Operation = GetDecodedRMWOperation(Record[OpNum]);
+      if (Operation < AtomicRMWInst::FIRST_BINOP ||
+          Operation > AtomicRMWInst::LAST_BINOP)
+        return Error("Invalid record");
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
+      if (Ordering == NotAtomic || Ordering == Unordered)
+        return Error("Invalid record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
+      I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SynchScope);
+      cast<AtomicRMWInst>(I)->setVolatile(Record[OpNum+1]);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_FENCE: { // FENCE:[ordering, synchscope]
+      if (2 != Record.size())
+        return Error("Invalid record");
+      AtomicOrdering Ordering = GetDecodedOrdering(Record[0]);
+      if (Ordering == NotAtomic || Ordering == Unordered ||
+          Ordering == Monotonic)
+        return Error("Invalid record");
+      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[1]);
+      I = new FenceInst(Context, Ordering, SynchScope);
+      InstructionList.push_back(I);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_CALL: {
+      // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+
+      AttributeSet PAL = getAttributes(Record[0]);
+      unsigned CCInfo = Record[1];
+
+      unsigned OpNum = 2;
+      Value *Callee;
+      if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+        return Error("Invalid record");
+
+      PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
+      FunctionType *FTy = nullptr;
+      if (OpTy) FTy = dyn_cast<FunctionType>(OpTy->getElementType());
+      if (!FTy || Record.size() < FTy->getNumParams()+OpNum)
+        return Error("Invalid record");
+
+      SmallVector<Value*, 16> Args;
+      // Read the fixed params.
+      for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+        if (FTy->getParamType(i)->isLabelTy())
+          Args.push_back(getBasicBlock(Record[OpNum]));
+        else
+          Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+        if (!Args.back())
+          return Error("Invalid record");
+      }
+
+      // Read type/value pairs for varargs params.
+      if (!FTy->isVarArg()) {
+        if (OpNum != Record.size())
+          return Error("Invalid record");
+      } else {
+        while (OpNum != Record.size()) {
+          Value *Op;
+          if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+            return Error("Invalid record");
+          Args.push_back(Op);
+        }
+      }
+
+      I = CallInst::Create(Callee, Args);
+      InstructionList.push_back(I);
+      cast<CallInst>(I)->setCallingConv(
+        static_cast<CallingConv::ID>(CCInfo>>1));
+      cast<CallInst>(I)->setTailCall(CCInfo & 1);
+      cast<CallInst>(I)->setAttributes(PAL);
+      break;
+    }
+    case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty]
+      if (Record.size() < 3)
+        return Error("Invalid record");
+      Type *OpTy = getTypeByID(Record[0]);
+      Value *Op = getFnValueByID(Record[1], OpTy);
+      Type *ResTy = getTypeByID(Record[2]);
+      if (!OpTy || !Op || !ResTy)
+        return Error("Invalid record");
+      I = new VAArgInst(Op, ResTy);
+      InstructionList.push_back(I);
+      break;
+    }
+    }
+
+    // Add instruction to end of current BB.  If there is no current BB, reject
+    // this file.
+    if (!CurBB) {
+      delete I;
+      return Error("Invalid instruction with no BB");
+    }
+    CurBB->getInstList().push_back(I);
+
+    // If this was a terminator instruction, move to the next block.
+    if (isa<TerminatorInst>(I)) {
+      ++CurBBNo;
+      CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : nullptr;
+    }
+
+    // Non-void values get registered in the value table for future use.
+    if (I && !I->getType()->isVoidTy())
+      ValueList.AssignValue(I, NextValueNo++);
+  }
+
+  // Check the function list for unresolved values.
+  if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
+    if (!A->getParent()) {
+      // We found at least one unresolved value.  Nuke them all to avoid leaks.
+      for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
+        if ((A = dyn_cast_or_null<Argument>(ValueList[i])) && !A->getParent()) {
+          A->replaceAllUsesWith(UndefValue::get(A->getType()));
+          delete A;
+        }
+      }
+      return Error("Never resolved value found in function");
+    }
+  }
+
+  // FIXME: Check for unresolved forward-declared metadata references
+  // and clean up leaks.
+
+  // See if anything took the address of blocks in this function.  If so,
+  // resolve them now.
+  DenseMap<Function*, std::vector<BlockAddrRefTy> >::iterator BAFRI =
+    BlockAddrFwdRefs.find(F);
+  if (BAFRI != BlockAddrFwdRefs.end()) {
+    std::vector<BlockAddrRefTy> &RefList = BAFRI->second;
+    for (unsigned i = 0, e = RefList.size(); i != e; ++i) {
+      unsigned BlockIdx = RefList[i].first;
+      if (BlockIdx >= FunctionBBs.size())
+        return Error("Invalid ID");
+
+      GlobalVariable *FwdRef = RefList[i].second;
+      FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx]));
+      FwdRef->eraseFromParent();
+    }
+
+    BlockAddrFwdRefs.erase(BAFRI);
+  }
+
+  // Trim the value list down to the size it was before we parsed this function.
+  ValueList.shrinkTo(ModuleValueListSize);
+  MDValueList.shrinkTo(ModuleMDValueListSize);
+  std::vector<BasicBlock*>().swap(FunctionBBs);
+  return std::error_code();
+}
+
+//===----------------------------------------------------------------------===//
+// GVMaterializer implementation
+//===----------------------------------------------------------------------===//
+
+void BitcodeReader::releaseBuffer() { Buffer.release(); }
+
+std::error_code BitcodeReader::materialize(GlobalValue *GV) {
+  if (std::error_code EC = materializeMetadata())
+    return EC;
+
+  Function *F = dyn_cast<Function>(GV);
+  // If it's not a function or is already material, ignore the request.
+  if (!F || !F->isMaterializable())
+    return std::error_code();
+
+  DenseMap<Function*, uint64_t>::iterator DFII = DeferredFunctionInfo.find(F);
+  assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!");
+
+  // Move the bit stream to the saved position of the deferred function body.
+  Stream.JumpToBit(DFII->second);
+
+  if (std::error_code EC = ParseFunctionBody(F))
+    return EC;
+  F->setIsMaterializable(false);
+
+  // Upgrade any old intrinsic calls in the function.
+  for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(),
+       E = UpgradedIntrinsics.end(); I != E; ++I) {
+    if (I->first != I->second) {
+      for (auto UI = I->first->user_begin(), UE = I->first->user_end();
+           UI != UE;) {
+        if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+          UpgradeIntrinsicCall(CI, I->second);
+      }
+    }
+  }
+
+  return std::error_code();
+}
+
+bool BitcodeReader::isDematerializable(const GlobalValue *GV) const {
+  const Function *F = dyn_cast<Function>(GV);
+  if (!F || F->isDeclaration())
+    return false;
+  return DeferredFunctionInfo.count(const_cast<Function*>(F));
+}
+
+void BitcodeReader::dematerialize(GlobalValue *GV) {
+  Function *F = dyn_cast<Function>(GV);
+  // If this function isn't dematerializable, this is a noop.
+  if (!F || !isDematerializable(F))
+    return;
+
+  assert(DeferredFunctionInfo.count(F) && "No info to read function later?");
+
+  // Just forget the function body, we can remat it later.
+  F->deleteBody();
+  F->setIsMaterializable(true);
+}
+
+std::error_code BitcodeReader::materializeModule() {
+  // Iterate over the module, deserializing any functions that are still on
+  // disk.
+  for (Module::iterator F = TheModule->begin(), E = TheModule->end();
+       F != E; ++F) {
+    if (std::error_code EC = materialize(&*F))
+      return EC;
+  }
+  // At this point, if there are any function bodies, the current bit is
+  // pointing to the END_BLOCK record after them. Now make sure the rest
+  // of the bits in the module have been read.
+  if (NextUnreadBit)
+    ParseModule(true);
+
+  // Upgrade any intrinsic calls that slipped through (should not happen!) and
+  // delete the old functions to clean up. We can't do this unless the entire
+  // module is materialized because there could always be another function body
+  // with calls to the old function.
+  for (std::vector<std::pair<Function*, Function*> >::iterator I =
+       UpgradedIntrinsics.begin(), E = UpgradedIntrinsics.end(); I != E; ++I) {
+    if (I->first != I->second) {
+      for (auto UI = I->first->user_begin(), UE = I->first->user_end();
+           UI != UE;) {
+        if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+          UpgradeIntrinsicCall(CI, I->second);
+      }
+      if (!I->first->use_empty())
+        I->first->replaceAllUsesWith(I->second);
+      I->first->eraseFromParent();
+    }
+  }
+  std::vector<std::pair<Function*, Function*> >().swap(UpgradedIntrinsics);
+
+  // Upgrade to new EH scheme. N.B. This will go away in 3.1.
+  UpgradeExceptionHandling(TheModule);
+
+  // Check debug info intrinsics.
+  CheckDebugInfoIntrinsics(TheModule);
+
+  return std::error_code();
+}
+
+std::vector<StructType *> BitcodeReader::getIdentifiedStructTypes() const {
+  return IdentifiedStructTypes;
+}
+
+std::error_code BitcodeReader::InitStream() {
+  if (LazyStreamer)
+    return InitLazyStream();
+  return InitStreamFromBuffer();
+}
+
+std::error_code BitcodeReader::InitStreamFromBuffer() {
+  const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart();
+  const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
+
+  if (Buffer->getBufferSize() & 3)
+    return Error("Invalid bitcode signature");
+
+  // If we have a wrapper header, parse it and ignore the non-bc file contents.
+  // The magic number is 0x0B17C0DE stored in little endian.
+  if (isBitcodeWrapper(BufPtr, BufEnd))
+    if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))
+      return Error("Invalid bitcode wrapper header");
+
+  StreamFile.reset(new BitstreamReader(BufPtr, BufEnd));
+  Stream.init(&*StreamFile);
+
+  return std::error_code();
+}
+
+std::error_code BitcodeReader::InitLazyStream() {
+  // Check and strip off the bitcode wrapper; BitstreamReader expects never to
+  // see it.
+  auto OwnedBytes = llvm::make_unique<StreamingMemoryObject>(
+      std::move(LazyStreamer));
+  StreamingMemoryObject &Bytes = *OwnedBytes;
+  StreamFile = llvm::make_unique<BitstreamReader>(std::move(OwnedBytes));
+  Stream.init(&*StreamFile);
+
+  unsigned char buf[16];
+  if (Bytes.readBytes(buf, 16, 0) != 16)
+    return Error("Invalid bitcode signature");
+
+  if (!isBitcode(buf, buf + 16))
+    return Error("Invalid bitcode signature");
+
+  if (isBitcodeWrapper(buf, buf + 4)) {
+    const unsigned char *bitcodeStart = buf;
+    const unsigned char *bitcodeEnd = buf + 16;
+    SkipBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false);
+    Bytes.dropLeadingBytes(bitcodeStart - buf);
+    Bytes.setKnownObjectSize(bitcodeEnd - bitcodeStart);
+  }
+  return std::error_code();
+}
+
+namespace {
+class BitcodeErrorCategoryType : public std::error_category {
+  const char *name() const LLVM_NOEXCEPT override {
+    return "llvm.bitcode";
+  }
+  std::string message(int IE) const override {
+    BitcodeError E = static_cast<BitcodeError>(IE);
+    switch (E) {
+    case BitcodeError::InvalidBitcodeSignature:
+      return "Invalid bitcode signature";
+    case BitcodeError::CorruptedBitcode:
+      return "Corrupted bitcode";
+    }
+    llvm_unreachable("Unknown error type!");
+  }
+};
+}
+
+static ManagedStatic<BitcodeErrorCategoryType> ErrorCategory;
+
+const std::error_category &BitcodeReader::BitcodeErrorCategory() {
+  return *ErrorCategory;
+}
+
+//===----------------------------------------------------------------------===//
+// External interface
+//===----------------------------------------------------------------------===//
+
+/// getLazyBitcodeModule - lazy function-at-a-time loading from a file.
+///
+static llvm::ErrorOr<llvm::Module *>
+getLazyBitcodeModuleImpl(std::unique_ptr<MemoryBuffer> &&Buffer,
+                         LLVMContext &Context, bool WillMaterializeAll,
+                         const DiagnosticHandlerFunction &DiagnosticHandler) {
+  Module *M = new Module(Buffer->getBufferIdentifier(), Context);
+  BitcodeReader *R =
+      new BitcodeReader(Buffer.get(), Context, DiagnosticHandler);
+  M->setMaterializer(R);
+
+  auto cleanupOnError = [&](std::error_code EC) {
+    R->releaseBuffer(); // Never take ownership on error.
+    delete M;  // Also deletes R.
+    return EC;
+  };
+
+  if (std::error_code EC = R->ParseBitcodeInto(M))
+    return cleanupOnError(EC);
+
+  Buffer.release(); // The BitcodeReader owns it now.
+  return M;
+}
+
+llvm::ErrorOr<Module *>
+llvm_3_0::getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
+                           LLVMContext &Context,
+                           const DiagnosticHandlerFunction &DiagnosticHandler) {
+  return getLazyBitcodeModuleImpl(std::move(Buffer), Context, false,
+                                  DiagnosticHandler);
+}
+
+/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
+/// If an error occurs, return null and fill in *ErrMsg if non-null.
+llvm::ErrorOr<llvm::Module *>
+llvm_3_0::parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context,
+                       const DiagnosticHandlerFunction &DiagnosticHandler) {
+  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
+  ErrorOr<Module *> ModuleOrErr = getLazyBitcodeModuleImpl(
+      std::move(Buf), Context, true, DiagnosticHandler);
+  if (!ModuleOrErr)
+    return ModuleOrErr;
+  Module *M = ModuleOrErr.get();
+  // Read in the entire module, and destroy the BitcodeReader.
+  if (std::error_code EC = M->materializeAll()) {
+    delete M;
+    return EC;
+  }
+
+  return M;
+}
+
+std::string
+llvm_3_0::getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context,
+                             DiagnosticHandlerFunction DiagnosticHandler) {
+  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
+  auto R = llvm::make_unique<BitcodeReader>(Buf.release(), Context,
+                                            DiagnosticHandler);
+  ErrorOr<std::string> Triple = R->parseTriple();
+  if (Triple.getError())
+    return "";
+  return Triple.get();
+}
diff --git a/libbcc/bcinfo/BitReader_3_0/CMakeLists.txt b/libbcc/bcinfo/BitReader_3_0/CMakeLists.txt
new file mode 100644
index 0000000..37bebc4
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_3_0/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_llvm_library(LLVMBitReader
+  BitReader.cpp
+  BitcodeReader.cpp
+  )
+
+add_llvm_library_dependencies(LLVMBitReader
+  LLVMCore
+  LLVMSupport
+  )
diff --git a/libbcc/bcinfo/BitReader_3_0/LLVMBuild.txt b/libbcc/bcinfo/BitReader_3_0/LLVMBuild.txt
new file mode 100644
index 0000000..948b335
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_3_0/LLVMBuild.txt
@@ -0,0 +1,23 @@
+;===- ./lib/Bitcode/Reader/LLVMBuild.txt -----------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = BitReader
+parent = Bitcode
+required_libraries = Core Support
+
diff --git a/libbcc/bcinfo/BitReader_3_0/Makefile b/libbcc/bcinfo/BitReader_3_0/Makefile
new file mode 100644
index 0000000..59af8d5
--- /dev/null
+++ b/libbcc/bcinfo/BitReader_3_0/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMBitReader
+BUILD_ARCHIVE = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/libbcc/bcinfo/BitcodeTranslator.cpp b/libbcc/bcinfo/BitcodeTranslator.cpp
new file mode 100644
index 0000000..3621c82
--- /dev/null
+++ b/libbcc/bcinfo/BitcodeTranslator.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright 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.
+ * 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 "bcinfo/BitcodeTranslator.h"
+
+#include "bcinfo/BitcodeWrapper.h"
+
+#include "BitReader_2_7/BitReader_2_7.h"
+#include "BitReader_3_0/BitReader_3_0.h"
+
+#include "BitWriter_3_2/ReaderWriter_3_2.h"
+
+#define LOG_TAG "bcinfo"
+#include <cutils/log.h>
+
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <cstdlib>
+#include <climits>
+
+namespace bcinfo {
+
+/**
+ * Define minimum and maximum target API versions. These correspond to the
+ * same API levels used by the standard Android SDK.
+ *
+ * LLVM 2.7
+ *  11 - Honeycomb
+ *  12 - Honeycomb MR1
+ *  13 - Honeycomb MR2
+ *
+ * LLVM 3.0
+ *  14 - Ice Cream Sandwich
+ *  15 - Ice Cream Sandwich MR1
+ *
+ * LLVM 3.1
+ *  16 - Ice Cream Sandwich MR2
+ */
+static const unsigned int kMinimumAPIVersion     = 11;
+static const unsigned int kMaximumAPIVersion     = RS_VERSION;
+static const unsigned int kCurrentAPIVersion     = 10000;
+static const unsigned int kDevelopmentAPIVersion = UINT_MAX;
+
+/**
+ * The minimum version which does not require translation (i.e. is already
+ * compatible with LLVM's default bitcode reader).
+ */
+static const unsigned int kMinimumUntranslatedVersion = 16;
+static const unsigned int kMinimumCompatibleVersion_LLVM_3_0 = 14;
+static const unsigned int kMinimumCompatibleVersion_LLVM_2_7 = 11;
+
+
+BitcodeTranslator::BitcodeTranslator(const char *bitcode, size_t bitcodeSize,
+                                     unsigned int version)
+    : mBitcode(bitcode), mBitcodeSize(bitcodeSize), mTranslatedBitcode(nullptr),
+      mTranslatedBitcodeSize(0), mVersion(version) {
+  return;
+}
+
+
+BitcodeTranslator::~BitcodeTranslator() {
+  if (mVersion < kMinimumUntranslatedVersion) {
+    // We didn't actually do a translation in the alternate case, so deleting
+    // the bitcode would be improper.
+    delete [] mTranslatedBitcode;
+  }
+  mTranslatedBitcode = nullptr;
+  return;
+}
+
+
+bool BitcodeTranslator::translate() {
+  if (!mBitcode || !mBitcodeSize) {
+    ALOGE("Invalid/empty bitcode");
+    return false;
+  }
+
+  BitcodeWrapper BCWrapper(mBitcode, mBitcodeSize);
+  if (BCWrapper.getTargetAPI() != mVersion) {
+    ALOGE("Bitcode wrapper (%u) and translator (%u) disagree about target API",
+          BCWrapper.getTargetAPI(), mVersion);
+  }
+
+  if ((mVersion != kDevelopmentAPIVersion) &&
+      (mVersion != kCurrentAPIVersion)     &&
+       ((mVersion < kMinimumAPIVersion) ||
+        (mVersion > kMaximumAPIVersion))) {
+    ALOGE("Invalid API version: %u is out of range ('%u' - '%u')", mVersion,
+         kMinimumAPIVersion, kMaximumAPIVersion);
+    return false;
+  }
+
+  // We currently don't need to transcode any API version higher than 14 or
+  // the current API version (i.e. 10000)
+  if (mVersion >= kMinimumUntranslatedVersion) {
+    mTranslatedBitcode = mBitcode;
+    mTranslatedBitcodeSize = mBitcodeSize;
+    return true;
+  }
+
+  // Do the actual transcoding by invoking a 2.7-era bitcode reader that can
+  // then write the bitcode back out in a more modern (acceptable) version.
+  std::unique_ptr<llvm::LLVMContext> mContext(new llvm::LLVMContext());
+  std::unique_ptr<llvm::MemoryBuffer> MEM(
+    llvm::MemoryBuffer::getMemBuffer(
+      llvm::StringRef(mBitcode, mBitcodeSize), "", false));
+  std::string error;
+  llvm::ErrorOr<llvm::MemoryBufferRef> MBOrErr = MEM->getMemBufferRef();
+
+  llvm::ErrorOr<llvm::Module *> MOrErr(nullptr);
+
+  if (mVersion >= kMinimumCompatibleVersion_LLVM_3_0) {
+    MOrErr = llvm_3_0::parseBitcodeFile(*MBOrErr, *mContext);
+  } else if (mVersion >= kMinimumCompatibleVersion_LLVM_2_7) {
+    MOrErr = llvm_2_7::parseBitcodeFile(*MBOrErr, *mContext);
+  } else {
+    ALOGE("No compatible bitcode reader for API version %d", mVersion);
+    return false;
+  }
+
+  if (std::error_code EC = MOrErr.getError()) {
+    ALOGE("Could not parse bitcode file");
+    ALOGE("%s", EC.message().c_str());
+    return false;
+  }
+
+  // Module ownership is handled by the context, so we don't need to free it.
+  llvm::Module *module = MOrErr.get();
+
+  std::string Buffer;
+
+  llvm::raw_string_ostream OS(Buffer);
+  // Use the LLVM 3.2 bitcode writer, instead of the top-of-tree version.
+  llvm_3_2::WriteBitcodeToFile(module, OS);
+  OS.flush();
+
+  AndroidBitcodeWrapper wrapper;
+  size_t actualWrapperLen = writeAndroidBitcodeWrapper(
+      &wrapper, Buffer.size(), kMinimumUntranslatedVersion,
+      BCWrapper.getCompilerVersion(), BCWrapper.getOptimizationLevel());
+  if (!actualWrapperLen) {
+    ALOGE("Couldn't produce bitcode wrapper!");
+    return false;
+  }
+
+  mTranslatedBitcodeSize = actualWrapperLen + Buffer.size();
+  char *c = new char[mTranslatedBitcodeSize];
+  memcpy(c, &wrapper, actualWrapperLen);
+  memcpy(c + actualWrapperLen, Buffer.c_str(), Buffer.size());
+
+  mTranslatedBitcode = c;
+
+  return true;
+}
+
+}  // namespace bcinfo
diff --git a/libbcc/bcinfo/BitcodeWrapper.cpp b/libbcc/bcinfo/BitcodeWrapper.cpp
new file mode 100644
index 0000000..1258067
--- /dev/null
+++ b/libbcc/bcinfo/BitcodeWrapper.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 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.
+ * 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 "bcinfo/BitcodeWrapper.h"
+#include "bcinfo/Wrap/bitcode_wrapperer.h"
+#include "bcinfo/Wrap/in_memory_wrapper_input.h"
+
+#define LOG_TAG "bcinfo"
+#include <cutils/log.h>
+
+#include "llvm/Bitcode/ReaderWriter.h"
+
+#include <cstdlib>
+#include <cstring>
+
+namespace bcinfo {
+
+BitcodeWrapper::BitcodeWrapper(const char *bitcode, size_t bitcodeSize)
+    : mFileType(BC_NOT_BC), mBitcode(bitcode),
+      mBitcodeSize(bitcodeSize),
+      mHeaderVersion(0), mTargetAPI(0), mCompilerVersion(0),
+      mOptimizationLevel(3) {
+  InMemoryWrapperInput inMem(mBitcode, mBitcodeSize);
+  BitcodeWrapperer wrapperer(&inMem, nullptr);
+  if (wrapperer.IsInputBitcodeWrapper()) {
+    mFileType = BC_WRAPPER;
+    mHeaderVersion = wrapperer.getAndroidHeaderVersion();
+    mTargetAPI = wrapperer.getAndroidTargetAPI();
+    mCompilerVersion = wrapperer.getAndroidCompilerVersion();
+    mOptimizationLevel = wrapperer.getAndroidOptimizationLevel();
+  } else if (wrapperer.IsInputBitcodeFile()) {
+    mFileType = BC_RAW;
+  }
+}
+
+
+BitcodeWrapper::~BitcodeWrapper() {
+  return;
+}
+
+
+bool BitcodeWrapper::unwrap() {
+  return mFileType != BC_NOT_BC;
+}
+
+}  // namespace bcinfo
+
diff --git a/libbcc/bcinfo/MetadataExtractor.cpp b/libbcc/bcinfo/MetadataExtractor.cpp
new file mode 100644
index 0000000..48a2ecb
--- /dev/null
+++ b/libbcc/bcinfo/MetadataExtractor.cpp
@@ -0,0 +1,685 @@
+/*
+ * Copyright 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.
+ * 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 "bcinfo/MetadataExtractor.h"
+
+#include "bcinfo/BitcodeWrapper.h"
+#include "rsDefines.h"
+
+#define LOG_TAG "bcinfo"
+#include <cutils/log.h>
+#ifdef __ANDROID__
+#include <cutils/properties.h>
+#endif
+
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <cstdlib>
+
+namespace bcinfo {
+
+namespace {
+
+llvm::StringRef getStringOperand(const llvm::Metadata *node) {
+  if (auto *mds = llvm::dyn_cast_or_null<const llvm::MDString>(node)) {
+    return mds->getString();
+  }
+  return llvm::StringRef();
+}
+
+bool extractUIntFromMetadataString(uint32_t *value,
+    const llvm::Metadata *m) {
+  llvm::StringRef SigString = getStringOperand(m);
+  if (SigString != "") {
+    if (!SigString.getAsInteger(10, *value)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+const char *createStringFromValue(llvm::Metadata *m) {
+  auto ref = getStringOperand(m);
+  char *c = new char[ref.size() + 1];
+  memcpy(c, ref.data(), ref.size());
+  c[ref.size()] = '\0';
+  return c;
+}
+
+const char *createStringFromOptionalValue(llvm::MDNode *n, unsigned opndNum) {
+  llvm::Metadata *opnd;
+  if (opndNum >= n->getNumOperands() || !(opnd = n->getOperand(opndNum)))
+    return nullptr;
+  return createStringFromValue(opnd);
+}
+
+// Collect metadata from NamedMDNodes that contain a list of names
+// (strings).
+//
+// Inputs:
+//
+// NamedMetadata - An LLVM metadata node, each of whose operands have
+// a string as their first entry
+//
+// NameList - A reference that will hold an allocated array of strings
+//
+// Count - A reference that will hold the length of the allocated
+// array of strings
+//
+// Return value:
+//
+// Return true on success, false on error.
+//
+// Upon success, the function sets NameList to an array of strings
+// corresponding the names found in the metadata. The function sets
+// Count to the number of entries in NameList.
+//
+// An error occurs if one of the metadata operands doesn't have a
+// first entry.
+bool populateNameMetadata(const llvm::NamedMDNode *NameMetadata,
+                          const char **&NameList, size_t &Count) {
+  if (!NameMetadata) {
+    NameList = nullptr;
+    Count = 0;
+    return true;
+  }
+
+  Count = NameMetadata->getNumOperands();
+  if (!Count) {
+    NameList = nullptr;
+    return true;
+  }
+
+  NameList = new const char *[Count];
+
+  for (size_t i = 0; i < Count; i++) {
+    llvm::MDNode *Name = NameMetadata->getOperand(i);
+    if (Name && Name->getNumOperands() > 0) {
+      NameList[i] = createStringFromValue(Name->getOperand(0));
+    } else {
+      ALOGE("Metadata operand does not contain a name string");
+      for (size_t AllocatedIndex = 0; AllocatedIndex < i; AllocatedIndex++) {
+        delete [] NameList[AllocatedIndex];
+      }
+      delete [] NameList;
+      NameList = nullptr;
+      Count = 0;
+
+      return false;
+    }
+  }
+
+  return true;
+}
+
+} // end anonymous namespace
+
+// Name of metadata node where pragma info resides (should be synced with
+// slang.cpp)
+static const llvm::StringRef PragmaMetadataName = "#pragma";
+
+// Name of metadata node where exported variable names reside (should be
+// synced with slang_rs_metadata.h)
+static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";
+
+// Name of metadata node where exported function names reside (should be
+// synced with slang_rs_metadata.h)
+static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
+
+// Name of metadata node where exported ForEach name information resides
+// (should be synced with slang_rs_metadata.h)
+static const llvm::StringRef ExportForEachNameMetadataName =
+    "#rs_export_foreach_name";
+
+// Name of metadata node where exported ForEach signature information resides
+// (should be synced with slang_rs_metadata.h)
+static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
+
+// Name of metadata node where exported general reduce information resides
+// (should be synced with slang_rs_metadata.h)
+static const llvm::StringRef ExportReduceMetadataName = "#rs_export_reduce";
+
+// Name of metadata node where RS object slot info resides (should be
+// synced with slang_rs_metadata.h)
+static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
+
+static const llvm::StringRef ThreadableMetadataName = "#rs_is_threadable";
+
+// Name of metadata node where the checksum for this build is stored.  (should
+// be synced with libbcc/lib/Core/Source.cpp)
+static const llvm::StringRef ChecksumMetadataName = "#rs_build_checksum";
+
+// Name of metadata node which contains a list of compile units that have debug
+// metadata. If this is null then there is no debug metadata in the compile
+// unit.
+static const llvm::StringRef DebugInfoMetadataName = "llvm.dbg.cu";
+
+MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
+    : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
+      mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
+      mExportReduceCount(0), mExportVarNameList(nullptr),
+      mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
+      mExportForEachSignatureList(nullptr),
+      mExportForEachInputCountList(nullptr),
+      mExportReduceList(nullptr),
+      mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
+      mObjectSlotCount(0), mObjectSlotList(nullptr),
+      mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
+      mBuildChecksum(nullptr), mHasDebugInfo(false) {
+  BitcodeWrapper wrapper(bitcode, bitcodeSize);
+  mTargetAPI = wrapper.getTargetAPI();
+  mCompilerVersion = wrapper.getCompilerVersion();
+  mOptimizationLevel = wrapper.getOptimizationLevel();
+}
+
+MetadataExtractor::MetadataExtractor(const llvm::Module *module)
+    : mModule(module), mBitcode(nullptr), mBitcodeSize(0),
+      mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
+      mExportReduceCount(0), mExportVarNameList(nullptr),
+      mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
+      mExportForEachSignatureList(nullptr),
+      mExportForEachInputCountList(nullptr),
+      mExportReduceList(nullptr),
+      mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
+      mObjectSlotCount(0), mObjectSlotList(nullptr),
+      mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
+      mBuildChecksum(nullptr) {
+  mCompilerVersion = RS_VERSION;  // Default to the actual current version.
+  mOptimizationLevel = 3;
+}
+
+
+MetadataExtractor::~MetadataExtractor() {
+  if (mExportVarNameList) {
+    for (size_t i = 0; i < mExportVarCount; i++) {
+        delete [] mExportVarNameList[i];
+        mExportVarNameList[i] = nullptr;
+    }
+  }
+  delete [] mExportVarNameList;
+  mExportVarNameList = nullptr;
+
+  if (mExportFuncNameList) {
+    for (size_t i = 0; i < mExportFuncCount; i++) {
+        delete [] mExportFuncNameList[i];
+        mExportFuncNameList[i] = nullptr;
+    }
+  }
+  delete [] mExportFuncNameList;
+  mExportFuncNameList = nullptr;
+
+  if (mExportForEachNameList) {
+    for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
+        delete [] mExportForEachNameList[i];
+        mExportForEachNameList[i] = nullptr;
+    }
+  }
+  delete [] mExportForEachNameList;
+  mExportForEachNameList = nullptr;
+
+  delete [] mExportForEachSignatureList;
+  mExportForEachSignatureList = nullptr;
+
+  delete [] mExportForEachInputCountList;
+  mExportForEachInputCountList = nullptr;
+
+  delete [] mExportReduceList;
+  mExportReduceList = nullptr;
+
+  for (size_t i = 0; i < mPragmaCount; i++) {
+    if (mPragmaKeyList) {
+      delete [] mPragmaKeyList[i];
+      mPragmaKeyList[i] = nullptr;
+    }
+    if (mPragmaValueList) {
+      delete [] mPragmaValueList[i];
+      mPragmaValueList[i] = nullptr;
+    }
+  }
+  delete [] mPragmaKeyList;
+  mPragmaKeyList = nullptr;
+  delete [] mPragmaValueList;
+  mPragmaValueList = nullptr;
+
+  delete [] mObjectSlotList;
+  mObjectSlotList = nullptr;
+
+  delete [] mBuildChecksum;
+
+  return;
+}
+
+
+bool MetadataExtractor::populateObjectSlotMetadata(
+    const llvm::NamedMDNode *ObjectSlotMetadata) {
+  if (!ObjectSlotMetadata) {
+    return true;
+  }
+
+  mObjectSlotCount = ObjectSlotMetadata->getNumOperands();
+
+  if (!mObjectSlotCount) {
+    return true;
+  }
+
+  uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
+  memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));
+
+  for (size_t i = 0; i < mObjectSlotCount; i++) {
+    llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
+    if (ObjectSlot != nullptr && ObjectSlot->getNumOperands() == 1) {
+      if (!extractUIntFromMetadataString(&TmpSlotList[i], ObjectSlot->getOperand(0))) {
+        ALOGE("Non-integer object slot value");
+        return false;
+      }
+    } else {
+      ALOGE("Corrupt object slot information");
+      return false;
+    }
+  }
+
+  mObjectSlotList = TmpSlotList;
+
+  return true;
+}
+
+
+void MetadataExtractor::populatePragmaMetadata(
+    const llvm::NamedMDNode *PragmaMetadata) {
+  if (!PragmaMetadata) {
+    return;
+  }
+
+  mPragmaCount = PragmaMetadata->getNumOperands();
+  if (!mPragmaCount) {
+    return;
+  }
+
+  const char **TmpKeyList = new const char*[mPragmaCount];
+  const char **TmpValueList = new const char*[mPragmaCount];
+
+  for (size_t i = 0; i < mPragmaCount; i++) {
+    llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
+    if (Pragma != nullptr && Pragma->getNumOperands() == 2) {
+      llvm::Metadata *PragmaKeyMDS = Pragma->getOperand(0);
+      TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
+      llvm::Metadata *PragmaValueMDS = Pragma->getOperand(1);
+      TmpValueList[i] = createStringFromValue(PragmaValueMDS);
+    }
+  }
+
+  mPragmaKeyList = TmpKeyList;
+  mPragmaValueList = TmpValueList;
+
+  // 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 FullPragmaSeen = false;
+  for (size_t i = 0; i < mPragmaCount; i++) {
+    if (!Relaxed.compare(mPragmaKeyList[i])) {
+      RelaxedPragmaSeen = true;
+    } else if (!Imprecise.compare(mPragmaKeyList[i])) {
+      ALOGW("rs_fp_imprecise is deprecated.  Assuming rs_fp_relaxed instead.");
+      RelaxedPragmaSeen = true;
+    } else if (!Full.compare(mPragmaKeyList[i])) {
+      FullPragmaSeen = true;
+    }
+  }
+
+  if (RelaxedPragmaSeen && FullPragmaSeen) {
+    ALOGE("Full and relaxed precision specified at the same time!");
+  }
+  mRSFloatPrecision = RelaxedPragmaSeen ? RS_FP_Relaxed : RS_FP_Full;
+
+#ifdef __ANDROID__
+  // Provide an override for precsiion 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)) {
+      ALOGI("Switching to RS FP relaxed mode via setprop");
+      mRSFloatPrecision = RS_FP_Relaxed;
+    } else if (!Imprecise.compare(PrecisionPropBuf)) {
+      ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was "
+            "specified but is deprecated ");
+      mRSFloatPrecision = RS_FP_Relaxed;
+    } else if (!Full.compare(PrecisionPropBuf)) {
+      ALOGI("Switching to RS FP full mode via setprop");
+      mRSFloatPrecision = RS_FP_Full;
+    } else {
+      ALOGE("Unrecognized debug.rs.precision %s", PrecisionPropBuf);
+    }
+  }
+#endif
+}
+
+uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
+                                               uint32_t Signature) {
+
+  if (hasForEachSignatureIn(Signature)) {
+    uint32_t OtherCount = 0;
+
+    OtherCount += hasForEachSignatureUsrData(Signature);
+    OtherCount += hasForEachSignatureX(Signature);
+    OtherCount += hasForEachSignatureY(Signature);
+    OtherCount += hasForEachSignatureZ(Signature);
+    OtherCount += hasForEachSignatureCtxt(Signature);
+    OtherCount += hasForEachSignatureOut(Signature) &&
+                  Function->getReturnType()->isVoidTy();
+
+    return Function->arg_size() - OtherCount;
+
+  } else {
+    return 0;
+  }
+}
+
+
+bool MetadataExtractor::populateForEachMetadata(
+    const llvm::NamedMDNode *Names,
+    const llvm::NamedMDNode *Signatures) {
+  if (!Names && !Signatures && mCompilerVersion == 0) {
+    // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
+    // section for ForEach. We generate a full signature for a "root" function
+    // which means that we need to set the bottom 5 bits in the mask.
+    mExportForEachSignatureCount = 1;
+    char **TmpNameList = new char*[mExportForEachSignatureCount];
+    size_t RootLen = strlen(kRoot) + 1;
+    TmpNameList[0] = new char[RootLen];
+    strncpy(TmpNameList[0], kRoot, RootLen);
+
+    uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
+    TmpSigList[0] = 0x1f;
+
+    mExportForEachNameList = (const char**)TmpNameList;
+    mExportForEachSignatureList = TmpSigList;
+    return true;
+  }
+
+  if (Signatures) {
+    mExportForEachSignatureCount = Signatures->getNumOperands();
+    if (!mExportForEachSignatureCount) {
+      return true;
+    }
+  } else {
+    mExportForEachSignatureCount = 0;
+    mExportForEachSignatureList = nullptr;
+    return true;
+  }
+
+  uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
+  const char **TmpNameList = new const char*[mExportForEachSignatureCount];
+  uint32_t *TmpInputCountList = new uint32_t[mExportForEachSignatureCount];
+
+  for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
+    llvm::MDNode *SigNode = Signatures->getOperand(i);
+    if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
+      if (!extractUIntFromMetadataString(&TmpSigList[i], SigNode->getOperand(0))) {
+        ALOGE("Non-integer signature value");
+        return false;
+      }
+    } else {
+      ALOGE("Corrupt signature information");
+      return false;
+    }
+  }
+
+  if (Names) {
+    for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
+      llvm::MDNode *Name = Names->getOperand(i);
+      if (Name != nullptr && Name->getNumOperands() == 1) {
+        TmpNameList[i] = createStringFromValue(Name->getOperand(0));
+
+        // Note that looking up the function by name can fail: One of
+        // the uses of MetadataExtractor is as part of the
+        // RSEmbedInfoPass, which bcc_compat runs sufficiently late in
+        // the phase order that RSKernelExpandPass has already run and
+        // the original (UNexpanded) kernel function (TmpNameList[i])
+        // may have been deleted as having no references (if it has
+        // been inlined into the expanded kernel function and is
+        // otherwise unreferenced).
+        llvm::Function *Func =
+            mModule->getFunction(llvm::StringRef(TmpNameList[i]));
+
+        TmpInputCountList[i] = (Func != nullptr) ?
+          calculateNumInputs(Func, TmpSigList[i]) : 0;
+      }
+    }
+  } else {
+    if (mExportForEachSignatureCount != 1) {
+      ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
+            mExportForEachSignatureCount);
+    }
+    char *RootName = new char[5];
+    strncpy(RootName, "root", 5);
+    TmpNameList[0] = RootName;
+  }
+
+  mExportForEachNameList = TmpNameList;
+  mExportForEachSignatureList = TmpSigList;
+  mExportForEachInputCountList = TmpInputCountList;
+
+  return true;
+}
+
+
+bool MetadataExtractor::populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata) {
+  mExportReduceCount = 0;
+  mExportReduceList = nullptr;
+
+  if (!ReduceMetadata || !(mExportReduceCount = ReduceMetadata->getNumOperands()))
+    return true;
+
+  Reduce *TmpReduceList = new Reduce[mExportReduceCount];
+
+  for (size_t i = 0; i < mExportReduceCount; i++) {
+    llvm::MDNode *Node = ReduceMetadata->getOperand(i);
+    if (!Node || Node->getNumOperands() < 3) {
+      ALOGE("Missing reduce metadata");
+      return false;
+    }
+
+    TmpReduceList[i].mReduceName = createStringFromValue(Node->getOperand(0));
+
+    if (!extractUIntFromMetadataString(&TmpReduceList[i].mAccumulatorDataSize,
+                                       Node->getOperand(1))) {
+      ALOGE("Non-integer accumulator data size value in reduce metadata");
+      return false;
+    }
+
+    llvm::MDNode *AccumulatorNode = llvm::dyn_cast<llvm::MDNode>(Node->getOperand(2));
+    if (!AccumulatorNode || AccumulatorNode->getNumOperands() != 2) {
+      ALOGE("Malformed accumulator node in reduce metadata");
+      return false;
+    }
+    TmpReduceList[i].mAccumulatorName = createStringFromValue(AccumulatorNode->getOperand(0));
+    if (!extractUIntFromMetadataString(&TmpReduceList[i].mSignature,
+                                       AccumulatorNode->getOperand(1))) {
+      ALOGE("Non-integer signature value in reduce metadata");
+      return false;
+    }
+    // Note that looking up the function by name can fail: One of the
+    // uses of MetadataExtractor is as part of the RSEmbedInfoPass,
+    // which bcc_compat runs sufficiently late in the phase order that
+    // RSKernelExpandPass has already run and the original
+    // (UNexpanded) accumulator function (mAccumulatorName) may have
+    // been deleted as having no references (if it has been inlined
+    // into the expanded accumulator function and is otherwise
+    // unreferenced).
+    llvm::Function *Func =
+        mModule->getFunction(llvm::StringRef(TmpReduceList[i].mAccumulatorName));
+    // Why calculateNumInputs() - 1?  The "-1" is because we don't
+    // want to treat the accumulator argument as an input.
+    TmpReduceList[i].mInputCount = (Func ? calculateNumInputs(Func, TmpReduceList[i].mSignature) - 1 : 0);
+
+    TmpReduceList[i].mInitializerName = createStringFromOptionalValue(Node, 3);
+    TmpReduceList[i].mCombinerName = createStringFromOptionalValue(Node, 4);
+    TmpReduceList[i].mOutConverterName = createStringFromOptionalValue(Node, 5);
+    TmpReduceList[i].mHalterName = createStringFromOptionalValue(Node, 6);
+  }
+
+  mExportReduceList = TmpReduceList;
+  return true;
+}
+
+void MetadataExtractor::readThreadableFlag(
+    const llvm::NamedMDNode *ThreadableMetadata) {
+
+  // Scripts are threadable by default.  If we read a valid metadata value for
+  // 'ThreadableMetadataName' and it is set to 'no', we mark script as non
+  // threadable.  All other exception paths retain the default value.
+
+  mIsThreadable = true;
+  if (ThreadableMetadata == nullptr)
+    return;
+
+  llvm::MDNode *mdNode = ThreadableMetadata->getOperand(0);
+  if (mdNode == nullptr)
+    return;
+
+  llvm::Metadata *mdValue = mdNode->getOperand(0);
+  if (mdValue == nullptr)
+    return;
+
+  if (getStringOperand(mdValue) == "no")
+    mIsThreadable = false;
+}
+
+void MetadataExtractor::readBuildChecksumMetadata(
+    const llvm::NamedMDNode *ChecksumMetadata) {
+
+  if (ChecksumMetadata == nullptr)
+    return;
+
+  llvm::MDNode *mdNode = ChecksumMetadata->getOperand(0);
+  if (mdNode == nullptr)
+    return;
+
+  llvm::Metadata *mdValue = mdNode->getOperand(0);
+  if (mdValue == nullptr)
+    return;
+
+  mBuildChecksum = createStringFromValue(mdValue);
+}
+
+bool MetadataExtractor::extract() {
+  if (!(mBitcode && mBitcodeSize) && !mModule) {
+    ALOGE("Invalid/empty bitcode/module");
+    return false;
+  }
+
+  std::unique_ptr<llvm::LLVMContext> mContext;
+  bool shouldNullModule = false;
+
+  if (!mModule) {
+    mContext.reset(new llvm::LLVMContext());
+    std::unique_ptr<llvm::MemoryBuffer> MEM(
+      llvm::MemoryBuffer::getMemBuffer(
+        llvm::StringRef(mBitcode, mBitcodeSize), "", false));
+    std::string error;
+
+    llvm::ErrorOr<std::unique_ptr<llvm::Module> > errval =
+        llvm::parseBitcodeFile(MEM.get()->getMemBufferRef(), *mContext);
+    if (std::error_code ec = errval.getError()) {
+        ALOGE("Could not parse bitcode file");
+        ALOGE("%s", ec.message().c_str());
+        return false;
+    }
+
+    mModule = errval.get().release();
+    shouldNullModule = true;
+  }
+
+  const llvm::NamedMDNode *ExportVarMetadata =
+      mModule->getNamedMetadata(ExportVarMetadataName);
+  const llvm::NamedMDNode *ExportFuncMetadata =
+      mModule->getNamedMetadata(ExportFuncMetadataName);
+  const llvm::NamedMDNode *ExportForEachNameMetadata =
+      mModule->getNamedMetadata(ExportForEachNameMetadataName);
+  const llvm::NamedMDNode *ExportForEachMetadata =
+      mModule->getNamedMetadata(ExportForEachMetadataName);
+  const llvm::NamedMDNode *ExportReduceMetadata =
+      mModule->getNamedMetadata(ExportReduceMetadataName);
+  const llvm::NamedMDNode *PragmaMetadata =
+      mModule->getNamedMetadata(PragmaMetadataName);
+  const llvm::NamedMDNode *ObjectSlotMetadata =
+      mModule->getNamedMetadata(ObjectSlotMetadataName);
+  const llvm::NamedMDNode *ThreadableMetadata =
+      mModule->getNamedMetadata(ThreadableMetadataName);
+  const llvm::NamedMDNode *ChecksumMetadata =
+      mModule->getNamedMetadata(ChecksumMetadataName);
+  const llvm::NamedMDNode *DebugInfoMetadata =
+      mModule->getNamedMetadata(DebugInfoMetadataName);
+
+  if (!populateNameMetadata(ExportVarMetadata, mExportVarNameList,
+                            mExportVarCount)) {
+    ALOGE("Could not populate export variable metadata");
+    goto err;
+  }
+
+  if (!populateNameMetadata(ExportFuncMetadata, mExportFuncNameList,
+                            mExportFuncCount)) {
+    ALOGE("Could not populate export function metadata");
+    goto err;
+  }
+
+  if (!populateForEachMetadata(ExportForEachNameMetadata,
+                               ExportForEachMetadata)) {
+    ALOGE("Could not populate ForEach signature metadata");
+    goto err;
+  }
+
+  if (!populateReduceMetadata(ExportReduceMetadata)) {
+    ALOGE("Could not populate export general reduction metadata");
+    goto err;
+  }
+
+  populatePragmaMetadata(PragmaMetadata);
+
+  if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
+    ALOGE("Could not populate object slot metadata");
+    goto err;
+  }
+
+  readThreadableFlag(ThreadableMetadata);
+  readBuildChecksumMetadata(ChecksumMetadata);
+
+  mHasDebugInfo = DebugInfoMetadata != nullptr;
+
+  if (shouldNullModule) {
+    mModule = nullptr;
+  }
+  return true;
+
+err:
+  if (shouldNullModule) {
+    mModule = nullptr;
+  }
+  return false;
+}
+
+}  // namespace bcinfo
diff --git a/libbcc/bcinfo/Wrap/Android.mk b/libbcc/bcinfo/Wrap/Android.mk
new file mode 100644
index 0000000..92508d8
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/Android.mk
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+LLVM_ROOT_PATH := external/llvm
+include $(LLVM_ROOT_PATH)/llvm.mk
+
+llvm_wrap_SRC_FILES := \
+  bitcode_wrapperer.cpp \
+  file_wrapper_input.cpp \
+  file_wrapper_output.cpp \
+  in_memory_wrapper_input.cpp \
+  wrapper_output.cpp
+
+llvm_wrap_C_INCLUDES := $(LOCAL_PATH)/../../include
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libLLVMWrap
+LOCAL_MODULE_HOST_OS := darwin linux windows
+
+LOCAL_SRC_FILES := $(llvm_wrap_SRC_FILES)
+LOCAL_CFLAGS += -D__HOST__
+LOCAL_C_INCLUDES := $(llvm_wrap_C_INCLUDES)
+
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libLLVMWrap
+
+LOCAL_SRC_FILES := $(llvm_wrap_SRC_FILES)
+LOCAL_C_INCLUDES := $(llvm_wrap_C_INCLUDES)
+
+include $(LLVM_DEVICE_BUILD_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/libbcc/bcinfo/Wrap/LLVMBuild.txt b/libbcc/bcinfo/Wrap/LLVMBuild.txt
new file mode 100644
index 0000000..8750711
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/LLVMBuild.txt
@@ -0,0 +1,21 @@
+;===- ./lib/Wrap/LLVMBuild.txt ------------------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = Wrap
+parent = Libraries
diff --git a/libbcc/bcinfo/Wrap/Makefile b/libbcc/bcinfo/Wrap/Makefile
new file mode 100644
index 0000000..79aa2b3
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/Makefile
@@ -0,0 +1,14 @@
+##===- lib/Linker/Makefile ---------------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = LLVMWrap
+BUILD_ARCHIVE := 1
+
+include $(LEVEL)/Makefile.common
diff --git a/libbcc/bcinfo/Wrap/bitcode_wrapperer.cpp b/libbcc/bcinfo/Wrap/bitcode_wrapperer.cpp
new file mode 100644
index 0000000..0a49497
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/bitcode_wrapperer.cpp
@@ -0,0 +1,385 @@
+/*
+ * 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 "bcinfo/Wrap/bitcode_wrapperer.h"
+
+#define LOG_TAG "bcinfo"
+#include <cutils/log.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+using std::vector;
+
+// The number of bytes in a 32 bit integer.
+static const uint32_t kWordSize = 4;
+
+// Number of LLVM-defined fixed fields in the header.
+static const uint32_t kLLVMFields = 4;
+
+// Total number of fixed fields in the header.
+static const uint32_t kFixedFields = 7;
+
+// The magic number that must exist for bitcode wrappers.
+static const uint32_t kWrapperMagicNumber = 0x0B17C0DE;
+
+// The version number associated with a wrapper file.
+// Note: llvm currently only allows the value 0. When this changes,
+// we should consider making this a command line option.
+static const uint32_t kLLVMVersionNumber = 0;
+
+// Fields defined by Android bitcode header.
+static const uint32_t kAndroidHeaderVersion = 0;
+static const uint32_t kAndroidTargetAPI = 0;
+static const uint32_t kAndroidDefaultCompilerVersion = 0;
+static const uint32_t kAndroidDefaultOptimizationLevel = 3;
+
+// PNaCl bitcode version number.
+static const uint32_t kPnaclBitcodeVersion = 0;
+
+// Max size for variable fields. Currently only used for writing them
+// out to files (the parsing works for arbitrary sizes).
+static const size_t kMaxVariableFieldSize = 256;
+
+BitcodeWrapperer::BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile)
+    : infile_(infile),
+      outfile_(outfile),
+      buffer_size_(0),
+      cursor_(0),
+      infile_at_eof_(false),
+      infile_bc_offset_(0),
+      wrapper_bc_offset_(0),
+      wrapper_bc_size_(0),
+      android_header_version_(kAndroidHeaderVersion),
+      android_target_api_(kAndroidTargetAPI),
+      android_compiler_version_(kAndroidDefaultCompilerVersion),
+      android_optimization_level_(kAndroidDefaultOptimizationLevel),
+      pnacl_bc_version_(0),
+      error_(false) {
+  buffer_.resize(kBitcodeWrappererBufferSize);
+  if (IsInputBitcodeWrapper()) {
+    ParseWrapperHeader();
+  } else if (IsInputBitcodeFile()) {
+    wrapper_bc_offset_ = kWordSize * kFixedFields;
+    wrapper_bc_size_ = GetInFileSize();
+  } else {
+    ALOGE("Error: input file is not a bitcode file.\n");
+    error_ = true;
+  }
+}
+
+BitcodeWrapperer::~BitcodeWrapperer() {
+  for(size_t i = 0; i < variable_field_data_.size(); i++) {
+    delete [] variable_field_data_[i];
+  }
+}
+
+
+void BitcodeWrapperer::ClearBuffer() {
+  buffer_size_ = 0;
+  cursor_ = 0;
+  infile_at_eof_ = false;
+}
+
+bool BitcodeWrapperer::Seek(uint32_t pos) {
+  if (infile_ != nullptr && infile_->Seek(pos)) {
+    ClearBuffer();
+    return true;
+  }
+  return false;
+}
+
+bool BitcodeWrapperer::CanReadWord() {
+  if (GetBufferUnreadBytes() < kWordSize) {
+    FillBuffer();
+    return GetBufferUnreadBytes() >= kWordSize;
+  } else {
+    return true;
+  }
+}
+
+void BitcodeWrapperer::FillBuffer() {
+  if (cursor_ > 0) {
+    // Before filling, move any remaining bytes to the
+    // front of the buffer. This allows us to assume
+    // that after the call to FillBuffer, readable
+    // text is contiguous.
+    if (cursor_ < buffer_size_) {
+      size_t i = 0;
+      while (cursor_ < buffer_size_) {
+        buffer_[i++] = buffer_[cursor_++];
+      }
+      cursor_ = 0;
+      buffer_size_ = i;
+    }
+  } else {
+    // Assume the buffer contents have been used,
+    // and we want to completely refill it.
+    buffer_size_ = 0;
+  }
+
+  // If we don't have an input, we can't refill the buffer at all.
+  if (infile_ == nullptr) {
+    return;
+  }
+
+  // Now fill in remaining space.
+  size_t needed = buffer_.size() - buffer_size_;
+
+  while (buffer_.size() > buffer_size_) {
+    int actually_read = infile_->Read(&buffer_[buffer_size_], needed);
+    if (infile_->AtEof()) {
+      infile_at_eof_ = true;
+    }
+    if (actually_read) {
+      buffer_size_ += actually_read;
+      needed -= actually_read;
+    } else if (infile_at_eof_) {
+      break;
+    }
+  }
+}
+
+bool BitcodeWrapperer::ReadWord(uint32_t& word) {
+  if (!CanReadWord()) return false;
+  word = (((uint32_t) BufferLookahead(0)) << 0)
+      | (((uint32_t) BufferLookahead(1)) << 8)
+      | (((uint32_t) BufferLookahead(2)) << 16)
+      | (((uint32_t) BufferLookahead(3)) << 24);
+  cursor_ += kWordSize;
+  return true;
+}
+
+bool BitcodeWrapperer::WriteWord(uint32_t value) {
+  uint8_t buffer[kWordSize];
+  buffer[3] = (value >> 24) & 0xFF;
+  buffer[2] = (value >> 16) & 0xFF;
+  buffer[1] = (value >> 8)  & 0xFF;
+  buffer[0] = (value >> 0)  & 0xFF;
+  return outfile_->Write(buffer, kWordSize);
+}
+
+bool BitcodeWrapperer::WriteVariableFields() {
+  // This buffer may have to be bigger if we start using the fields
+  // for larger things.
+  uint8_t buffer[kMaxVariableFieldSize];
+  for (vector<BCHeaderField>::iterator it = header_fields_.begin();
+       it != header_fields_.end(); ++it) {
+    if (!it->Write(buffer, kMaxVariableFieldSize) ||
+        !outfile_->Write(buffer, it->GetTotalSize())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool BitcodeWrapperer::ParseWrapperHeader() {
+  // Make sure LLVM-defined fields have been parsed
+  if (!IsInputBitcodeWrapper()) return false;
+  // Check the android/pnacl fields
+  if (!ReadWord(android_header_version_) ||
+      !ReadWord(android_target_api_) || !ReadWord(pnacl_bc_version_)) {
+    ALOGW("Error: file not long enough to contain header\n");
+    return false;
+  }
+  if (pnacl_bc_version_ != kPnaclBitcodeVersion) {
+    ALOGW("Error: bad PNaCl Bitcode version\n");
+    return false;
+  }
+  int field_data_total = wrapper_bc_offset_ - kWordSize * kFixedFields;
+  if (field_data_total > 0) {
+    // Read in the variable fields. We need to allocate space for the data.
+    int field_data_read = 0;
+
+    while (field_data_read < field_data_total) {
+      FillBuffer();
+      size_t buffer_needed = BCHeaderField::GetDataSizeFromSerialized(
+          &buffer_[cursor_]);
+      if (buffer_needed > buffer_.size()) {
+        buffer_.resize(buffer_needed +
+                       sizeof(BCHeaderField::FixedSubfield) * 2);
+        FillBuffer();
+      }
+      variable_field_data_.push_back(new uint8_t[buffer_needed]);
+
+      BCHeaderField field(BCHeaderField::kInvalid, 0,
+                          variable_field_data_.back());
+      field.Read(&buffer_[cursor_], buffer_size_);
+      header_fields_.push_back(field);
+      size_t field_size = field.GetTotalSize();
+      cursor_ += field_size;
+      field_data_read += field_size;
+      if (field_data_read > field_data_total) {
+        // We read too much data, the header is corrupted
+        ALOGE("Error: raw bitcode offset inconsistent with "
+              "variable field data\n");
+        return false;
+      }
+
+      struct IntFieldHelper {
+        BCHeaderField::FixedSubfield tag;
+        uint16_t len;
+        uint32_t val;
+      };
+      IntFieldHelper tempIntField;
+
+      switch (field.getID()) {
+        case BCHeaderField::kAndroidCompilerVersion:
+          if (field.Write((uint8_t*)&tempIntField,
+                          sizeof(tempIntField))) {
+            android_compiler_version_ = tempIntField.val;
+          }
+          break;
+        case BCHeaderField::kAndroidOptimizationLevel:
+          if (field.Write((uint8_t*)&tempIntField,
+                          sizeof(tempIntField))) {
+            android_optimization_level_ = tempIntField.val;
+          }
+          break;
+        default:
+          // Ignore other field types for now
+          break;
+      }
+    }
+    Seek(0);
+  }
+  return true;
+}
+
+bool BitcodeWrapperer::IsInputBitcodeWrapper() {
+  ResetCursor();
+  // First make sure that there are enough words (LLVM header)
+  // to peek at.
+  if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) {
+    FillBuffer();
+    if (GetBufferUnreadBytes() < kLLVMFields * kWordSize) return false;
+  }
+
+  // Now make sure the magic number is right.
+  uint32_t first_word;
+  if ((!ReadWord(first_word)) ||
+      (kWrapperMagicNumber != first_word)) return false;
+
+  // Make sure the version is right.
+  uint32_t second_word;
+  if ((!ReadWord(second_word)) ||
+      (kLLVMVersionNumber != second_word)) return false;
+
+  // Make sure that the offset and size (for llvm) is defined.
+  uint32_t bc_offset;
+  uint32_t bc_size;
+  if (ReadWord(bc_offset) &&
+      ReadWord(bc_size)) {
+    // Before returning, save the extracted values.
+    wrapper_bc_offset_ = bc_offset;
+    infile_bc_offset_ = bc_offset;
+    wrapper_bc_size_ = bc_size;
+    return true;
+  }
+  // If reached, unable to read wrapped header.
+  return false;
+}
+
+bool BitcodeWrapperer::IsInputBitcodeFile() {
+  ResetCursor();
+  // First make sure that there are four bytes to peek at.
+  if (GetBufferUnreadBytes() < kWordSize) {
+    FillBuffer();
+    if (GetBufferUnreadBytes() < kWordSize) return false;
+  }
+  // If reached, Check if first 4 bytes match bitcode
+  // file magic number.
+  return (BufferLookahead(0) == 'B') &&
+      (BufferLookahead(1) == 'C') &&
+      (BufferLookahead(2) == 0xc0) &&
+      (BufferLookahead(3) == 0xde);
+}
+
+bool BitcodeWrapperer::BufferCopyInToOut(uint32_t size) {
+  while (size > 0) {
+    // Be sure buffer is non-empty before writing.
+    if (0 == buffer_size_) {
+      FillBuffer();
+      if (0 == buffer_size_) {
+        return false;
+      }
+    }
+    // copy the buffer to the output file.
+    size_t block = (buffer_size_ < size) ? buffer_size_ : size;
+    if (!outfile_->Write(&buffer_[cursor_], block)) return false;
+    size -= block;
+    buffer_size_ = 0;
+  }
+  // Be sure that there isn't more bytes on the input stream.
+  FillBuffer();
+  return buffer_size_ == 0;
+}
+
+void BitcodeWrapperer::AddHeaderField(BCHeaderField* field) {
+  header_fields_.push_back(*field);
+  wrapper_bc_offset_ += field->GetTotalSize();
+}
+
+bool BitcodeWrapperer::WriteBitcodeWrapperHeader() {
+  return
+      // Note: This writes out the 4 word header required by llvm wrapped
+      // bitcode.
+      WriteWord(kWrapperMagicNumber) &&
+      WriteWord(kLLVMVersionNumber) &&
+      WriteWord(wrapper_bc_offset_) &&
+      WriteWord(wrapper_bc_size_) &&
+      // 2 fixed fields defined by Android
+      WriteWord(android_header_version_) &&
+      WriteWord(android_target_api_) &&
+      // PNaClBitcode version
+      WriteWord(kPnaclBitcodeVersion) &&
+      // Common variable-length fields
+      WriteVariableFields();
+}
+
+void BitcodeWrapperer::PrintWrapperHeader() {
+  if (error_) {
+    fprintf(stderr, "Error condition exists: the following"
+            "data may not be reliable\n");
+  }
+  fprintf(stderr, "Wrapper magic:\t\t%x\n", kWrapperMagicNumber);
+  fprintf(stderr, "LLVM Bitcode version:\t%d\n", kLLVMVersionNumber);
+  fprintf(stderr, "Raw bitcode offset:\t%d\n", wrapper_bc_offset_);
+  fprintf(stderr, "Raw bitcode size:\t%d\n", wrapper_bc_size_);
+  fprintf(stderr, "Android header version:\t%d\n", android_header_version_);
+  fprintf(stderr, "Android target API:\t%d\n", android_target_api_);
+  fprintf(stderr, "PNaCl bitcode version:\t%d\n", kPnaclBitcodeVersion);
+  for (size_t i = 0; i < header_fields_.size(); i++) header_fields_[i].Print();
+}
+
+bool BitcodeWrapperer::GenerateWrappedBitcodeFile() {
+  if (!error_ &&
+      WriteBitcodeWrapperHeader() &&
+      Seek(infile_bc_offset_) &&
+      BufferCopyInToOut(wrapper_bc_size_)) {
+    off_t dangling = wrapper_bc_size_ & 3;
+    if (dangling) {
+      return outfile_->Write((const uint8_t*) "\0\0\0\0", 4 - dangling);
+    }
+    return true;
+  }
+  return false;
+}
+
+bool BitcodeWrapperer::GenerateRawBitcodeFile() {
+  return !error_ && Seek(infile_bc_offset_) &&
+      BufferCopyInToOut(wrapper_bc_size_);
+}
diff --git a/libbcc/bcinfo/Wrap/file_wrapper_input.cpp b/libbcc/bcinfo/Wrap/file_wrapper_input.cpp
new file mode 100644
index 0000000..7e34ba5
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/file_wrapper_input.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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 <sys/stat.h>
+#include <stdlib.h>
+
+#include "bcinfo/Wrap/file_wrapper_input.h"
+
+FileWrapperInput::FileWrapperInput(const char* name) :
+    _name(name), _at_eof(false), _size_found(false), _size(0) {
+  _file = fopen(name, "rb");
+  if (_file == nullptr) {
+    fprintf(stderr, "Unable to open: %s\n", name);
+    exit(1);
+  }
+}
+
+FileWrapperInput::~FileWrapperInput() {
+  fclose(_file);
+}
+
+size_t FileWrapperInput::Read(uint8_t* buffer, size_t wanted) {
+  size_t found = fread((char*) buffer, 1, wanted, _file);
+  if (feof(_file) || ferror(_file)) {
+    _at_eof = true;
+  }
+  return found;
+}
+
+bool FileWrapperInput::AtEof() {
+  return _at_eof;
+}
+
+off_t FileWrapperInput::Size() {
+  if (_size_found) return _size;
+  struct stat st;
+  if (stat(_name, &st) == 0) {
+    _size_found = true;
+    _size = st.st_size;
+    return _size;
+  } else {
+    fprintf(stderr, "Unable to compute file size: %s\n", _name);
+    exit(1);
+  }
+  // NOT REACHABLE.
+  return 0;
+}
+
+bool FileWrapperInput::Seek(uint32_t pos) {
+  return fseek(_file, (long) pos, SEEK_SET) == 0;
+}
diff --git a/libbcc/bcinfo/Wrap/file_wrapper_output.cpp b/libbcc/bcinfo/Wrap/file_wrapper_output.cpp
new file mode 100644
index 0000000..c785223
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/file_wrapper_output.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 <stdlib.h>
+
+#include "bcinfo/Wrap/file_wrapper_output.h"
+
+FileWrapperOutput::FileWrapperOutput(const char* name)
+    : _name(name) {
+  _file = fopen(name, "wb");
+  if (nullptr == _file) {
+    fprintf(stderr, "Unable to open: %s\n", name);
+    exit(1);
+  }
+}
+
+FileWrapperOutput::~FileWrapperOutput() {
+  fclose(_file);
+}
+
+bool FileWrapperOutput::Write(uint8_t byte) {
+  return EOF != fputc(byte, _file);
+}
+
+bool FileWrapperOutput::Write(const uint8_t* buffer, size_t buffer_size) {
+  if (!buffer) {
+    return false;
+  }
+
+  if (buffer_size > 0) {
+    return buffer_size == fwrite(buffer, 1, buffer_size, _file);
+  } else {
+    return true;
+  }
+}
diff --git a/libbcc/bcinfo/Wrap/in_memory_wrapper_input.cpp b/libbcc/bcinfo/Wrap/in_memory_wrapper_input.cpp
new file mode 100644
index 0000000..2d45d9c
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/in_memory_wrapper_input.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 <sys/stat.h>
+#include <stdlib.h>
+
+#include "bcinfo/Wrap/in_memory_wrapper_input.h"
+
+InMemoryWrapperInput::InMemoryWrapperInput(const char* buffer, size_t size) :
+    _buffer(buffer), _pos(0), _size(size) {
+}
+
+InMemoryWrapperInput::~InMemoryWrapperInput() {
+}
+
+size_t InMemoryWrapperInput::Read(uint8_t* buffer, size_t wanted) {
+  size_t found = 0;
+
+  if (!buffer) {
+    return 0;
+  }
+
+  while (found < wanted) {
+    if (_pos >= _size) {
+      return found;
+    }
+    buffer[found++] = _buffer[_pos++];
+  }
+  return found;
+}
+
+bool InMemoryWrapperInput::AtEof() {
+  return (_pos >= _size);
+}
+
+off_t InMemoryWrapperInput::Size() {
+  return _size;
+}
+
+bool InMemoryWrapperInput::Seek(uint32_t pos) {
+  if (pos < _size) {
+    _pos = pos;
+    return true;
+  } else {
+    return false;
+  }
+}
diff --git a/libbcc/bcinfo/Wrap/wrapper_output.cpp b/libbcc/bcinfo/Wrap/wrapper_output.cpp
new file mode 100644
index 0000000..3c72422
--- /dev/null
+++ b/libbcc/bcinfo/Wrap/wrapper_output.cpp
@@ -0,0 +1,25 @@
+/*
+ * 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 "bcinfo/Wrap/wrapper_output.h"
+
+bool WrapperOutput::Write(const uint8_t* buffer, size_t buffer_size) {
+  // Default implementation that uses the byte write routine.
+  for (size_t i = 0; i < buffer_size; ++i) {
+    if (!Write(buffer[i])) return false;
+  }
+  return true;
+}
diff --git a/libbcc/bcinfo/tools/Android.mk b/libbcc/bcinfo/tools/Android.mk
new file mode 100644
index 0000000..876a53c
--- /dev/null
+++ b/libbcc/bcinfo/tools/Android.mk
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2011 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+LLVM_ROOT_PATH := external/llvm
+include $(LLVM_ROOT_PATH)/llvm.mk
+
+# Executable for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bcinfo
+LOCAL_MODULE_CLASS := EXECUTABLES
+
+LOCAL_SRC_FILES := \
+  main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+  libbcinfo
+
+LOCAL_STATIC_LIBRARIES := \
+  libLLVMBitReader \
+  libLLVMBitWriter \
+  libLLVMCore \
+  libLLVMSupport
+
+LOCAL_CFLAGS += -D__HOST__
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/../../include
+
+LOCAL_LDLIBS = -ldl -lpthread
+
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(BUILD_HOST_EXECUTABLE)
+
diff --git a/libbcc/bcinfo/tools/main.cpp b/libbcc/bcinfo/tools/main.cpp
new file mode 100644
index 0000000..c85fdc4
--- /dev/null
+++ b/libbcc/bcinfo/tools/main.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright 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.
+ * 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 <bcinfo/BitcodeTranslator.h>
+#include <bcinfo/BitcodeWrapper.h>
+#include <bcinfo/MetadataExtractor.h>
+
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/IR/AssemblyAnnotationWriter.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Support/FileSystem.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>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#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.
+
+std::string inFile;
+std::string outFile;
+std::string infoFile;
+
+extern int opterr;
+extern int optind;
+
+bool translateFlag = false;
+bool infoFlag = false;
+bool verbose = true;
+
+static int parseOption(int argc, char** argv) {
+  int c;
+  while ((c = getopt(argc, argv, "itv")) != -1) {
+    opterr = 0;
+
+    switch(c) {
+      case '?':
+        // ignore any error
+        break;
+
+      case 't':
+        translateFlag = true;
+        break;
+
+      case 'i':
+        // Turn off verbose so that we only generate the .info file.
+        infoFlag = true;
+        verbose = false;
+        break;
+
+      case 'v':
+        verbose = true;
+        break;
+
+      default:
+        // Critical error occurs
+        return 0;
+        break;
+    }
+  }
+
+  if(optind >= argc) {
+    fprintf(stderr, "input file required\n");
+    return 0;
+  }
+
+  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";
+    infoFile = std::string(inFile.begin(), inFile.end() - 3) + ".bcinfo";
+  } else {
+    outFile = inFile + ".ll";
+    infoFile = inFile + ".bcinfo";
+  }
+  return 1;
+}
+
+
+static void dumpReduceInfo(FILE *info, const char *Kind, const char *Name) {
+  if (Name)
+    fprintf(info, "  %s(%s)\n", Kind, Name);
+}
+
+static int dumpInfo(bcinfo::MetadataExtractor *ME) {
+  if (!ME) {
+    return 1;
+  }
+
+  FILE *info = fopen(infoFile.c_str(), "w");
+  if (!info) {
+    fprintf(stderr, "Could not open info file %s\n", infoFile.c_str());
+    return 2;
+  }
+
+  fprintf(info, "exportVarCount: %zu\n", ME->getExportVarCount());
+  const char **varNameList = ME->getExportVarNameList();
+  for (size_t i = 0; i < ME->getExportVarCount(); i++) {
+    fprintf(info, "%s\n", varNameList[i]);
+  }
+
+  fprintf(info, "exportFuncCount: %zu\n", ME->getExportFuncCount());
+  const char **funcNameList = ME->getExportFuncNameList();
+  for (size_t i = 0; i < ME->getExportFuncCount(); i++) {
+    fprintf(info, "%s\n", funcNameList[i]);
+  }
+
+  fprintf(info, "exportForEachCount: %zu\n",
+          ME->getExportForEachSignatureCount());
+  const char **nameList = ME->getExportForEachNameList();
+  const uint32_t *sigList = ME->getExportForEachSignatureList();
+  const uint32_t *inputCountList = ME->getExportForEachInputCountList();
+  for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) {
+    fprintf(info, "%u - %s - %u\n", sigList[i], nameList[i],
+            inputCountList[i]);
+  }
+
+  fprintf(info, "exportReduceCount: %zu\n", ME->getExportReduceCount());
+  const bcinfo::MetadataExtractor::Reduce *reduceList =
+      ME->getExportReduceList();
+  for (size_t i = 0; i < ME->getExportReduceCount(); i++) {
+    const bcinfo::MetadataExtractor::Reduce &reduce = reduceList[i];
+    fprintf(info, "%u - %s - %u - %u\n", reduce.mSignature, reduce.mReduceName,
+            reduce.mInputCount, reduce.mAccumulatorDataSize);
+    dumpReduceInfo(info, "initializer",  reduce.mInitializerName);
+    dumpReduceInfo(info, "accumulator",  reduce.mAccumulatorName);
+    dumpReduceInfo(info, "combiner",     reduce.mCombinerName);
+    dumpReduceInfo(info, "outconverter", reduce.mOutConverterName);
+    dumpReduceInfo(info, "halter",       reduce.mHalterName);
+  }
+
+  fprintf(info, "objectSlotCount: %zu\n", ME->getObjectSlotCount());
+  const uint32_t *slotList = ME->getObjectSlotList();
+  for (size_t i = 0; i < ME->getObjectSlotCount(); i++) {
+    fprintf(info, "%u\n", slotList[i]);
+  }
+
+  fclose(info);
+  return 0;
+}
+
+
+static void dumpMetadata(bcinfo::MetadataExtractor *ME) {
+  if (!ME) {
+    return;
+  }
+
+  printf("RSFloatPrecision: ");
+  switch (ME->getRSFloatPrecision()) {
+  case bcinfo::RS_FP_Full:
+    printf("Full\n\n");
+    break;
+  case bcinfo::RS_FP_Relaxed:
+    printf("Relaxed\n\n");
+    break;
+  default:
+    printf("UNKNOWN\n\n");
+    break;
+  }
+
+  printf("exportVarCount: %zu\n", ME->getExportVarCount());
+  const char **varNameList = ME->getExportVarNameList();
+  for (size_t i = 0; i < ME->getExportVarCount(); i++) {
+    printf("var[%zu]: %s\n", i, varNameList[i]);
+  }
+  printf("\n");
+
+  printf("exportFuncCount: %zu\n", ME->getExportFuncCount());
+  const char **funcNameList = ME->getExportFuncNameList();
+  for (size_t i = 0; i < ME->getExportFuncCount(); i++) {
+    printf("func[%zu]: %s\n", i, funcNameList[i]);
+  }
+  printf("\n");
+
+  printf("exportForEachSignatureCount: %zu\n",
+         ME->getExportForEachSignatureCount());
+  const char **nameList = ME->getExportForEachNameList();
+  const uint32_t *sigList = ME->getExportForEachSignatureList();
+  const uint32_t *inputCountList = ME->getExportForEachInputCountList();
+  for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) {
+    printf("exportForEachSignatureList[%zu]: %s - 0x%08x - %u\n", i, nameList[i],
+           sigList[i], inputCountList[i]);
+  }
+  printf("\n");
+
+  printf("exportReduceCount: %zu\n", ME->getExportReduceCount());
+  const bcinfo::MetadataExtractor::Reduce *reduceList = ME->getExportReduceList();
+  for (size_t i = 0; i < ME->getExportReduceCount(); i++) {
+    const bcinfo::MetadataExtractor::Reduce &reduce = reduceList[i];
+    printf("exportReduceList[%zu]: %s - 0x%08x - %u - %u\n", i, reduce.mReduceName,
+           reduce.mSignature, reduce.mInputCount, reduce.mAccumulatorDataSize);
+    dumpReduceInfo(stdout, "initializer",  reduce.mInitializerName);
+    dumpReduceInfo(stdout, "accumulator",  reduce.mAccumulatorName);
+    dumpReduceInfo(stdout, "combiner",     reduce.mCombinerName);
+    dumpReduceInfo(stdout, "outconverter", reduce.mOutConverterName);
+    dumpReduceInfo(stdout, "halter",       reduce.mHalterName);
+  }
+  printf("\n");
+
+  printf("pragmaCount: %zu\n", ME->getPragmaCount());
+  const char **keyList = ME->getPragmaKeyList();
+  const char **valueList = ME->getPragmaValueList();
+  for (size_t i = 0; i < ME->getPragmaCount(); i++) {
+    printf("pragma[%zu]: %s - %s\n", i, keyList[i], valueList[i]);
+  }
+  printf("\n");
+
+  printf("objectSlotCount: %zu\n", ME->getObjectSlotCount());
+  const uint32_t *slotList = ME->getObjectSlotList();
+  for (size_t i = 0; i < ME->getObjectSlotCount(); i++) {
+    printf("objectSlotList[%zu]: %u\n", i, slotList[i]);
+  }
+  printf("\n");
+
+  return;
+}
+
+
+static size_t readBitcode(const char **bitcode) {
+  if (!inFile.length()) {
+    fprintf(stderr, "input file required\n");
+    return 0;
+  }
+
+  struct stat statInFile;
+  if (stat(inFile.c_str(), &statInFile) < 0) {
+    fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno));
+    return 0;
+  }
+
+  if (!S_ISREG(statInFile.st_mode)) {
+    fprintf(stderr, "Input file should be a regular file.\n");
+    return 0;
+  }
+
+  FILE *in = fopen(inFile.c_str(), "r");
+  if (!in) {
+    fprintf(stderr, "Could not open input file %s\n", inFile.c_str());
+    return 0;
+  }
+
+  size_t bitcodeSize = statInFile.st_size;
+
+  *bitcode = (const char*) calloc(1, bitcodeSize + 1);
+  size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in);
+
+  if (nread != bitcodeSize)
+      fprintf(stderr, "Could not read all of file %s\n", inFile.c_str());
+
+  fclose(in);
+  return nread;
+}
+
+
+static void releaseBitcode(const char **bitcode) {
+  if (bitcode && *bitcode) {
+    free((void*) *bitcode);
+    *bitcode = nullptr;
+  }
+  return;
+}
+
+
+int main(int argc, char** argv) {
+  if(!parseOption(argc, argv)) {
+    fprintf(stderr, "failed to parse option\n");
+    return 1;
+  }
+
+  const char *bitcode = nullptr;
+  size_t bitcodeSize = readBitcode(&bitcode);
+
+  unsigned int version = 0;
+
+  bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize);
+  if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
+    version = bcWrapper.getTargetAPI();
+    if (verbose) {
+      printf("Found bitcodeWrapper\n");
+    }
+  } else if (translateFlag) {
+    version = 12;
+  }
+
+  if (verbose) {
+    printf("targetAPI: %u\n", version);
+    printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion());
+    printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel());
+  }
+
+  std::unique_ptr<bcinfo::BitcodeTranslator> BT;
+  BT.reset(new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version));
+  if (!BT->translate()) {
+    fprintf(stderr, "failed to translate bitcode\n");
+    return 3;
+  }
+
+  std::unique_ptr<bcinfo::MetadataExtractor> ME;
+  ME.reset(new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(),
+                                         BT->getTranslatedBitcodeSize()));
+  if (!ME->extract()) {
+    fprintf(stderr, "failed to get metadata\n");
+    return 4;
+  }
+
+  if (verbose) {
+    dumpMetadata(ME.get());
+
+    const char *translatedBitcode = BT->getTranslatedBitcode();
+    size_t translatedBitcodeSize = BT->getTranslatedBitcodeSize();
+
+    llvm::LLVMContext &ctx = llvm::getGlobalContext();
+    llvm::llvm_shutdown_obj called_on_exit;
+
+    std::unique_ptr<llvm::MemoryBuffer> mem;
+
+    mem = llvm::MemoryBuffer::getMemBuffer(
+        llvm::StringRef(translatedBitcode, translatedBitcodeSize),
+        inFile.c_str(), false);
+
+    std::unique_ptr<llvm::Module> module;
+    llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError =
+        llvm::parseBitcodeFile(mem.get()->getMemBufferRef(), ctx);
+    std::error_code ec = moduleOrError.getError();
+    if (!ec) {
+        module = std::move(moduleOrError.get());
+        ec = module->materializeAll();
+    }
+    std::string errmsg;
+    if (ec) {
+      errmsg = ec.message();
+      module.reset();
+      if (errmsg.size()) {
+        fprintf(stderr, "error: %s\n", errmsg.c_str());
+      } else {
+        fprintf(stderr, "error: failed to parse bitcode file\n");
+      }
+      return 5;
+    }
+
+    std::unique_ptr<llvm::tool_output_file> tof(
+        new llvm::tool_output_file(outFile.c_str(), ec,
+                                   llvm::sys::fs::F_None));
+    std::unique_ptr<llvm::AssemblyAnnotationWriter> ann;
+    module->print(tof->os(), ann.get());
+
+    tof->keep();
+  }
+
+  if (infoFlag) {
+    if (dumpInfo(ME.get()) != 0) {
+      fprintf(stderr, "Error dumping info file\n");
+      return 6;
+    }
+  }
+
+  releaseBitcode(&bitcode);
+
+  return 0;
+}
diff --git a/libbcc/gdb_plugin/android-commands.py b/libbcc/gdb_plugin/android-commands.py
new file mode 100644
index 0000000..92b771c
--- /dev/null
+++ b/libbcc/gdb_plugin/android-commands.py
@@ -0,0 +1,771 @@
+#
+# 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.
+#
+
+#
+# GDB plugin to allow debugging of apps on remote Android systems using gdbserver.
+#
+# To use this plugin, source this file from a Python-enabled GDB client, then use:
+#   load-android-app <app-source-dir>  to tell GDB about the app you are debugging
+#   run-android-app to start the app in a running state
+#   start-android-app to start the app in a paused state
+#   attach-android-ap to attach to an existing (running) instance of app
+#   set-android-device to select a target (only if multiple devices are attached)
+
+import fnmatch
+import gdb
+import os
+import shutil
+import subprocess
+import tempfile
+import time
+
+be_verbose = False
+enable_renderscript_dumps = True
+local_symbols_library_directory = os.path.join(os.getenv('ANDROID_PRODUCT_OUT', 'out'),
+      'symbols', 'system', 'lib')
+local_library_directory = os.path.join(os.getenv('ANDROID_PRODUCT_OUT', 'out'),
+      'system', 'lib')
+
+# ADB              - Basic ADB wrapper, far from complete
+# DebugAppInfo     - App configuration struct, as far as GDB cares
+# StartAndroidApp  - Implementation of GDB start (for android apps)
+# RunAndroidApp    - Implementation of GDB run (for android apps)
+# AttachAndroidApp - GDB command to attach to an existing android app process
+# AndroidStatus    - app status query command (not needed, mostly harmless)
+# LoadAndroidApp   - Sets the package and intent names for an app
+
+def _interesting_libs():
+  return ['libc', 'libbcc', 'libRS', 'libandroid_runtime', 'libart']
+
+# In python 2.6, subprocess.check_output does not exist, so it is implemented here
+def check_output(*popenargs, **kwargs):
+  p = subprocess.Popen(stdout=subprocess.PIPE, stderr=subprocess.STDOUT, *popenargs, **kwargs)
+  out, err = p.communicate()
+  retcode = p.poll()
+  if retcode != 0:
+    c = kwargs.get("args")
+    if c is None:
+      c = popenargs[0]
+    e = subprocess.CalledProcessError(retcode, c)
+    e.output = str(out) + str(err)
+    raise e
+  return out
+
+class DebugAppInfo:
+  """Stores information from an app manifest"""
+
+  def __init__(self):
+    self.name = None
+    self.intent = None
+
+  def get_name(self):
+    return self.name
+
+  def get_intent(self):
+    return self.intent
+
+  def get_data_directory(self):
+    return self.data_directory
+
+  def get_gdbserver_path(self):
+    return os.path.join(self.data_directory, "lib", "gdbserver")
+
+  def set_info(self, name, intent, data_directory):
+    self.name = name
+    self.intent = intent
+    self.data_directory = data_directory
+
+  def unset_info():
+    self.name = None
+    self.intent = None
+    self.data_directory = None
+
+class ADB:
+  """
+  Python class implementing a basic ADB wrapper for useful commands.
+  Uses subprocess to invoke adb.
+  """
+
+  def __init__(self, device=None, verbose=False):
+    self.verbose = verbose
+    self.current_device = device
+    self.temp_libdir = None
+    self.background_processes = []
+    self.android_build_top = os.getenv('ANDROID_BUILD_TOP', None)
+    if not self.android_build_top:
+      raise gdb.GdbError("Unable to read ANDROID_BUILD_TOP. " \
+        + "Is your environment setup correct?")
+
+    self.adb_path = os.path.join(self.android_build_top,
+                      'out', 'host', 'linux-x86', 'bin', 'adb')
+
+    if not self.current_device:
+      devices = self.devices()
+      if len(devices) == 1:
+        self.set_current_device(devices[0])
+        return
+      else:
+        msg = ""
+        if len(devices) == 0:
+          msg = "No devices detected. Please connect a device and "
+        else:
+          msg = "Too many devices (" + ", ".join(devices) + ") detected. " \
+              + "Please "
+
+        print "Warning: " + msg + " use the set-android-device command."
+
+
+  def _prepare_adb_args(self, args):
+    largs = list(args)
+
+    # Prepare serial number option from current_device
+    if self.current_device and len(self.current_device) > 0:
+      largs.insert(0, self.current_device)
+      largs.insert(0, "-s")
+
+    largs.insert(0, self.adb_path)
+    return largs
+
+
+  def _background_adb(self, *args):
+    largs = self._prepare_adb_args(args)
+    p = None
+    try:
+      if self.verbose:
+        print "### " + str(largs)
+      p = subprocess.Popen(largs)
+      self.background_processes.append(p)
+    except CalledProcessError, e:
+      raise gdb.GdbError("Error starting background adb " + str(largs))
+    except:
+      raise gdb.GdbError("Unknown error starting background adb " + str(largs))
+
+    return p
+
+  def _call_adb(self, *args):
+    output = ""
+    largs = self._prepare_adb_args(args)
+    try:
+      if self.verbose:
+        print "### " + str(largs)
+      output = check_output(largs)
+    except subprocess.CalledProcessError, e:
+      raise gdb.GdbError("Error starting adb " + str(largs))
+    except Exception as e:
+      raise gdb.GdbError("Unknown error starting adb " + str(largs))
+
+    return output
+
+  def _shell(self, *args):
+    args = ["shell"] + list(args)
+    return self._call_adb(*args)
+
+  def _background_shell(self, *args):
+    args = ["shell"] + list(args)
+    return self._background_adb(*args)
+
+  def _cleanup_background_processes(self):
+    for handle in self.background_processes:
+      try:
+        handle.terminate()
+      except OSError, e:
+        # Background process died already
+        pass
+
+  def _cleanup_temp(self):
+    if self.temp_libdir:
+      shutil.rmtree(self.temp_libdir)
+      self.temp_libdir = None
+
+  def __del__(self):
+    self._cleanup_temp()
+    self._cleanup_background_processes()
+
+  def _get_local_libs(self):
+    ret = []
+    for lib in _interesting_libs():
+      lib_path = os.path.join(local_library_directory, lib + ".so")
+      if not os.path.exists(lib_path) and self.verbose:
+        print "Warning: unable to find expected library " \
+          + lib_path + "."
+      ret.append(lib_path)
+
+    return ret
+
+  def _check_remote_libs_match_local_libs(self):
+    ret = []
+    all_remote_libs = self._shell("ls", "/system/lib/*.so").split()
+    local_libs = self._get_local_libs()
+
+    self.temp_libdir = tempfile.mkdtemp()
+
+    for lib in _interesting_libs():
+      lib += ".so"
+      for remote_lib in all_remote_libs:
+        if lib in remote_lib:
+          # Pull lib from device and compute hash
+          tmp_path = os.path.join(self.temp_libdir, lib)
+          self.pull(remote_lib, tmp_path)
+          remote_hash = self._md5sum(tmp_path)
+
+          # Find local lib and compute hash
+          built_library = filter(lambda l: lib in l, local_libs)[0]
+          built_hash = self._md5sum(built_library)
+
+          # Alert user if library mismatch is detected
+          if built_hash != remote_hash:
+            self._cleanup_temp()
+            raise gdb.GdbError("Library mismatch between:\n" \
+              + "\t(" + remote_hash + ") " + tmp_path + " (from target) and\n " \
+              + "\t(" + built_hash + ") " + built_library + " (on host)\n" \
+              + "The target is running a different build than the host." \
+              + " This situation is not debuggable.")
+
+    self._cleanup_temp()
+
+  def _md5sum(self, file):
+    try:
+      return check_output(["md5sum", file]).strip().split()[0]
+    except subprocess.CalledProcessError, e:
+      raise gdb.GdbError("Error invoking md5sum commandline utility")
+
+  # Returns the list of serial numbers of connected devices
+  def devices(self):
+    ret = []
+    raw_output = self._call_adb("devices").split()
+    if len(raw_output) < 5:
+      return None
+    else:
+      for serial_num_index in range(4, len(raw_output), 2):
+        ret.append(raw_output[serial_num_index])
+    return ret
+
+  def set_current_device(self, serial):
+    if self.current_device == str(serial):
+      print "Current device already is: " + str(serial)
+      return
+
+    # TODO: this function should probably check the serial is valid.
+    self.current_device = str(serial)
+
+    api_version = self.getprop("ro.build.version.sdk")
+    if api_version < 15:
+      print "Warning: untested API version. Upgrade to 15 or higher"
+
+    # Verify the local libraries loaded by GDB are identical to those
+    # sitting on the device actually executing. Alert the user if
+    # this is happening
+    self._check_remote_libs_match_local_libs()
+
+  # adb getprop [property]
+  # if property is not None, returns the given property, otherwise
+  # returns all properties.
+  def getprop(self, property=None):
+    if property == None:
+      # get all the props
+      return self._call_adb(*["shell", "getprop"]).split('\n')
+    else:
+      return str(self._call_adb(*["shell", "getprop",
+        str(property)]).split('\n')[0])
+
+  # adb push
+  def push(self, source, destination):
+    self._call_adb(*["push", source, destination])
+
+  # adb forward <source> <destination>
+  def forward(self, source, destination):
+    self._call_adb(*["forward", source, destination])
+
+  # Returns true if filename exists on Android fs, false otherwise
+  def exists(self, filename):
+    raw_listing = self._shell(*["ls", filename])
+    return "No such file or directory" not in raw_listing
+
+  # adb pull <remote_path> <local_path>
+  def pull(self, remote_path, local_path):
+    self._call_adb(*["pull", remote_path, local_path])
+
+  #wrapper for adb shell ps. leave process_name=None for list of all processes
+  #Otherwise, returns triple with process name, pid and owner,
+  def get_process_info(self, process_name=None):
+    ret = []
+    raw_output = self._shell("ps")
+    for raw_line in raw_output.splitlines()[1:]:
+      line = raw_line.split()
+      name = line[-1]
+
+      if process_name == None or name == process_name:
+        user = line[0]
+        pid = line[1]
+
+        if process_name != None:
+          return (pid, user)
+        else:
+          ret.append((pid, user))
+
+    # No match in target process
+    if process_name != None:
+      return (None, None)
+
+    return ret
+
+  def kill_by_pid(self, pid):
+    self._shell(*["kill", "-9", pid])
+
+  def kill_by_name(self, process_name):
+    (pid, user) = self.get_process_info(process_name)
+    while pid != None:
+      self.kill_by_pid(pid)
+      (pid, user) = self.get_process_info(process_name)
+
+class AndroidStatus(gdb.Command):
+  """Implements the android-status gdb command."""
+
+  def __init__(self, adb, name="android-status", cat=gdb.COMMAND_OBSCURE, verbose=False):
+    super (AndroidStatus, self).__init__(name, cat)
+    self.verbose = verbose
+    self.adb = adb
+
+  def _update_status(self, process_name, gdbserver_process_name):
+    self._check_app_is_loaded()
+
+    # Update app status
+    (self.pid, self.owner_user) = \
+      self.adb.get_process_info(process_name)
+    self.running = self.pid != None
+
+    # Update gdbserver status
+    (self.gdbserver_pid, self.gdbserver_user) = \
+      self.adb.get_process_info(gdbserver_process_name)
+    self.gdbserver_running = self.gdbserver_pid != None
+
+    # Print results
+    if self.verbose:
+      print "--==Android GDB Plugin Status Update==--"
+      print "\tinferior name: " + process_name
+      print "\trunning: " + str(self.running)
+      print "\tpid: " + str(self.pid)
+      print "\tgdbserver running: " + str(self.gdbserver_running)
+      print "\tgdbserver pid: " + str(self.gdbserver_pid)
+      print "\tgdbserver user: " + str(self.gdbserver_user)
+
+  def _check_app_is_loaded(self):
+    if not currentAppInfo.get_name():
+      raise gdb.GdbError("Error: no app loaded. Try load-android-app.")
+
+  def invoke(self, arg, from_tty):
+    self._check_app_is_loaded()
+    self._update_status(currentAppInfo.get_name(),
+      currentAppInfo.get_gdbserver_path())
+    # TODO: maybe print something if verbose is off
+
+class StartAndroidApp (AndroidStatus):
+  """Implements the 'start-android-app' gdb command."""
+
+  def _update_status(self):
+    AndroidStatus._update_status(self, self.process_name, \
+      self.gdbserver_path)
+
+  # Calls adb shell ps every retry_delay seconds and returns
+  # the pid when process_name show up in output, or return 0
+  # after num_retries attempts. num_retries=0 means retry
+  # indefinitely.
+  def _wait_for_process(self, process_name, retry_delay=1, num_retries=10):
+    """ This function is a hack and should not be required"""
+    (pid, user) = self.adb.get_process_info(process_name)
+    retries_left = num_retries
+    while pid == None and retries_left != 0:
+      (pid, user) = self.adb.get_process_info(process_name)
+      time.sleep(retry_delay)
+      retries_left -= 1
+
+    return pid
+
+  def _gdbcmd(self, cmd, from_tty=False):
+    if self.verbose:
+      print '### GDB Command: ' + str(cmd)
+
+    gdb.execute(cmd, from_tty)
+
+  # Remove scratch directory if any
+  def _cleanup_temp(self):
+    if self.temp_dir:
+      shutil.rmtree(self.temp_dir)
+      self.temp_dir = None
+
+  def _cleanup_jdb(self):
+    if self.jdb_handle:
+      try:
+        self.jdb_handle.terminate()
+      except OSError, e:
+        # JDB process has likely died
+        pass
+
+      self.jdb_handle = None
+
+  def _load_local_libs(self):
+    for lib in _interesting_libs():
+      self._gdbcmd("shar " + lib)
+
+  def __del__(self):
+    self._cleanup_temp()
+    self._cleanup_jdb()
+
+  def __init__ (self, adb, name="start-android-app", cat=gdb.COMMAND_RUNNING, verbose=False):
+    super (StartAndroidApp, self).__init__(adb, name, cat, verbose)
+    self.adb = adb
+
+    self.jdb_handle = None
+    # TODO: handle possibility that port 8700 is in use (may help with
+    # Eclipse problems)
+    self.jdwp_port = 8700
+
+    # Port for gdbserver
+    self.gdbserver_port = 5039
+
+    self.temp_dir = None
+
+  def start_process(self, start_running=False):
+    #TODO: implement libbcc cache removal if needed
+
+    args = ["am", "start"]
+
+    # If we are to start running, we can take advantage of am's -W flag to wait
+    # for the process to start before returning. That way, we don't have to
+    # emulate the behaviour (poorly) through the sleep-loop below.
+    if not start_running:
+      args.append("-D")
+    else:
+      args.append("-W")
+
+    args.append(self.process_name + "/" + self.intent)
+    am_output = self.adb._shell(*args)
+    if "Error:" in am_output:
+      raise gdb.GdbError("Cannot start app. Activity Manager returned:\n"\
+        + am_output)
+
+    # Gotta wait until the process starts if we can't use -W
+    if not start_running:
+      self.pid = self._wait_for_process(self.process_name)
+
+    if not self.pid:
+      raise gdb.GdbError("Unable to detect running app remotely." \
+        + "Is " + self.process_name + " installed correctly?")
+
+    if self.verbose:
+      print "--==Android App Started: " + self.process_name \
+        + " (pid=" + self.pid + ")==--"
+
+    # Forward port for java debugger to Dalvik
+    self.adb.forward("tcp:" + str(self.jdwp_port), \
+                     "jdwp:" + str(self.pid))
+
+  def start_gdbserver(self):
+    # TODO: adjust for architecture...
+    gdbserver_local_path = os.path.join(os.getenv('ANDROID_BUILD_TOP'),
+      'prebuilt', 'android-arm', 'gdbserver', 'gdbserver')
+
+    if not self.adb.exists(self.gdbserver_path):
+      # Install gdbserver
+      try:
+        self.adb.push(gdbserver_local_path, self.gdbserver_path)
+      except gdb.GdbError, e:
+        print "Unable to push gdbserver to device. Try re-installing app."
+        raise e
+
+    self.adb._background_shell(*[self.gdbserver_path, "--attach",
+      ":" + str(self.gdbserver_port), self.pid])
+
+    self._wait_for_process(self.gdbserver_path)
+    self._update_status()
+
+    if self.verbose:
+      print "--==Remote gdbserver Started " \
+        + " (pid=" + str(self.gdbserver_pid) \
+        + " port=" + str(self.gdbserver_port) + ") ==--"
+
+    # Forward port for gdbserver
+    self.adb.forward("tcp:" + str(self.gdbserver_port), \
+                     "tcp:" + str(5039))
+
+  def attach_gdb(self, from_tty):
+    self._gdbcmd("target remote :" + str(self.gdbserver_port), False)
+    if self.verbose:
+      print "--==GDB Plugin requested attach (port=" \
+        + str(self.gdbserver_port) + ")==-"
+
+    # If GDB has no file set, things start breaking...so grab the same
+    # binary the NDK grabs from the filesystem and continue
+    self._cleanup_temp()
+    self.temp_dir = tempfile.mkdtemp()
+    self.gdb_inferior = os.path.join(self.temp_dir, 'app_process')
+    self.adb.pull("/system/bin/app_process", self.gdb_inferior)
+    self._gdbcmd('file ' + self.gdb_inferior)
+
+  def start_jdb(self, port):
+    # Kill if running
+    self._cleanup_jdb()
+
+    # Start the java debugger
+    args = ["jdb", "-connect",
+      "com.sun.jdi.SocketAttach:hostname=localhost,port=" + str(port)]
+    if self.verbose:
+      self.jdb_handle = subprocess.Popen(args, \
+        stdin=subprocess.PIPE)
+    else:
+      # Unix-only bit here..
+      self.jdb_handle = subprocess.Popen(args, \
+        stdin=subprocess.PIPE,
+        stderr=subprocess.STDOUT,
+        stdout=open('/dev/null', 'w'))
+
+  def invoke (self, arg, from_tty):
+    # TODO: self._check_app_is_installed()
+    self._check_app_is_loaded()
+
+    self.intent = currentAppInfo.get_intent()
+    self.process_name = currentAppInfo.get_name()
+    self.data_directory = currentAppInfo.get_data_directory()
+    self.gdbserver_path = currentAppInfo.get_gdbserver_path()
+
+    self._update_status()
+
+    if self.gdbserver_running:
+      self.adb.kill_by_name(self.gdbserver_path)
+      if self.verbose:
+        print "--==Killed gdbserver process (pid=" \
+          + str(self.gdbserver_pid) + ")==--"
+      self._update_status()
+
+    if self.running:
+      self.adb.kill_by_name(self.process_name)
+      if self.verbose:
+        print "--==Killed app process (pid=" + str(self.pid) + ")==--"
+      self._update_status()
+
+    self.start_process()
+
+    # Start remote gdbserver
+    self.start_gdbserver()
+
+    # Attach the gdb
+    self.attach_gdb(from_tty)
+
+    # Load symbolic libraries
+    self._load_local_libs()
+
+    # Set the debug output directory (for JIT debugging)
+    if enable_renderscript_dumps:
+      self._gdbcmd('set gDebugDumpDirectory="' + self.data_directory + '"')
+
+    # Start app
+    # unblock the gdb by connecting with jdb
+    self.start_jdb(self.jdwp_port)
+
+class RunAndroidApp(StartAndroidApp):
+  """Implements the run-android-app gdb command."""
+
+  def __init__(self, adb, name="run-android-app", cat=gdb.COMMAND_RUNNING, verbose=False):
+    super (RunAndroidApp, self).__init__(adb, name, cat, verbose)
+
+  def invoke(self, arg, from_tty):
+    StartAndroidApp.invoke(self, arg, from_tty)
+    self._gdbcmd("continue")
+
+class AttachAndroidApp(StartAndroidApp):
+  """Implements the attach-android-app gdb command."""
+
+  def __init__(self, adb, name="attach-android-app", cat=gdb.COMMAND_RUNNING, verbose=False):
+    super (AttachAndroidApp, self).__init__(adb, name, cat, verbose)
+
+  def invoke(self, arg, from_tty):
+    # TODO: self._check_app_is_installed()
+    self._check_app_is_loaded()
+
+    self.intent = currentAppInfo.get_intent()
+    self.process_name = currentAppInfo.get_name()
+    self.data_directory = currentAppInfo.get_data_directory()
+    self.gdbserver_path = currentAppInfo.get_gdbserver_path()
+
+    self._update_status()
+
+    if self.gdbserver_running:
+      self.adb.kill_by_name(self.gdbserver_path)
+      if self.verbose:
+        print "--==Killed gdbserver process (pid=" \
+          + str(self.gdbserver_pid) + ")==--"
+      self._update_status()
+
+    # Start remote gdbserver
+    self.start_gdbserver()
+
+    # Attach the gdb
+    self.attach_gdb(from_tty)
+
+    # Load symbolic libraries
+    self._load_local_libs()
+
+    # Set the debug output directory (for JIT debugging)
+    if enable_renderscript_dumps:
+      self._gdbcmd('set gDebugDumpDirectory="' + self.data_directory + '"')
+
+class LoadApp(AndroidStatus):
+  """ Implements the load-android-app gbd command.
+  """
+  def _awk_script_path(self, script_name):
+    if os.path.exists(script_name):
+      return script_name
+
+    script_root = os.path.join(os.getenv('ANDROID_BUILD_TOP'), \
+      'ndk', 'build', 'awk')
+
+    path_in_root = os.path.join(script_root, script_name)
+    if os.path.exists(path_in_root):
+      return path_in_root
+
+    raise gdb.GdbError("Unable to find awk script " \
+      +  str(script_name) + " in " + path_in_root)
+
+  def _awk(self, script, command):
+    args = ["awk", "-f", self._awk_script_path(script), str(command)]
+
+    if self.verbose:
+      print "### awk command: " + str(args)
+
+    awk_output = ""
+    try:
+      awk_output = check_output(args)
+    except subprocess.CalledProcessError, e:
+      raise gdb.GdbError("### Error in subprocess awk " + str(args))
+    except:
+      print "### Random error calling awk " + str(args)
+
+    return awk_output.rstrip()
+
+  def __init__(self, adb, name="load-android-app", cat=gdb.COMMAND_RUNNING, verbose=False):
+    super (LoadApp, self).__init__(adb, name, cat, verbose)
+    self.manifest_name = "AndroidManifest.xml"
+    self.verbose = verbose
+    self.adb = adb
+    self.temp_libdir = None
+
+  def _find_manifests(self, path):
+    manifests = []
+    for root, dirnames, filenames in os.walk(path):
+      for filename in fnmatch.filter(filenames, self.manifest_name):
+        manifests.append(os.path.join(root, filename))
+    return manifests
+
+  def _usage(self):
+    return "Usage: load-android-app [<path-to-AndroidManifest.xml>" \
+            + " | <package-name> <intent-name>]"
+
+  def invoke(self, arg, from_tty):
+ 
+    package_name = ''
+    launchable = ''
+    args = arg.strip('"').split()
+    if len(args) == 2:
+      package_name = args[0]
+      launchable = args[1]
+    elif len(args) == 1:
+      if os.path.isfile(args[0]) and os.path.basename(args[0]) == self.manifest_name:
+        self.manifest_path = args[0]
+      elif os.path.isdir(args[0]):
+        manifests = self._find_manifests(args[0])
+        if len(manifests) == 0:
+          raise gdb.GdbError(self.manifest_name + " not found in: " \
+            + args[0] + "\n" + self._usage())
+        elif len(manifests) > 1:
+          raise gdb.GdbError("Ambiguous argument! Found too many " \
+            + self.manifest_name + " files found:\n" + "\n".join(manifests))
+        else:
+          self.manifest_path = manifests[0]
+      else:
+        raise gdb.GdbError("Invalid path: " + args[0] + "\n" + self._usage())
+
+      package_name = self._awk("extract-package-name.awk",
+        self.manifest_path)
+      launchable = self._awk("extract-launchable.awk",
+        self.manifest_path)
+    else:
+      raise gdb.GdbError(self._usage())
+
+
+    data_directory = self.adb._shell("run-as", package_name,
+      "/system/bin/sh", "-c", "pwd").rstrip()
+
+    if not data_directory \
+      or len(data_directory) == 0 \
+      or not self.adb.exists(data_directory):
+      data_directory = os.path.join('/data', 'data', package_name)
+      print "Warning: unable to read data directory for package " \
+        + package_name + ". Meh, defaulting to " + data_directory
+
+    currentAppInfo.set_info(package_name, launchable, data_directory)
+
+    if self.verbose:
+      print "--==Android App Loaded==--"
+      print "\tname=" + currentAppInfo.get_name()
+      print "\tintent=" + currentAppInfo.get_intent()
+
+    # TODO: Check status of app on device
+
+class SetAndroidDevice (gdb.Command):
+  def __init__(self, adb, name="set-android-device", cat=gdb.COMMAND_RUNNING, verbose=False):
+    super (SetAndroidDevice, self).__init__(name, cat)
+    self.verbose = verbose
+    self.adb = adb
+
+  def _usage(self):
+    return "Usage: set-android-device <serial>"
+
+  def invoke(self, arg, from_tty):
+    if not arg or len(arg) == 0:
+      raise gdb.GdbError(self._usage)
+
+    serial = str(arg)
+    devices = adb.devices()
+    if serial in devices:
+      adb.set_current_device(serial)
+    else:
+      raise gdb.GdbError("Invalid serial. Serial numbers of connected " \
+        + "device(s): \n" + "\n".join(devices))
+
+# Global initialization
+def initOnce(adb):
+  # Try to speed up startup by skipping most android shared objects
+  gdb.execute("set auto-solib-add 0", False);
+
+  # Set shared object search path
+  gdb.execute("set solib-search-path " + local_symbols_library_directory, False)
+
+# Global instance of the object containing the info for current app
+currentAppInfo = DebugAppInfo ()
+
+# Global instance of ADB helper
+adb = ADB(verbose=be_verbose)
+
+# Perform global initialization
+initOnce(adb)
+
+# Command registration
+StartAndroidApp (adb, "start-android-app", gdb.COMMAND_RUNNING, be_verbose)
+RunAndroidApp (adb, "run-android-app", gdb.COMMAND_RUNNING, be_verbose)
+AndroidStatus (adb, "android-status", gdb.COMMAND_OBSCURE, be_verbose)
+LoadApp (adb, "load-android-app", gdb.COMMAND_RUNNING, be_verbose)
+SetAndroidDevice (adb, "set-android-device", gdb.COMMAND_RUNNING, be_verbose)
+AttachAndroidApp (adb, "attach-android-app", gdb.COMMAND_RUNNING, be_verbose)
diff --git a/libbcc/include/bcc/Assert.h b/libbcc/include/bcc/Assert.h
new file mode 100644
index 0000000..e87ba42
--- /dev/null
+++ b/libbcc/include/bcc/Assert.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 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.
+ * 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 _FRAMEWORKS_COMPILE_LIBBCC_INCLUDE_BCC_ASSERT_H_  // NOLINT
+#define _FRAMEWORKS_COMPILE_LIBBCC_INCLUDE_BCC_ASSERT_H_
+
+#ifdef __cplusplus
+#include <cstdlib>
+#include <cstdio>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#endif  // __cplusplus
+
+#ifdef __DISABLE_ASSERTS
+
+#define bccAssert(v) do {} while (0)
+
+#else
+
+#define LOG_TAG "bcc"
+#include <cutils/log.h>
+
+#define __ABORT_ON_FAILURES 1
+
+#define bccAssert(v)                                \
+  do {                                              \
+    if (!(v)) {                                     \
+      ALOGE("bccAssert failed at %s:%d - '%s'\n",   \
+          __FILE__, __LINE__, #v);                  \
+      if (__ABORT_ON_FAILURES) {                    \
+        abort();                                    \
+      }                                             \
+    }                                               \
+  } while (0)
+
+#endif  // __DISABLE_ASSERTS
+
+#endif  // _FRAMEWORKS_COMPILE_LIBBCC_INCLUDE_BCC_ASSERT_H_  NOLINT
diff --git a/libbcc/include/bcc/BCCContext.h b/libbcc/include/bcc/BCCContext.h
new file mode 100644
index 0000000..be24d31
--- /dev/null
+++ b/libbcc/include/bcc/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_CONTEXT_H
+#define BCC_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_CONTEXT_H
diff --git a/libbcc/include/bcc/Compiler.h b/libbcc/include/bcc/Compiler.h
new file mode 100644
index 0000000..92150fa
--- /dev/null
+++ b/libbcc/include/bcc/Compiler.h
@@ -0,0 +1,127 @@
+/*
+ * 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_COMPILER_H
+#define BCC_COMPILER_H
+
+namespace llvm {
+
+class raw_ostream;
+class raw_pwrite_stream;
+class DataLayout;
+class TargetMachine;
+
+namespace legacy {
+class PassManager;
+} // end namespace legacy
+
+using legacy::PassManager;
+
+} // end namespace llvm
+
+namespace bcc {
+
+class CompilerConfig;
+class OutputFile;
+class Script;
+
+//===----------------------------------------------------------------------===//
+// 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,
+
+    kInvalidConfigNoTarget,
+    kErrCreateTargetMachine,
+    kErrSwitchTargetMachine,
+    kErrNoTargetMachine,
+    kErrMaterialization,
+    kErrInvalidOutputFileState,
+    kErrPrepareOutput,
+    kPrepareCodeGenPass,
+
+    kErrCustomPasses,
+
+    kErrInvalidSource,
+
+    kIllegalGlobalFunction,
+
+    kErrInvalidTargetMachine
+  };
+
+  static const char *GetErrorString(enum ErrorCode pErrCode);
+
+private:
+  llvm::TargetMachine *mTarget;
+  // Optimization is enabled by default.
+  bool mEnableOpt;
+
+  enum ErrorCode runPasses(Script &pScript, llvm::raw_pwrite_stream &pResult);
+
+  bool addInternalizeSymbolsPass(Script &pScript, llvm::legacy::PassManager &pPM);
+  void addExpandKernelPass(llvm::legacy::PassManager &pPM);
+  void addDebugInfoPass(Script &pScript, llvm::legacy::PassManager &pPM);
+  void addGlobalInfoPass(Script &pScript, llvm::legacy::PassManager &pPM);
+  void addInvariantPass(llvm::legacy::PassManager &pPM);
+  void addInvokeHelperPass(llvm::legacy::PassManager &pPM);
+
+public:
+  Compiler();
+  explicit Compiler(const CompilerConfig &pConfig);
+
+  enum ErrorCode config(const CompilerConfig &pConfig);
+
+  // Compile a script and output the result to a LLVM stream.
+  //
+  // @param IRStream If not NULL, the LLVM-IR that is fed to code generation
+  //                 will be written to IRStream.
+  enum ErrorCode compile(Script &pScript, llvm::raw_pwrite_stream &pResult,
+                         llvm::raw_ostream *IRStream);
+
+  // Compile a script and output the result to a file.
+  enum ErrorCode compile(Script &pScript, OutputFile &pResult,
+                         llvm::raw_ostream *IRStream = 0);
+
+  const llvm::TargetMachine& getTargetMachine() const
+  { return *mTarget; }
+
+  void enableOpt(bool pEnable = true)
+  { mEnableOpt = pEnable; }
+
+  ~Compiler();
+
+  // Compare undefined external functions in pScript against a 'whitelist' of
+  // all RenderScript functions.  Returns error if any external function that is
+  // not in this whitelist is callable from the script.
+  enum ErrorCode screenGlobalFunctions(Script &pScript);
+
+  void translateGEPs(Script &pScript);
+};
+
+} // end namespace bcc
+
+#endif // BCC_COMPILER_H
diff --git a/libbcc/include/bcc/Config/Config.h b/libbcc/include/bcc/Config/Config.h
new file mode 100644
index 0000000..8293827
--- /dev/null
+++ b/libbcc/include/bcc/Config/Config.h
@@ -0,0 +1,111 @@
+#ifndef BCC_CONFIG_CONFIG_H
+#define BCC_CONFIG_CONFIG_H
+
+//---------------------------------------------------------------------------
+// Configuration for Disassembler
+//---------------------------------------------------------------------------
+
+#if DEBUG_MC_DISASSEMBLER
+#define USE_DISASSEMBLER 1
+#else
+#define USE_DISASSEMBLER 0
+#endif
+
+#if defined(__HOST__)
+#define DEBUG_DISASSEMBLER_FILE "/tmp/mc-dis.s"
+#else
+#define DEBUG_DISASSEMBLER_FILE "/data/local/tmp/mc-dis.s"
+#endif // defined(__HOST__)
+
+//---------------------------------------------------------------------------
+// Configuration for CodeGen and CompilerRT
+//---------------------------------------------------------------------------
+
+#if defined(FORCE_ARM_CODEGEN)
+  #define PROVIDE_ARM_CODEGEN
+  #define DEFAULT_ARM_CODEGEN
+
+#elif defined(FORCE_ARM64_CODEGEN)
+  #define PROVIDE_ARM_CODEGEN
+  #define PROVIDE_ARM64_CODEGEN
+  #define DEFAULT_ARM64_CODEGEN
+
+#elif defined(FORCE_MIPS_CODEGEN)
+  #define PROVIDE_MIPS_CODEGEN
+  #define DEFAULT_MIPS_CODEGEN
+
+#elif defined(FORCE_MIPS64_CODEGEN)
+  #define PROVIDE_MIPS_CODEGEN
+  #define PROVIDE_MIPS64_CODEGEN
+  #define DEFAULT_MIPS64_CODEGEN
+
+#elif defined(FORCE_X86_CODEGEN)
+  #define PROVIDE_X86_CODEGEN
+  #define DEFAULT_X86_CODEGEN
+
+#elif defined(FORCE_X86_64_CODEGEN)
+  // There is no separate X86_64 code generation target. It is all part of X86.
+  #define PROVIDE_X86_CODEGEN
+  #define DEFAULT_X86_64_CODEGEN
+
+#else
+  #define PROVIDE_ARM_CODEGEN
+  #define PROVIDE_ARM64_CODEGEN
+  #define PROVIDE_MIPS_CODEGEN
+  #define PROVIDE_MIPS64_CODEGEN
+  #define PROVIDE_X86_CODEGEN
+  #define PROVIDE_X86_64_CODEGEN
+
+  #if defined(__arm__)
+    #define DEFAULT_ARM_CODEGEN
+  #elif defined(__aarch64__)
+    #define DEFAULT_ARM64_CODEGEN
+  #elif defined(__mips__)
+    #if defined(__LP64__)
+      #define DEFAULT_MIPS64_CODEGEN
+    #else
+      #define DEFAULT_MIPS_CODEGEN
+    #endif
+  #elif defined(__i386__)
+    #define DEFAULT_X86_CODEGEN
+  #elif defined(__x86_64__)
+    #define DEFAULT_X86_64_CODEGEN
+  #endif
+#endif
+
+#define DEFAULT_ARM_TRIPLE_STRING      "armv7-none-linux-gnueabi"
+#define DEFAULT_THUMB_TRIPLE_STRING    "thumbv7-none-linux-gnueabi"
+#define DEFAULT_ARM64_TRIPLE_STRING    "aarch64-none-linux-gnueabi"
+#define DEFAULT_MIPS_TRIPLE_STRING     "mipsel-none-linux-gnueabi"
+#define DEFAULT_MIPS64_TRIPLE_STRING   "mips64el-none-linux-gnueabi"
+#define DEFAULT_X86_TRIPLE_STRING      "i686-unknown-linux"
+#define DEFAULT_X86_64_TRIPLE_STRING   "x86_64-unknown-linux"
+
+// Custom DataLayout string for X86 with i64 and f64 set to match the ARM32
+// alignment requirement of 64-bits.
+#define X86_CUSTOM_DL_STRING "e-m:e-p:32:32-i64:64-f64:64:64-f80:32-n8:16:32-S128"
+// Default DataLayout string for X86.  Present to detect future LLVM datalayout
+// changes so X86_CUSTOM_DL_STRING above can be modified appropriately.
+#define X86_DEFAULT_DL_STRING "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
+
+#if defined(DEFAULT_ARM_CODEGEN)
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_ARM_TRIPLE_STRING
+#elif defined(DEFAULT_ARM64_CODEGEN)
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_ARM64_TRIPLE_STRING
+#elif defined(DEFAULT_MIPS_CODEGEN)
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_MIPS_TRIPLE_STRING
+#elif defined(DEFAULT_MIPS64_CODEGEN)
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_MIPS64_TRIPLE_STRING
+#elif defined(DEFAULT_X86_CODEGEN)
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_X86_TRIPLE_STRING
+#elif defined(DEFAULT_X86_64_CODEGEN)
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_X86_64_TRIPLE_STRING
+#endif
+
+#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
+  #define ARM_USE_VFP
+#endif
+
+//---------------------------------------------------------------------------
+
+#endif // BCC_CONFIG_CONFIG_H
diff --git a/libbcc/include/bcc/Renderscript/RSCompilerDriver.h b/libbcc/include/bcc/Renderscript/RSCompilerDriver.h
new file mode 100644
index 0000000..76c9f98
--- /dev/null
+++ b/libbcc/include/bcc/Renderscript/RSCompilerDriver.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_RS_COMPILER_DRIVER_H
+#define BCC_RS_COMPILER_DRIVER_H
+
+#include "bcc/Compiler.h"
+#include "bcc/Renderscript/RSScript.h"
+
+#include "bcinfo/MetadataExtractor.h"
+
+#include <list>
+#include <string>
+#include <vector>
+
+namespace bcc {
+
+class BCCContext;
+class CompilerConfig;
+class RSCompilerDriver;
+class Source;
+
+// Type signature for dynamically loaded initialization of an RSCompilerDriver.
+typedef void (*RSCompilerDriverInit_t) (bcc::RSCompilerDriver *);
+// Name of the function that we attempt to dynamically load/execute.
+#define RS_COMPILER_DRIVER_INIT_FN rsCompilerDriverInit
+
+class RSCompilerDriver {
+private:
+  CompilerConfig *mConfig;
+  Compiler mCompiler;
+
+  // Are we compiling under an RS debug context with additional checks?
+  bool mDebugContext;
+
+  // Callback before linking with the runtime library.
+  RSLinkRuntimeCallback mLinkRuntimeCallback;
+
+  // Do we merge global variables on ARM using LLVM's optimization pass?
+  // Disabling LLVM's global merge pass allows static globals to be correctly
+  // emitted to ELF. This can result in decreased performance due to increased
+  // register pressure, but it does make the resulting code easier to debug
+  // and work with.
+  bool mEnableGlobalMerge;
+
+  // Specifies whether we should embed global variable information in the
+  // code via special RS variables that can be examined later by the driver.
+  bool mEmbedGlobalInfo;
+
+  // Specifies whether we should skip constant (immutable) global variables
+  // when potentially embedding information about globals.
+  bool mEmbedGlobalInfoSkipConstant;
+
+  // Setup the compiler config for the given script. Return true if mConfig has
+  // been changed and false if it remains unchanged.
+  bool setupConfig(const RSScript &pScript);
+
+  // Compiles the provided bitcode, placing the binary at pOutputPath.
+  // - If pDumpIR is true, a ".ll" file will also be created.
+  Compiler::ErrorCode compileScript(RSScript& pScript, const char* pScriptName,
+                                    const char* pOutputPath,
+                                    const char* pRuntimePath,
+                                    const char* pBuildChecksum,
+                                    bool pDumpIR);
+
+public:
+  RSCompilerDriver();
+  ~RSCompilerDriver();
+
+  Compiler *getCompiler() {
+    return &mCompiler;
+  }
+
+  void setConfig(CompilerConfig *config) {
+    mConfig = config;
+  }
+
+  void setDebugContext(bool v) {
+    mDebugContext = v;
+  }
+
+  void setLinkRuntimeCallback(RSLinkRuntimeCallback c) {
+    mLinkRuntimeCallback = c;
+  }
+
+  RSLinkRuntimeCallback getLinkRuntimeCallback() const {
+    return mLinkRuntimeCallback;
+  }
+
+  // This function enables/disables merging of global static variables.
+  // Note that it only takes effect on ARM architectures (other architectures
+  // do not offer this option).
+  void setEnableGlobalMerge(bool v) {
+    mEnableGlobalMerge = v;
+  }
+
+  bool getEnableGlobalMerge() const {
+    return mEnableGlobalMerge;
+  }
+
+  const CompilerConfig * getConfig() const {
+    return mConfig;
+  }
+
+  // Set to true if we should embed global variable information in the code.
+  void setEmbedGlobalInfo(bool v) {
+    mEmbedGlobalInfo = v;
+  }
+
+  // Returns true if we should embed global variable information in the code.
+  bool getEmbedGlobalInfo() const {
+    return mEmbedGlobalInfo;
+  }
+
+  // Set to true if we should skip constant (immutable) global variables when
+  // potentially embedding information about globals.
+  void setEmbedGlobalInfoSkipConstant(bool v) {
+    mEmbedGlobalInfoSkipConstant = v;
+  }
+
+  // Returns true if we should skip constant (immutable) global variables when
+  // potentially embedding information about globals.
+  bool getEmbedGlobalInfoSkipConstant() const {
+    return mEmbedGlobalInfoSkipConstant;
+  }
+
+  // FIXME: This method accompany with loadScript and compileScript should
+  //        all be const-methods. They're not now because the getAddress() in
+  //        SymbolResolverInterface is not a const-method.
+  // Returns true if script is successfully compiled.
+  bool build(BCCContext& pContext, const char* pCacheDir, const char* pResName,
+             const char* pBitcode, size_t pBitcodeSize,
+             const char *pBuildChecksum, const char* pRuntimePath,
+             RSLinkRuntimeCallback pLinkRuntimeCallback = nullptr,
+             bool pDumpIR = false);
+
+  bool buildScriptGroup(
+      BCCContext& Context, const char* pOutputFilepath, const char* pRuntimePath,
+      const char* pRuntimeRelaxedPath, bool dumpIR, const char* buildChecksum,
+      const std::vector<Source*>& sources,
+      const std::list<std::list<std::pair<int, int>>>& toFuse,
+      const std::list<std::string>& fused,
+      const std::list<std::list<std::pair<int, int>>>& invokes,
+      const std::list<std::string>& invokeBatchNames);
+
+  // Returns true if script is successfully compiled.
+  bool buildForCompatLib(RSScript &pScript, const char *pOut,
+                         const char *pBuildChecksum, const char *pRuntimePath,
+                         bool pDumpIR);
+};
+
+} // end namespace bcc
+
+#endif // BCC_RS_COMPILER_DRIVER_H
diff --git a/libbcc/include/bcc/Renderscript/RSScript.h b/libbcc/include/bcc/Renderscript/RSScript.h
new file mode 100644
index 0000000..b88298a
--- /dev/null
+++ b/libbcc/include/bcc/Renderscript/RSScript.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_RS_SCRIPT_H
+#define BCC_RS_SCRIPT_H
+
+#include "bcc/Script.h"
+#include "bcc/Support/Sha1Util.h"
+
+namespace llvm {
+  class Module;
+}
+
+namespace bcc {
+
+class RSScript;
+class Source;
+class CompilerConfig;
+
+typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
+
+
+class RSScript : public Script {
+public:
+  // This is one-one mapping with the llvm::CodeGenOpt::Level in
+  // 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
+  };
+
+private:
+  unsigned mCompilerVersion;
+
+  OptimizationLevel mOptimizationLevel;
+
+  RSLinkRuntimeCallback mLinkRuntimeCallback;
+
+  bool mEmbedInfo;
+
+  // Specifies whether we should embed global variable information in the
+  // code via special RS variables that can be examined later by the driver.
+  bool mEmbedGlobalInfo;
+
+  // Specifies whether we should skip constant (immutable) global variables
+  // when potentially embedding information about globals.
+  bool mEmbedGlobalInfoSkipConstant;
+
+private:
+  // This will be invoked when the containing source has been reset.
+  virtual bool doReset();
+
+public:
+  static bool LinkRuntime(RSScript &pScript, const char *rt_path = nullptr);
+
+  explicit RSScript(Source &pSource);
+
+  // Passing in the CompilerConfig allows the optimization level to
+  // be derived rather than defaulted to aggressive (-O3)
+  RSScript(Source &pSource, const CompilerConfig * pCompilerConfig);
+
+  virtual ~RSScript() { }
+
+  void setCompilerVersion(unsigned pCompilerVersion) {
+    mCompilerVersion = pCompilerVersion;
+  }
+
+  unsigned getCompilerVersion() const {
+    return mCompilerVersion;
+  }
+
+  void setOptimizationLevel(OptimizationLevel pOptimizationLevel) {
+    mOptimizationLevel = pOptimizationLevel;
+  }
+
+  OptimizationLevel getOptimizationLevel() const {
+    return mOptimizationLevel;
+  }
+
+  void setLinkRuntimeCallback(RSLinkRuntimeCallback fn){
+    mLinkRuntimeCallback = fn;
+  }
+
+  void setEmbedInfo(bool pEnable) {
+    mEmbedInfo = pEnable;
+  }
+
+  bool getEmbedInfo() const {
+    return mEmbedInfo;
+  }
+
+  // Set to true if we should embed global variable information in the code.
+  void setEmbedGlobalInfo(bool pEnable) {
+    mEmbedGlobalInfo = pEnable;
+  }
+
+  // Returns true if we should embed global variable information in the code.
+  bool getEmbedGlobalInfo() const {
+    return mEmbedGlobalInfo;
+  }
+
+  // Set to true if we should skip constant (immutable) global variables when
+  // potentially embedding information about globals.
+  void setEmbedGlobalInfoSkipConstant(bool pEnable) {
+    mEmbedGlobalInfoSkipConstant = pEnable;
+  }
+
+  // Returns true if we should skip constant (immutable) global variables when
+  // potentially embedding information about globals.
+  bool getEmbedGlobalInfoSkipConstant() const {
+    return mEmbedGlobalInfoSkipConstant;
+  }
+};
+
+} // end namespace bcc
+
+#endif // BCC_RS_SCRIPT_H
diff --git a/libbcc/include/bcc/Renderscript/RSScriptGroupFusion.h b/libbcc/include/bcc/Renderscript/RSScriptGroupFusion.h
new file mode 100644
index 0000000..c173ac4
--- /dev/null
+++ b/libbcc/include/bcc/Renderscript/RSScriptGroupFusion.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_RS_SCRIPT_GROUP_FUSION_H
+#define BCC_RS_SCRIPT_GROUP_FUSION_H
+
+#include <vector>
+#include <string>
+
+namespace llvm {
+class Module;
+}
+
+namespace bcc {
+
+class Source;
+class BCCContext;
+
+/// @brief Fuse kernels
+///
+/// @param Context bcc context.
+/// @param sources The Sources containing the kernels.
+/// @param slots The slots where the kernels are located.
+/// @param fusedName
+/// @return True, if kernels are successfully fused. False, otherwise. It's up to
+/// the caller on how to deal with unsuccessful fusion. A script group can
+/// execute with either fused kernels or individual kernels.
+bool fuseKernels(BCCContext& Context,
+                 const std::vector<Source *>& sources,
+                 const std::vector<int>& slots,
+                 const std::string& fusedName,
+                 llvm::Module* mergedModule);
+
+bool renameInvoke(BCCContext& Context, const Source* source, const int slot,
+                  const std::string& newName, llvm::Module* mergedModule);
+}
+
+#endif /* BCC_RS_SCRIPT_GROUP_FUSION_H */
diff --git a/libbcc/include/bcc/Renderscript/RSTransforms.h b/libbcc/include/bcc/Renderscript/RSTransforms.h
new file mode 100644
index 0000000..04e8460
--- /dev/null
+++ b/libbcc/include/bcc/Renderscript/RSTransforms.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_RS_TRANSFORMS_H
+#define BCC_RS_TRANSFORMS_H
+
+namespace llvm {
+  class ModulePass;
+  class FunctionPass;
+}
+
+namespace bcc {
+
+extern const char BCC_INDEX_VAR_NAME[];
+
+llvm::ModulePass *
+createRSKernelExpandPass(bool pEnableStepOpt);
+
+llvm::FunctionPass *
+createRSInvariantPass();
+
+llvm::FunctionPass *
+createRSInvokeHelperPass();
+
+llvm::ModulePass * createRSEmbedInfoPass();
+
+llvm::ModulePass * createRSGlobalInfoPass(bool pSkipConstants);
+
+llvm::ModulePass * createRSScreenFunctionsPass();
+
+llvm::ModulePass * createRSIsThreadablePass();
+
+llvm::ModulePass * createRSX86_64CallConvPass();
+
+llvm::ModulePass * createRSAddDebugInfoPass();
+
+llvm::FunctionPass *createRSX86TranslateGEPPass();
+
+} // end namespace bcc
+
+#endif // BCC_RS_TRANSFORMS_H
diff --git a/libbcc/include/bcc/Renderscript/RSUtils.h b/libbcc/include/bcc/Renderscript/RSUtils.h
new file mode 100644
index 0000000..4e80c4e
--- /dev/null
+++ b/libbcc/include/bcc/Renderscript/RSUtils.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_RS_UTILS_H
+#define BCC_RS_UTILS_H
+
+#include "rsDefines.h"
+
+#include <llvm/IR/Type.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/ADT/StringRef.h>
+
+#include <string>
+
+namespace {
+
+static inline llvm::StringRef getUnsuffixedStructName(const llvm::StructType *T) {
+#ifdef FORCE_BUILD_LLVM_DISABLE_NDEBUG
+  // Bug: 22926131
+  // When building with assertions enabled, LLVM cannot read the name of a
+  // literal (anonymous) structure, because they shouldn't actually ever have
+  // a name. Unfortunately, due to past definitions of RenderScript object
+  // types as anonymous structures typedef-ed to their proper typename,
+  // we had been relying on accessing this information. LLVM bitcode retains
+  // the typedef-ed name for such anonymous structures. There is a
+  // corresponding (safe) fix to the RenderScript headers to actually name
+  // these types the same as their typedef name to simplify things. That
+  // fixes this issue going forward, but it won't allow us to compile legacy
+  // code properly. In that case, we just have non-assert builds ignore the
+  // fact that anonymous structures shouldn't have their name read, and do it
+  // anyway. Note that RSCompilerDriver.cpp checks the compiler version
+  // number (from llvm-rs-cc) to ensure that we are only ever building modern
+  // code when we have assertions enabled. Legacy code can only be compiled
+  // correctly with a non-asserting compiler.
+  //
+  // Note that the whole reason for looking at the "unsuffixed" name of the
+  // type is because LLVM suffixes duplicate typedefs of the same anonymous
+  // structure. In the new case, where all of the RS object types have a
+  // proper name, they won't have a dotted suffix at all. We still need
+  // to look at the old unsuffixed version to handle legacy code properly.
+  if (T->isLiteral()) {
+    return "";
+  }
+#endif
+
+  // Get just the object type name with no suffix.
+  size_t LastDot = T->getName().rfind('.');
+  if (LastDot == strlen("struct")) {
+    // If we get back to just the "struct" part, we know that we had a
+    // raw typename (i.e. struct.rs_element with no ".[0-9]+" suffix on it.
+    // In that case, we will want to create our slice such that it contains
+    // the entire name.
+    LastDot = T->getName().size();
+  }
+  return T->getStructName().slice(0, LastDot);
+}
+
+const char kAllocationTypeName[] = "struct.rs_allocation";
+const char kElementTypeName[]    = "struct.rs_element";
+const char kSamplerTypeName[]    = "struct.rs_sampler";
+const char kScriptTypeName[]     = "struct.rs_script";
+const char kTypeTypeName[]       = "struct.rs_type";
+
+// Returns the RsDataType for a given input LLVM type.
+// This is only used to distinguish the associated RS object types (i.e.
+// rs_allocation, rs_element, rs_sampler, rs_script, and rs_type).
+// All other types are reported back as RS_TYPE_NONE, since no special
+// handling would be necessary.
+static inline enum RsDataType getRsDataTypeForType(const llvm::Type *T) {
+  if (T->isStructTy()) {
+    const llvm::StringRef StructName = getUnsuffixedStructName(llvm::dyn_cast<const llvm::StructType>(T));
+    if (StructName.equals(kAllocationTypeName)) {
+      return RS_TYPE_ALLOCATION;
+    } else if (StructName.equals(kElementTypeName)) {
+      return RS_TYPE_ELEMENT;
+    } else if (StructName.equals(kSamplerTypeName)) {
+      return RS_TYPE_SAMPLER;
+    } else if (StructName.equals(kScriptTypeName)) {
+      return RS_TYPE_SCRIPT;
+    } else if (StructName.equals(kTypeTypeName)) {
+      return RS_TYPE_TYPE;
+    }
+  }
+  return RS_TYPE_NONE;
+}
+
+// Returns true if the input type is one of our RenderScript object types
+// (allocation, element, sampler, script, type) and false if it is not.
+static inline bool isRsObjectType(const llvm::Type *T) {
+  return getRsDataTypeForType(T) != RS_TYPE_NONE;
+}
+
+}  // end namespace
+
+// When we have a general reduction kernel with no combiner function,
+// we will synthesize a combiner function from the accumulator
+// function.  Given the accumulator function name, what should be the
+// name of the combiner function?
+static inline std::string nameReduceCombinerFromAccumulator(llvm::StringRef accumName) {
+  return std::string(accumName) + ".combiner";
+}
+
+#endif // BCC_RS_UTILS_H
diff --git a/libbcc/include/bcc/Script.h b/libbcc/include/bcc/Script.h
new file mode 100644
index 0000000..660cbee
--- /dev/null
+++ b/libbcc/include/bcc/Script.h
@@ -0,0 +1,61 @@
+/*
+ * 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_SCRIPT_H
+#define BCC_SCRIPT_H
+
+namespace bcc {
+
+class Source;
+
+class Script {
+private:
+  // This is the source associated with this object and is going to be
+  // compiled.
+  Source *mSource;
+
+protected:
+  // This hook will be invoked after the script object is successfully reset.
+  virtual bool doReset()
+  { return true; }
+
+public:
+  explicit Script(Source &pSource) : mSource(&pSource) { }
+
+  virtual ~Script() { }
+
+  // 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);
+
+  // Merge (or link) another source into the current source associated with
+  // this Script object. Return false on error.
+  //
+  // This is equivalent to the call to Script::merge(...) on mSource.
+  bool mergeSource(Source &pSource);
+
+  inline Source &getSource()
+  { return *mSource; }
+  inline const Source &getSource() const
+  { return *mSource; }
+};
+
+} // end namespace bcc
+
+#endif  // BCC_SCRIPT_H
diff --git a/libbcc/include/bcc/Source.h b/libbcc/include/bcc/Source.h
new file mode 100644
index 0000000..ad337c9
--- /dev/null
+++ b/libbcc/include/bcc/Source.h
@@ -0,0 +1,112 @@
+/*
+ * 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_SOURCE_H
+#define BCC_SOURCE_H
+
+#include <string>
+
+namespace llvm {
+  class Module;
+}
+
+namespace bcinfo {
+  class MetadataExtractor;
+}
+
+namespace bcc {
+
+class BCCContext;
+
+class Source {
+private:
+  const std::string mName; // A unique name
+  BCCContext &mContext;
+  llvm::Module *mModule;
+
+  bcinfo::MetadataExtractor *mMetadata;
+
+  // If true, destructor won't destroy the mModule.
+  bool mNoDelete;
+
+  // Keep track of whether mModule is destroyed (possibly as a consequence of
+  // getting linked with a different llvm::Module).
+  bool mIsModuleDestroyed;
+
+private:
+  Source(const char* name, 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,
+                                  const char* name,
+                                  llvm::Module &pModule,
+                                  bool pNoDelete = false);
+
+  static Source *CreateEmpty(BCCContext &pContext, const std::string &pName);
+
+  const std::string& getName() const { return mName; }
+
+  // Merge the current source with pSource. pSource
+  // will be destroyed after successfully merged. Return false on error.
+  bool merge(Source &pSource);
+
+  inline BCCContext &getContext()
+  { return mContext; }
+  inline const BCCContext &getContext() const
+  { return mContext; }
+
+  void setModule(llvm::Module *pModule);
+
+  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;
+
+  void addBuildChecksumMetadata(const char *) const;
+
+  // Get whether debugging has been enabled for this module by checking
+  // for presence of debug info in the module.
+  bool getDebugInfoEnabled() const;
+
+  // Extract metadata from mModule using MetadataExtractor.
+  bool extractMetadata();
+  bcinfo::MetadataExtractor* getMetadata() const { return mMetadata; }
+
+  // Mark mModule was destroyed in the process of linking with a different
+  // llvm::Module
+  void markModuleDestroyed() { mIsModuleDestroyed = true; }
+
+  ~Source();
+};
+
+} // namespace bcc
+
+#endif // BCC_SOURCE_H
diff --git a/libbcc/include/bcc/Support/CompilerConfig.h b/libbcc/include/bcc/Support/CompilerConfig.h
new file mode 100644
index 0000000..c558a16
--- /dev/null
+++ b/libbcc/include/bcc/Support/CompilerConfig.h
@@ -0,0 +1,127 @@
+/*
+ * 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_SUPPORT_COMPILER_CONFIG_H
+#define BCC_SUPPORT_COMPILER_CONFIG_H
+
+#include <string>
+#include <vector>
+
+#include <llvm/ADT/Triple.h>
+#include <llvm/Support/CodeGen.h>
+#include <llvm/Target/TargetOptions.h>
+
+namespace llvm {
+
+class Target;
+
+} // end namespace llvm
+
+namespace bcc {
+
+class CompilerConfig {
+private:
+  //===--------------------------------------------------------------------===//
+  // Available Configurations
+  //===--------------------------------------------------------------------===//
+  std::string mTriple;
+
+  // Optional. If given, the name of the target CPU to generate code for.
+  std::string mCPU;
+
+  llvm::TargetOptions mTargetOpts;
+
+  llvm::CodeModel::Model mCodeModel;
+
+  llvm::CodeGenOpt::Level mOptLevel;
+
+  llvm::Reloc::Model mRelocModel;
+
+  // Are we set up to compile for full precision or something reduced?
+  bool mFullPrecision;
+
+  // The list of target specific features to enable or disable -- this should
+  // be a list of strings starting with '+' (enable) or '-' (disable).
+  std::string mFeatureString;
+
+  //===--------------------------------------------------------------------===//
+  // These are generated by CompilerConfig during initialize().
+  //===--------------------------------------------------------------------===//
+  const llvm::Target *mTarget;
+  bool initializeTarget();
+
+  llvm::Triple::ArchType mArchType;
+  bool initializeArch();
+
+public:
+  //===--------------------------------------------------------------------===//
+  // Getters
+  //===--------------------------------------------------------------------===//
+  inline const std::string &getTriple() const
+  { return mTriple; }
+
+  inline const std::string &getCPU() const
+  { return mCPU; }
+  inline void setCPU(const std::string &pCPU)
+  { mCPU = pCPU; }
+
+  inline const llvm::TargetOptions &getTargetOptions() const
+  { return mTargetOpts; }
+  inline llvm::TargetOptions &getTargetOptions()
+  { return mTargetOpts; }
+
+  inline llvm::CodeModel::Model getCodeModel() const
+  { return mCodeModel; }
+  inline void setCodeModel(llvm::CodeModel::Model pCodeMode)
+  { mCodeModel = pCodeMode; }
+
+  inline llvm::CodeGenOpt::Level getOptimizationLevel() const
+  { return mOptLevel; }
+  inline void setOptimizationLevel(llvm::CodeGenOpt::Level pOptLvl)
+  { mOptLevel = pOptLvl; }
+
+  inline llvm::Reloc::Model getRelocationModel() const
+  { return mRelocModel; }
+  inline void setRelocationModel(llvm::Reloc::Model pRelocModel)
+  { mRelocModel = pRelocModel; }
+
+  inline const llvm::Target *getTarget() const
+  { return mTarget; }
+
+  inline llvm::Triple::ArchType getArchType() const
+  { return mArchType; }
+
+  inline bool getFullPrecision() const
+  { return mFullPrecision; }
+  inline void setFullPrecision(bool pFullPrecision) {
+    mFullPrecision = pFullPrecision;
+    // Note that we have to reinitialize here to ensure that mFeatureString
+    // is up to date.
+    initializeArch();
+  }
+
+  inline const std::string &getFeatureString() const
+  { return mFeatureString; }
+  void setFeatureString(const std::vector<std::string> &pAttrs);
+
+  explicit CompilerConfig(const std::string &pTriple);
+
+  virtual ~CompilerConfig() { }
+};
+
+} // end namespace bcc
+
+#endif  // BCC_SUPPORT_COMPILER_CONFIG_H
diff --git a/libbcc/include/bcc/Support/Disassembler.h b/libbcc/include/bcc/Support/Disassembler.h
new file mode 100644
index 0000000..0ec0eed
--- /dev/null
+++ b/libbcc/include/bcc/Support/Disassembler.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 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.
+ * 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_SUPPORT_DISASSEMBLER_H
+#define BCC_SUPPORT_DISASSEMBLER_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+namespace llvm {
+  class raw_ostream;
+} // end namespace llvm
+
+namespace bcc {
+
+class OutputFile;
+
+enum DisassembleResult {
+  kDisassembleSuccess,
+  kDisassemblerNotAvailable,
+  kDisassembleInvalidOutput,
+  kDisassembleFailedPrepareOutput,
+  kDisassembleUnknownTarget,
+  kDisassembleFailedSetup,
+  kDisassembleOutOfMemory,
+  kDisassembleInvalidInstruction,
+};
+
+DisassembleResult Disassemble(llvm::raw_ostream &pOutput, const char *pTriple,
+                              const char *pFuncName, const uint8_t *pFunc,
+                              size_t pFuncSize);
+
+DisassembleResult Disassemble(OutputFile &pOutput, const char *pTriple,
+                              const char *pFuncName, const uint8_t *pFunc,
+                              size_t pFuncSize);
+
+} // end namespace bcc
+
+#endif // BCC_SUPPORT_DISASSEMBLER_H
diff --git a/libbcc/include/bcc/Support/File.h b/libbcc/include/bcc/Support/File.h
new file mode 100644
index 0000000..6367359
--- /dev/null
+++ b/libbcc/include/bcc/Support/File.h
@@ -0,0 +1,72 @@
+/*
+ * 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_SUPPORT_FILE_H
+#define BCC_SUPPORT_FILE_H
+
+#include "bcc/Support/FileBase.h"
+
+namespace bcc {
+
+template<enum FileBase::OpenModeEnum OpenMode>
+struct FileAttribute {
+  // The flags to the 2nd argument in ::open().
+  enum { kOpenFlags };
+
+  // Default value of LockMode.
+  enum { kDefaultLockMode };
+};
+
+// FileAttribute for accessing read-only file
+template<>
+struct FileAttribute<FileBase::kReadMode> {
+  enum { kOpenFlags       = O_RDONLY };
+  enum { kDefaultLockMode = FileBase::kReadLock };
+};
+
+// FileAttribute for accessing writable file
+template<>
+struct FileAttribute<FileBase::kWriteMode> {
+  enum { kOpenFlags       = O_RDWR | O_CREAT };
+  enum { kDefaultLockMode = FileBase::kWriteLock };
+};
+
+template<enum FileBase::OpenModeEnum OpenMode>
+class File : public FileBase {
+public:
+  File(const std::string &pFilename, unsigned pFlags)
+    : FileBase(pFilename, FileAttribute<OpenMode>::kOpenFlags, pFlags) { }
+
+  inline bool lock(enum LockModeEnum pMode = static_cast<enum LockModeEnum>(
+                      FileAttribute<OpenMode>::kDefaultLockMode),
+                   bool pNonblocking = true,
+                   unsigned pMaxRetry = FileBase::kDefaultMaxRetryLock,
+                   useconds_t pRetryInterval =
+                      FileBase::kDefaultRetryLockInterval) {
+    return FileBase::lock(pMode, pNonblocking, pMaxRetry, pRetryInterval);
+  }
+
+  inline android::FileMap *createMap(off_t pOffset, size_t pLength,
+                                     bool pIsReadOnly =
+                                        (OpenMode == FileBase::kReadMode)) {
+    return FileBase::createMap(pOffset, pLength, pIsReadOnly);
+  }
+};
+
+
+} // end namespace bcc
+
+#endif  // BCC_SUPPORT_FILE_H
diff --git a/libbcc/include/bcc/Support/FileBase.h b/libbcc/include/bcc/Support/FileBase.h
new file mode 100644
index 0000000..cf9c998
--- /dev/null
+++ b/libbcc/include/bcc/Support/FileBase.h
@@ -0,0 +1,155 @@
+/*
+ * 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_SUPPORT_FILE_BASE_H
+#define BCC_SUPPORT_FILE_BASE_H
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <string>
+#include <system_error>
+
+namespace android {
+  class FileMap;
+}
+
+namespace bcc {
+
+class FileBase {
+public:
+  enum OpenModeEnum {
+    kReadMode       = 1 << 0,
+    kWriteMode      = 1 << 1,
+    kReadWriteMode  = (kReadMode | kWriteMode),
+  };
+
+  enum FlagEnum {
+    kBinary = 1 << 0,
+    kTruncate = 1 << 1,
+    kAppend = 1 << 2,
+    kDeleteOnClose = 1 << 3
+  };
+
+  enum LockModeEnum {
+    // The shared resource behind the Stream locked in ReadLock mode can be
+    // locked by other processes at the same time.
+    kReadLock,
+
+    // The shared resource behind the Stream locked in WriteLock mode can only
+    // be locked by one process. It's exclusive. That is, the shared resource
+    // cannot have both ReadLock and WriteLock simultaneously.
+    kWriteLock
+  };
+
+  // Default configuration to the lock().
+  enum {
+    kDefaultMaxRetryLock = 4,
+    kDefaultRetryLockInterval = 200000UL,
+  };
+
+protected:
+  // Grant direct access of the internal file descriptor to the sub-class and
+  // error message such that they can implement their own I/O functionality.
+  int mFD;
+
+  std::error_code mError;
+
+private:
+  std::string mName;
+
+  // The 2nd argument to the POSIX open().
+  unsigned mOpenFlags;
+
+  // True true if we should call unlock() in destructor.
+  bool mShouldUnlock;
+
+  // True if file should be deleted in destructor.
+  bool mShouldDelete;
+
+  // Open mName with flag mOpenFlags (using POSIX open().)
+  bool open();
+
+  // Return true if mFD is the corresponded file descriptor to the file named
+  // mName on the filesystem. This check may returns failed, for example,
+  // someone re-create the file with the same name after we openning the file.
+  bool checkFileIntegrity();
+
+  inline bool reopen() {
+    // It's a private method, and all its callers are the few that can invoke it.
+    // That is, the pre-condition will be checked by the caller. Therefore, we don't
+    // need to check it again in reopen().
+    close();
+    return open();
+  }
+
+private:
+  FileBase(FileBase &); // Do not implement.
+  void operator=(const FileBase &); // Do not implement.
+
+protected:
+  // pOpenFlags is the 2nd argument to the POSIX open(). pFlags are the flags to
+  // FileBase. It's a bit set composed by the value defined in
+  // FileBase::FlagEnum.
+  FileBase(const std::string &pFilename, unsigned pOpenFlags, unsigned pFlags);
+
+  void detectError();
+
+public:
+  // Lock the file descriptor in given pMode. If pNonblocking is true, the lock
+  // request issued will return immediately when the shared resource is locked.
+  // In this case, it retries pMaxRetry times, each wait pRetryInterval (in
+  // usecs) before the previous retry getting done.
+  //
+  // Only file is allowed to use this API.
+  bool lock(enum LockModeEnum pMode, bool pNonblocking = true,
+            unsigned pMaxRetry = kDefaultMaxRetryLock,
+            useconds_t pRetryInterval = kDefaultRetryLockInterval);
+
+  void unlock();
+
+  // Map the file content to the memory.
+  //
+  // One who gets non-null android::FileMap returned from this API is responsible
+  // for destroying it after the use.
+  android::FileMap *createMap(off_t pOffset, size_t pLength, bool pIsReadOnly);
+
+  size_t getSize();
+
+  off_t seek(off_t pOffset);
+  off_t tell();
+
+  inline bool hasError() const
+  { return (bool) mError; }
+
+  inline const std::error_code &getError() const
+  { return mError; }
+
+  // The return value of std::error_code::message() is obtained upon the call
+  // and is passed by value (that is, it's not a member of std::error_code.)
+  inline std::string getErrorMessage() const
+  { return mError.message(); }
+
+  inline const std::string &getName() const
+  { return mName; }
+
+  void close();
+
+  virtual ~FileBase();
+};
+
+} // end namespace bcc
+
+#endif  // BCC_SUPPORT_FILE_BASE_H
diff --git a/libbcc/include/bcc/Support/FileMutex.h b/libbcc/include/bcc/Support/FileMutex.h
new file mode 100644
index 0000000..ec9ac21
--- /dev/null
+++ b/libbcc/include/bcc/Support/FileMutex.h
@@ -0,0 +1,43 @@
+/*
+ * 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_SUPPORT_FILE_MUTEX_H
+#define BCC_SUPPORT_FILE_MUTEX_H
+
+#include <string>
+
+#include "bcc/Support/FileBase.h"
+
+namespace bcc {
+
+template<enum FileBase::LockModeEnum LockMode>
+class FileMutex : public FileBase {
+public:
+  explicit FileMutex(const std::string &pFileToLock)
+    : FileBase(pFileToLock + ".lock", O_RDONLY | O_CREAT, kDeleteOnClose) { }
+
+  // Provide a lock() interface filled with default configuration.
+  inline bool lock(bool pNonblocking = true,
+                   unsigned pMaxRetry = FileBase::kDefaultMaxRetryLock,
+                   useconds_t pRetryInterval =
+                       FileBase::kDefaultRetryLockInterval) {
+    return FileBase::lock(LockMode, pNonblocking, pMaxRetry, pRetryInterval);
+  }
+};
+
+} // namespace bcc
+
+#endif  // BCC_SUPPORT_FILE_MUTEX_H
diff --git a/libbcc/include/bcc/Support/Initialization.h b/libbcc/include/bcc/Support/Initialization.h
new file mode 100644
index 0000000..521f082
--- /dev/null
+++ b/libbcc/include/bcc/Support/Initialization.h
@@ -0,0 +1,30 @@
+/*
+ * 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_SUPPORT_INITIALIZATION_H
+#define BCC_SUPPORT_INITIALIZATION_H
+
+namespace bcc {
+
+namespace init {
+
+void Initialize();
+
+} // end namespace init
+
+} // end namespace bcc
+
+#endif // BCC_SUPPORT_INITIALIZATION_H
diff --git a/libbcc/include/bcc/Support/InputFile.h b/libbcc/include/bcc/Support/InputFile.h
new file mode 100644
index 0000000..01f2b02
--- /dev/null
+++ b/libbcc/include/bcc/Support/InputFile.h
@@ -0,0 +1,35 @@
+/*
+ * 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_SUPPORT_INPUT_FILE_H
+#define BCC_SUPPORT_INPUT_FILE_H
+
+#include "bcc/Support/File.h"
+#include "bcc/Support/FileBase.h"
+
+namespace bcc {
+
+class InputFile : public File<FileBase::kReadMode> {
+  typedef File<FileBase::kReadMode> super;
+public:
+  explicit InputFile(const std::string &pFilename, unsigned pFlags = 0);
+
+  ssize_t read(void *pBuf, size_t count);
+};
+
+} // end namespace bcc
+
+#endif  // BCC_SUPPORT_INPUT_FILE_H
diff --git a/libbcc/include/bcc/Support/Log.h b/libbcc/include/bcc/Support/Log.h
new file mode 100644
index 0000000..f4079ef
--- /dev/null
+++ b/libbcc/include/bcc/Support/Log.h
@@ -0,0 +1,25 @@
+/*
+ * 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_SUPPORT_LOG_H
+#define BCC_SUPPORT_LOG_H
+
+#ifndef LOG_TAG
+#   define LOG_TAG "bcc"
+#   include <cutils/log.h>
+#endif
+
+#endif // BCC_SUPPORT_LOG_H
diff --git a/libbcc/include/bcc/Support/OutputFile.h b/libbcc/include/bcc/Support/OutputFile.h
new file mode 100644
index 0000000..daabbf8
--- /dev/null
+++ b/libbcc/include/bcc/Support/OutputFile.h
@@ -0,0 +1,47 @@
+/*
+ * 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_SUPPORT_OUTPUT_FILE_H
+#define BCC_SUPPORT_OUTPUT_FILE_H
+
+#include "bcc/Support/File.h"
+#include "bcc/Support/FileBase.h"
+
+namespace llvm {
+  class raw_fd_ostream;
+}
+
+namespace bcc {
+
+class OutputFile : public File<FileBase::kWriteMode> {
+  typedef File<FileBase::kWriteMode> super;
+public:
+  explicit OutputFile(const std::string &pFilename, unsigned pFlags = 0);
+
+  ssize_t write(const void *pBuf, size_t count);
+
+  void truncate();
+
+  // This is similar to the system call dup(). It creates a copy of the file
+  // descriptor it contains and wrap it in llvm::raw_fd_ostream object. It
+  // returns a non-NULL object if everything goes well and user should later
+  // use delete operator to destroy it by itself.
+  llvm::raw_fd_ostream *dup();
+};
+
+} // end namespace bcc
+
+#endif  // BCC_SUPPORT_OUTPUT_FILE_H
diff --git a/libbcc/include/bcc/Support/Properties.h b/libbcc/include/bcc/Support/Properties.h
new file mode 100644
index 0000000..4c3c404
--- /dev/null
+++ b/libbcc/include/bcc/Support/Properties.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013, 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_SUPPORT_PROPERTIES_H
+#define BCC_SUPPORT_PROPERTIES_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#if !defined(RS_SERVER) && defined(__ANDROID__)
+#include <cutils/properties.h>
+#endif
+
+static inline uint32_t getProperty(const char *str) {
+#if !defined(RS_SERVER) && defined(__ANDROID__)
+    char buf[PROPERTY_VALUE_MAX];
+    property_get(str, buf, "0");
+    return atoi(buf);
+#else
+    return 0;
+#endif
+}
+
+#endif // BCC_SUPPORT_PROPERTIES_H
diff --git a/libbcc/include/bcc/Support/Sha1Util.h b/libbcc/include/bcc/Support/Sha1Util.h
new file mode 100644
index 0000000..b7712ed
--- /dev/null
+++ b/libbcc/include/bcc/Support/Sha1Util.h
@@ -0,0 +1,57 @@
+/*
+ * 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_SUPPORT_SHA1_UTIL_H
+#define BCC_SUPPORT_SHA1_UTIL_H
+
+#include <stdint.h>
+
+#include <cstddef>
+
+// This guard prevents system sha1.h (such as the one in bionic) has been
+// included before this header.
+#ifndef SHA1_DIGEST_LENGTH
+#define SHA1_DIGEST_LENGTH 20
+#endif
+
+namespace bcc {
+
+class Sha1Util {
+private:
+  Sha1Util(); // DISABLED.
+  Sha1Util(Sha1Util &); // DISABLED.
+
+public:
+  // Return true on success.
+  static bool GetSHA1DigestFromFile(uint8_t pResult[SHA1_DIGEST_LENGTH],
+                                    const char *pFilename);
+
+  // Return true on success.
+  static bool GetSHA1DigestFromBuffer(uint8_t pResult[SHA1_DIGEST_LENGTH],
+                                      const uint8_t *pData, size_t pSize);
+
+  // Useful function when passing buffer of type  "const char *."
+  static bool GetSHA1DigestFromBuffer(uint8_t pResult[SHA1_DIGEST_LENGTH],
+                                      const char *pData, size_t pSize) {
+    return GetSHA1DigestFromBuffer(pResult,
+                                   reinterpret_cast<const uint8_t*>(pData),
+                                   pSize);
+  }
+};
+
+} // end namespace bcc
+
+#endif // BCC_SUPPORT_SHA1_UTIL_H
diff --git a/libbcc/include/bcinfo/BitcodeTranslator.h b/libbcc/include/bcinfo/BitcodeTranslator.h
new file mode 100644
index 0000000..92fe777
--- /dev/null
+++ b/libbcc/include/bcinfo/BitcodeTranslator.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011, 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 __ANDROID_BCINFO_BITCODETRANSLATOR_H__
+#define __ANDROID_BCINFO_BITCODETRANSLATOR_H__
+
+#include <cstddef>
+
+namespace bcinfo {
+
+class BitcodeTranslator {
+ private:
+  const char *mBitcode;
+  size_t mBitcodeSize;
+  const char *mTranslatedBitcode;
+  size_t mTranslatedBitcodeSize;
+  unsigned int mVersion;
+
+ public:
+  /**
+   * Translates \p bitcode of a particular \p version to the latest version.
+   *
+   * \param bitcode - input bitcode string.
+   * \param bitcodeSize - length of \p bitcode string (in bytes).
+   * \param version - corresponding target SDK version of \p bitcode.
+   */
+  BitcodeTranslator(const char *bitcode, size_t bitcodeSize,
+                    unsigned int version);
+
+  ~BitcodeTranslator();
+
+  /**
+   * Translate the supplied bitcode to the latest supported version.
+   *
+   * \return true if the bitcode was translated successfully and false if an
+   *         error occurred.
+   */
+  bool translate();
+
+  /**
+   * \return translated bitcode.
+   */
+  const char *getTranslatedBitcode() const {
+    return mTranslatedBitcode;
+  }
+
+  /**
+   * \return size of the translated bitcode (in bytes).
+   */
+  size_t getTranslatedBitcodeSize() const {
+    return mTranslatedBitcodeSize;
+  }
+};
+
+}  // namespace bcinfo
+
+#endif  // __ANDROID_BCINFO_BITCODETRANSLATOR_H__
diff --git a/libbcc/include/bcinfo/BitcodeWrapper.h b/libbcc/include/bcinfo/BitcodeWrapper.h
new file mode 100644
index 0000000..e3e65d2
--- /dev/null
+++ b/libbcc/include/bcinfo/BitcodeWrapper.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 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.
+ * 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 __ANDROID_BCINFO_BITCODEWRAPPER_H__
+#define __ANDROID_BCINFO_BITCODEWRAPPER_H__
+
+#include "bcinfo/Wrap/BCHeaderField.h"
+
+#include <cstddef>
+#include <stdint.h>
+
+namespace bcinfo {
+
+struct AndroidBitcodeWrapper {
+  uint32_t Magic;
+  uint32_t Version;
+  uint32_t BitcodeOffset;
+  uint32_t BitcodeSize;
+  uint32_t HeaderVersion;
+  uint32_t TargetAPI;
+  uint32_t PNaClVersion;
+  uint16_t CompilerVersionTag;
+  uint16_t CompilerVersionLen;
+  uint32_t CompilerVersion;
+  uint16_t OptimizationLevelTag;
+  uint16_t OptimizationLevelLen;
+  uint32_t OptimizationLevel;
+};
+
+enum BCFileType {
+  BC_NOT_BC = 0,
+  BC_WRAPPER = 1,
+  BC_RAW = 2
+};
+
+class BitcodeWrapper {
+ private:
+  enum BCFileType mFileType;
+  const char *mBitcode;
+  size_t mBitcodeSize;
+
+  uint32_t mHeaderVersion;
+  uint32_t mTargetAPI;
+  uint32_t mCompilerVersion;
+  uint32_t mOptimizationLevel;
+
+ public:
+  /**
+   * Reads wrapper information from \p bitcode.
+   *
+   * \param bitcode - input bitcode string.
+   * \param bitcodeSize - length of \p bitcode string (in bytes).
+   */
+  BitcodeWrapper(const char *bitcode, size_t bitcodeSize);
+
+  ~BitcodeWrapper();
+
+  /**
+   * Attempt to unwrap the target bitcode. This function is \deprecated.
+   *
+   * \return true on success and false if an error occurred.
+   */
+  bool unwrap();
+
+  /**
+   * \return type of bitcode file.
+   */
+  enum BCFileType getBCFileType() const {
+    return mFileType;
+  }
+
+  /**
+   * \return header version of bitcode wrapper.
+   */
+  uint32_t getHeaderVersion() const {
+    return mHeaderVersion;
+  }
+
+  /**
+   * \return target API version for this bitcode.
+   */
+  uint32_t getTargetAPI() const {
+    return mTargetAPI;
+  }
+
+  /**
+   * \return compiler version that generated this bitcode.
+   */
+  uint32_t getCompilerVersion() const {
+    return mCompilerVersion;
+  }
+
+  /**
+   * \return compiler optimization level for this bitcode.
+   */
+  uint32_t getOptimizationLevel() const {
+    return mOptimizationLevel;
+  }
+
+};
+
+/**
+ * Helper function to emit just the bitcode wrapper returning the number of
+ * bytes that were written.
+ *
+ * \param wrapper - where to write header information into.
+ * \param bitcodeSize - size of bitcode in bytes.
+ * \param targetAPI - target API version for this bitcode.
+ * \param compilerVersion - compiler version that generated this bitcode.
+ * \param optimizationLevel - compiler optimization level for this bitcode.
+ *
+ * \return number of wrapper bytes written into the \p buffer.
+ */
+static inline size_t writeAndroidBitcodeWrapper(AndroidBitcodeWrapper *wrapper,
+    size_t bitcodeSize, uint32_t targetAPI, uint32_t compilerVersion,
+    uint32_t optimizationLevel) {
+  if (!wrapper) {
+    return 0;
+  }
+
+  wrapper->Magic = 0x0B17C0DE;
+  wrapper->Version = 0;
+  wrapper->BitcodeOffset = sizeof(*wrapper);
+  wrapper->BitcodeSize = bitcodeSize;
+  wrapper->HeaderVersion = 0;
+  wrapper->TargetAPI = targetAPI;
+  wrapper->PNaClVersion = 0;
+  wrapper->CompilerVersionTag = BCHeaderField::kAndroidCompilerVersion;
+  wrapper->CompilerVersionLen = 4;
+  wrapper->CompilerVersion = compilerVersion;
+  wrapper->OptimizationLevelTag = BCHeaderField::kAndroidOptimizationLevel;
+  wrapper->OptimizationLevelLen = 4;
+  wrapper->OptimizationLevel = optimizationLevel;
+
+  return sizeof(*wrapper);
+}
+
+}  // namespace bcinfo
+
+#endif  // __ANDROID_BCINFO_BITCODEWRAPPER_H__
diff --git a/libbcc/include/bcinfo/MetadataExtractor.h b/libbcc/include/bcinfo/MetadataExtractor.h
new file mode 100644
index 0000000..d1de4fe
--- /dev/null
+++ b/libbcc/include/bcinfo/MetadataExtractor.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright 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.
+ * 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 __ANDROID_BCINFO_METADATAEXTRACTOR_H__
+#define __ANDROID_BCINFO_METADATAEXTRACTOR_H__
+
+#include <cstddef>
+#include <memory>
+
+#include <stdint.h>
+
+namespace llvm {
+  class Function;
+  class Module;
+  class NamedMDNode;
+}
+
+namespace bcinfo {
+
+enum RSFloatPrecision {
+  RS_FP_Full = 0,
+  RS_FP_Relaxed = 1,
+};
+
+enum MetadataSignatureBitval {
+  MD_SIG_None        = 0,
+  MD_SIG_In          = 0x000001,
+  MD_SIG_Out         = 0x000002,
+  MD_SIG_Usr         = 0x000004,
+  MD_SIG_X           = 0x000008,
+  MD_SIG_Y           = 0x000010,
+  MD_SIG_Kernel      = 0x000020,
+  MD_SIG_Z           = 0x000040,
+  MD_SIG_Ctxt        = 0x000080,
+};
+
+class MetadataExtractor {
+ public:
+  struct Reduce {
+    // These strings are owned by the Reduce instance, and deleted upon its destruction.
+    // They are assumed to have been allocated by "new []" and hence are deleted by "delete []".
+    const char *mReduceName;
+    const char *mInitializerName;
+    const char *mAccumulatorName;
+    const char *mCombinerName;
+    const char *mOutConverterName;
+    const char *mHalterName;
+
+    uint32_t mSignature;   // of accumulator function
+    uint32_t mInputCount;  // of accumulator function (and of kernel itself)
+    uint32_t mAccumulatorDataSize;  // in bytes
+
+    Reduce() :
+        mReduceName(nullptr),
+        mInitializerName(nullptr), mAccumulatorName(nullptr), mCombinerName(nullptr),
+        mOutConverterName(nullptr), mHalterName(nullptr),
+        mSignature(0), mInputCount(0), mAccumulatorDataSize(0) {
+    }
+    ~Reduce() {
+      delete [] mReduceName;
+      delete [] mInitializerName;
+      delete [] mAccumulatorName;
+      delete [] mCombinerName;
+      delete [] mOutConverterName;
+      delete [] mHalterName;
+    }
+
+    Reduce(const Reduce &) = delete;
+    void operator=(const Reduce &) = delete;
+  };
+
+ private:
+  const llvm::Module *mModule;
+  const char *mBitcode;
+  size_t mBitcodeSize;
+
+  size_t mExportVarCount;
+  size_t mExportFuncCount;
+  size_t mExportForEachSignatureCount;
+  size_t mExportReduceCount;
+  const char **mExportVarNameList;
+  const char **mExportFuncNameList;
+  const char **mExportForEachNameList;
+  const uint32_t *mExportForEachSignatureList;
+  const uint32_t *mExportForEachInputCountList;
+  const Reduce *mExportReduceList;
+
+  size_t mPragmaCount;
+  const char **mPragmaKeyList;
+  const char **mPragmaValueList;
+
+  size_t mObjectSlotCount;
+  const uint32_t *mObjectSlotList;
+
+  uint32_t mTargetAPI;
+  uint32_t mCompilerVersion;
+  uint32_t mOptimizationLevel;
+
+  enum RSFloatPrecision mRSFloatPrecision;
+
+  // Flag to mark that script is threadable.  True by default.
+  bool mIsThreadable;
+
+  const char *mBuildChecksum;
+
+  bool mHasDebugInfo;
+
+  // Helper functions for extraction
+  bool populateForEachMetadata(const llvm::NamedMDNode *Names,
+                               const llvm::NamedMDNode *Signatures);
+  bool populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata);
+  bool populateObjectSlotMetadata(const llvm::NamedMDNode *ObjectSlotMetadata);
+  void populatePragmaMetadata(const llvm::NamedMDNode *PragmaMetadata);
+  void readThreadableFlag(const llvm::NamedMDNode *ThreadableMetadata);
+  void readBuildChecksumMetadata(const llvm::NamedMDNode *ChecksumMetadata);
+
+  uint32_t calculateNumInputs(const llvm::Function *Function,
+                              uint32_t Signature);
+
+ public:
+  /**
+   * Reads metadata from \p bitcode.
+   *
+   * \param bitcode - input bitcode string.
+   * \param bitcodeSize - length of \p bitcode string (in bytes).
+   */
+  MetadataExtractor(const char *bitcode, size_t bitcodeSize);
+
+  /**
+   * Reads metadata from \p module.
+   *
+   * \param module - input module.
+   */
+  explicit MetadataExtractor(const llvm::Module *module);
+
+  ~MetadataExtractor();
+
+  /**
+   * Extract the actual metadata from the supplied bitcode.
+   *
+   * \return true on success and false if an error occurred.
+   */
+  bool extract();
+
+  /**
+   * \return target API level of this bitcode.
+   *
+   * The target API is used during the SDK compilation to provide proper
+   * visibility of the RenderScript runtime API functions.
+   */
+  uint32_t getTargetAPI() const {
+    return mTargetAPI;
+  }
+
+  /**
+   * \return number of exported global variables (slots) in this script/module.
+   */
+  size_t getExportVarCount() const {
+    return mExportVarCount;
+  }
+
+  /**
+   * \return array of exported variable names.
+   */
+  const char **getExportVarNameList() const {
+    return mExportVarNameList;
+  }
+
+  /**
+   * \return number of exported global functions (slots) in this script/module.
+   */
+  size_t getExportFuncCount() const {
+    return mExportFuncCount;
+  }
+
+  /**
+   * \return array of exported function names.
+   */
+  const char **getExportFuncNameList() const {
+    return mExportFuncNameList;
+  }
+
+  /**
+   * \return number of exported ForEach functions in this script/module.
+   */
+  size_t getExportForEachSignatureCount() const {
+    return mExportForEachSignatureCount;
+  }
+
+  /**
+   * \return array of exported ForEach function signatures.
+   */
+  const uint32_t *getExportForEachSignatureList() const {
+    return mExportForEachSignatureList;
+  }
+
+  /**
+   * \return array of exported ForEach function names.
+   */
+  const char **getExportForEachNameList() const {
+    return mExportForEachNameList;
+  }
+
+  /**
+   * \return array of input parameter counts.
+   */
+  const uint32_t *getExportForEachInputCountList() const {
+    return mExportForEachInputCountList;
+  }
+
+  /**
+   * \return number of exported general reduce kernels (slots) in this script/module.
+   */
+  size_t getExportReduceCount() const {
+    return mExportReduceCount;
+  }
+
+  /**
+   * \return array of exported general reduce kernel descriptions.
+   */
+  const Reduce *getExportReduceList() const {
+    return mExportReduceList;
+  }
+
+  /**
+   * \return number of pragmas contained in pragmaKeyList and pragmaValueList.
+   */
+  size_t getPragmaCount() const {
+    return mPragmaCount;
+  }
+
+  /**
+   * \return pragma keys (the name for the pragma).
+   */
+  const char **getPragmaKeyList() const {
+    return mPragmaKeyList;
+  }
+
+  /**
+   * \return pragma values (contents corresponding to a particular pragma key).
+   */
+  const char **getPragmaValueList() const {
+    return mPragmaValueList;
+  }
+
+  /**
+   * \return number of object slots contained in objectSlotList.
+   */
+  size_t getObjectSlotCount() const {
+    return mObjectSlotCount;
+  }
+
+  /**
+   * \return array of object slot numbers that must be cleaned up by driver
+   *         on script teardown.
+   */
+  const uint32_t *getObjectSlotList() const {
+    return mObjectSlotList;
+  }
+
+  /**
+   * \return compiler version that generated this bitcode.
+   */
+  uint32_t getCompilerVersion() const {
+    return mCompilerVersion;
+  }
+
+  /**
+   * \return compiler optimization level for this bitcode.
+   */
+  uint32_t getOptimizationLevel() const {
+    return mOptimizationLevel;
+  }
+
+  /**
+   * \return minimal floating point precision that the script requires.
+   */
+  enum RSFloatPrecision getRSFloatPrecision() const {
+    return mRSFloatPrecision;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature has an "In"
+   * parameter.
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureIn(uint32_t sig) {
+    return sig & MD_SIG_In;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature has an "Out"
+   * parameter.
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureOut(uint32_t sig) {
+    return sig & MD_SIG_Out;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature has a "UsrData"
+   * parameter.
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureUsrData(uint32_t sig) {
+    return sig & MD_SIG_Usr;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature has an "X"
+   * parameter.
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureX(uint32_t sig) {
+    return sig & MD_SIG_X;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature has a "Y"
+   * parameter.
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureY(uint32_t sig) {
+    return sig & MD_SIG_Y;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature is a
+   * pass-by-value "Kernel".
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureKernel(uint32_t sig) {
+    return sig & MD_SIG_Kernel;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature has a "Z"
+   * parameter.
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureZ(uint32_t sig) {
+    return sig & MD_SIG_Z;
+  }
+
+  /**
+   * \return whether or not this ForEach function signature has a "Ctxt"
+   * parameter.
+   *
+   * \param sig - ForEach function signature to check.
+   */
+  static bool hasForEachSignatureCtxt(uint32_t sig) {
+    return sig & MD_SIG_Ctxt;
+  }
+
+  /**
+   * \return whether "Kernels" in this script can be processed
+   * by multiple threads
+   */
+
+  bool isThreadable() const {
+    return mIsThreadable;
+  }
+
+  /**
+   * \return the build checksum extracted from the LLVM metadata
+   */
+  const char *getBuildChecksum() const {
+    return mBuildChecksum;
+  }
+
+  /**
+   * \return whether the module contains debug metadata
+   */
+  bool hasDebugInfo() const {
+    return mHasDebugInfo;
+  }
+};
+
+}  // namespace bcinfo
+
+#endif  // __ANDROID_BCINFO_METADATAEXTRACTOR_H__
diff --git a/libbcc/include/bcinfo/Wrap/BCHeaderField.h b/libbcc/include/bcinfo/Wrap/BCHeaderField.h
new file mode 100644
index 0000000..fd8d585
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/BCHeaderField.h
@@ -0,0 +1,118 @@
+/*
+ * 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 LLVM_WRAP_BCHEADER_FIELD_H__
+#define LLVM_WRAP_BCHEADER_FIELD_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+// Class representing a variable-size metadata field in the bitcode header.
+// Also contains the list of known Tag IDs.
+// Contains a pointer to the data but does not own the data, so it can be
+// copied with the trivial copy constructor/assignment operator.
+
+// The serialized format has 2 fixed subfields (ID and length) and the
+// variable-length data subfield
+class BCHeaderField {
+ public:
+  typedef enum {
+    kInvalid = 0,
+    kBitcodeHash = 1,
+    kAndroidCompilerVersion = 0x4001,
+    kAndroidOptimizationLevel = 0x4002
+  } Tag;
+  typedef uint16_t FixedSubfield;
+
+  BCHeaderField(Tag ID, size_t len, uint8_t* data) :
+      ID_(ID), len_(len), data_(data) {}
+  size_t GetTotalSize() {
+    // Round up to 4 byte alignment
+    return (kTagLenSize + len_ + 3) & ~3;
+  }
+
+  bool Write(uint8_t* buf, size_t buf_len) {
+    size_t fields_len = kTagLenSize + len_;
+    size_t pad_len = (4 - (fields_len & 3)) & 3;
+    // Ensure buffer is large enough and that length can be represented
+    // in 16 bits
+    const size_t max_uint16_t = 65535;
+    if (buf_len < fields_len + pad_len ||
+        len_ > max_uint16_t) return false;
+
+    WriteFixedSubfield(static_cast<FixedSubfield>(ID_), buf);
+    WriteFixedSubfield(static_cast<FixedSubfield>(len_),
+                       buf + sizeof(FixedSubfield));
+    memcpy(buf + kTagLenSize, data_, len_);
+    // Pad out to 4 byte alignment
+    if (pad_len) {
+      memset(buf + fields_len, 0, pad_len);
+    }
+    return true;
+  }
+
+  bool Read(const uint8_t* buf, size_t buf_len) {
+    if (buf_len < kTagLenSize) return false;
+    FixedSubfield field;
+    ReadFixedSubfield(&field, buf);
+    ID_ = static_cast<Tag>(field);
+    ReadFixedSubfield(&field, buf + sizeof(FixedSubfield));
+    len_ = static_cast<size_t>(field);
+    if (buf_len < kTagLenSize + len_) return false;
+    memcpy(data_, buf + kTagLenSize, len_);
+    return true;
+  }
+
+  void Print() {
+    fprintf(stderr, "Field ID: %d, data length %d, total length %d\n",
+            ID_, static_cast<int>(len_), static_cast<int>(GetTotalSize()));
+    fprintf(stderr, "Data:");
+    for (size_t i = 0; i < len_; i++) fprintf(stderr, "0x%x ", data_[i]);
+    fprintf(stderr, "\n");
+  }
+
+  // Get the data size from a serialized field to allow allocation
+  static size_t GetDataSizeFromSerialized(const uint8_t* buf) {
+    FixedSubfield len;
+    ReadFixedSubfield(&len, buf + sizeof(FixedSubfield));
+    return len;
+  }
+
+  Tag getID() const {
+    return ID_;
+  }
+
+  size_t getLen() const {
+    return len_;
+  }
+
+ private:
+ // Combined size of the fixed subfields
+ const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
+  static void WriteFixedSubfield(FixedSubfield value, uint8_t* buf) {
+    buf[0] = value & 0xFF;
+    buf[1] = (value >> 8) & 0xFF;
+  }
+  static void ReadFixedSubfield(FixedSubfield* value, const uint8_t* buf) {
+    *value = buf[0] | buf[1] << 8;
+  }
+  Tag ID_;
+  size_t len_;
+  uint8_t *data_;
+};
+
+#endif  // LLVM_WRAP_BCHEADER_FIELD_H__
diff --git a/libbcc/include/bcinfo/Wrap/bitcode_wrapperer.h b/libbcc/include/bcinfo/Wrap/bitcode_wrapperer.h
new file mode 100644
index 0000000..42ad5a9
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/bitcode_wrapperer.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define utility class to wrap/unwrap bitcode files. Does wrapping/unwrapping
+// in such a way that the wrappered bitcode file is still a bitcode file.
+
+#ifndef LLVM_WRAP_BITCODE_WRAPPERER_H__
+#define LLVM_WRAP_BITCODE_WRAPPERER_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <vector>
+
+#include "bcinfo/Wrap/support_macros.h"
+#include "bcinfo/Wrap/BCHeaderField.h"
+#include "bcinfo/Wrap/wrapper_input.h"
+#include "bcinfo/Wrap/wrapper_output.h"
+
+// The bitcode wrapper header is the following 7 fixed 4-byte fields:
+//      1) 0B17C0DE - The magic number expected by llvm for wrapped bitcodes
+//      2) Version # 0 - The current version of wrapped bitcode files
+//      3) (raw) bitcode offset
+//      4) (raw) bitcode size
+//      5) Android header version
+//      6) Android target API
+//      7) PNaCl Bitcode version
+//      plus 0 or more variable-length fields (consisting of ID, length, data)
+
+// Initial buffer size. It is expanded if needed to hold large variable-size
+// fields.
+static const size_t kBitcodeWrappererBufferSize = 1024;
+
+// Support class for outputting a wrapped bitcode file from a raw bitcode
+// file (and optionally additional header fields), or for outputting a raw
+// bitcode file from a wrapped one.
+class BitcodeWrapperer {
+ public:
+  // Create a bitcode wrapperer using the following
+  // input and output files.
+  BitcodeWrapperer(WrapperInput* infile, WrapperOutput* outfile);
+
+  // Returns true if the input file begins with a bitcode
+  // wrapper magic number. As a side effect, _wrapper_ fields are set.
+  bool IsInputBitcodeWrapper();
+
+  // Returns true if the input file begins with a bitcode
+  // file magic number.
+  bool IsInputBitcodeFile();
+
+  // Add a variable-length field to the header. The caller is responsible
+  // for freeing the data pointed to by the BCHeaderField.
+  void AddHeaderField(BCHeaderField* field);
+
+  // Generate a wrapped bitcode file from the input bitcode file
+  // and the current header data. Return true on success.
+  bool GenerateWrappedBitcodeFile();
+
+  // Unwrap the wrapped bitcode file, to the corresponding
+  // outfile. Return true on success.
+  bool GenerateRawBitcodeFile();
+
+  // Print current wrapper header fields to stderr for debugging.
+  void PrintWrapperHeader();
+
+  uint32_t getAndroidHeaderVersion() {
+    return android_header_version_;
+  }
+
+  uint32_t getAndroidTargetAPI() {
+    return android_target_api_;
+  }
+
+  uint32_t getAndroidCompilerVersion() {
+    return android_compiler_version_;
+  }
+
+  uint32_t getAndroidOptimizationLevel() {
+    return android_optimization_level_;
+  }
+
+  ~BitcodeWrapperer();
+
+ private:
+  DISALLOW_CLASS_COPY_AND_ASSIGN(BitcodeWrapperer);
+
+  // Refills the buffer with more bytes. Does this in a way
+  // such that it is maximally filled.
+  void FillBuffer();
+
+  // Returns the number of bytes in infile.
+  off_t GetInFileSize() {
+    if (infile_ != nullptr) {
+      return infile_->Size();
+    } else {
+      return 0;
+    }
+  }
+
+  // Returns the offset of bitcode (i.e. the size of the wrapper header)
+  // if the output file were to be written now.
+  size_t BitcodeOffset();
+
+  // Returns true if we can read a word. If necessary, fills the buffer
+  // with enough characters so that there are at least a 32-bit value
+  // in the buffer. Returns false if there isn't a 32-bit value
+  // to read from the input file.
+  bool CanReadWord();
+
+  // Read a (32-bit) word from the input. Return true
+  // if able to read the word.
+  bool ReadWord(uint32_t& word);
+
+  // Write a (32-bit) word to the output. Return true if successful
+  bool WriteWord(uint32_t word);
+
+  // Write all variable-sized header fields to the output. Return true
+  // if successful.
+  bool WriteVariableFields();
+
+  // Parse the bitcode wrapper header in the infile, if any. Return true
+  // if successful.
+  bool ParseWrapperHeader();
+
+  // Returns the i-th character in front of the cursor in the buffer.
+  uint8_t BufferLookahead(int i) { return buffer_[cursor_ + i]; }
+
+  // Returns how many unread bytes are in the buffer.
+  size_t GetBufferUnreadBytes() { return buffer_size_ - cursor_; }
+
+
+  // Backs up the read cursor to the beginning of the input buffer.
+  void ResetCursor() {
+    cursor_ = 0;
+  }
+
+  // Generates the header sequence for the wrapped bitcode being
+  // generated.
+  bool WriteBitcodeWrapperHeader();
+
+  // Copies size bytes of infile to outfile, using the buffer.
+  bool BufferCopyInToOut(uint32_t size);
+
+  // Discards the old infile and replaces it with the given file.
+  void ReplaceInFile(WrapperInput* new_infile);
+
+  // Discards the old outfile and replaces it with the given file.
+  void ReplaceOutFile(WrapperOutput* new_outfile);
+
+  // Moves to the given position in the input file. Returns false
+  // if unsuccessful.
+  bool Seek(uint32_t pos);
+
+  // Clear the buffer of all contents.
+  void ClearBuffer();
+
+  // The input file being processed. Can be either
+  // a bitcode file, a wrappered bitcode file, or a secondary
+  // file to be wrapped.
+  WrapperInput* infile_;
+
+  // The output file being generated. Can be either
+  // a bitcode file, a wrappered bitcode file, or a secondary
+  // unwrapped file.
+  WrapperOutput* outfile_;
+
+  // A buffer of bytes read from the input file.
+  std::vector<uint8_t> buffer_;
+
+  // The number of bytes that were read from the input file
+  // into the buffer.
+  size_t buffer_size_;
+
+  // The index to the current read point within the buffer.
+  size_t cursor_;
+
+  // True when eof of input is reached.
+  bool infile_at_eof_;
+
+  // The 32-bit value defining the offset of the raw bitcode in the input file.
+  uint32_t infile_bc_offset_;
+
+  // The 32-bit value defining the generated offset of the wrapped bitcode.
+  // This value changes as new fields are added with AddHeaderField
+  uint32_t wrapper_bc_offset_;
+
+  // The 32-bit value defining the size of the raw wrapped bitcode.
+  uint32_t wrapper_bc_size_;
+
+  // Android header version and target API
+  uint32_t android_header_version_;
+  uint32_t android_target_api_;
+  uint32_t android_compiler_version_;
+  uint32_t android_optimization_level_;
+
+  // PNaCl bitcode version
+  uint32_t pnacl_bc_version_;
+
+  // Vector of variable header fields
+  std::vector<BCHeaderField> header_fields_;
+  // If any bufferdata from header fields is owned, it is stored here and
+  // freed on destruction.
+  std::vector<uint8_t*> variable_field_data_;
+
+  // True if there was an error condition (e.g. the file is not bitcode)
+  bool error_;
+};
+
+#endif  // LLVM_WRAP_BITCODE_WRAPPERER_H__
diff --git a/libbcc/include/bcinfo/Wrap/file_wrapper_input.h b/libbcc/include/bcinfo/Wrap/file_wrapper_input.h
new file mode 100644
index 0000000..117d335
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/file_wrapper_input.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+// Defines utility allowing files for bitcode input wrapping.
+
+#ifndef FILE_WRAPPER_INPUT_H__
+#define FILE_WRAPPER_INPUT_H__
+
+#include <stdio.h>
+
+#include "bcinfo/Wrap/support_macros.h"
+#include "bcinfo/Wrap/wrapper_input.h"
+
+// Define a class to wrap named files.
+class FileWrapperInput : public WrapperInput {
+ public:
+  explicit FileWrapperInput(const char* _name);
+  ~FileWrapperInput();
+  // Tries to read the requested number of bytes into the buffer. Returns the
+  // actual number of bytes read.
+  virtual size_t Read(uint8_t* buffer, size_t wanted);
+  // Returns true if at end of file. Note: May return false
+  // until Read is called, and returns 0.
+  virtual bool AtEof();
+  // Returns the size of the file (in bytes).
+  virtual off_t Size();
+  // Moves to the given offset within the file. Returns
+  // false if unable to move to that position.
+  virtual bool Seek(uint32_t pos);
+ private:
+  // The name of the file.
+  const char* _name;
+  // True once eof has been encountered.
+  bool _at_eof;
+  // True if size has been computed.
+  bool _size_found;
+  // The size of the file.
+  off_t _size;
+  // The corresponding (opened) file.
+  FILE* _file;
+ private:
+  DISALLOW_CLASS_COPY_AND_ASSIGN(FileWrapperInput);
+};
+
+#endif // FILE_WRAPPER_INPUT_H__
diff --git a/libbcc/include/bcinfo/Wrap/file_wrapper_output.h b/libbcc/include/bcinfo/Wrap/file_wrapper_output.h
new file mode 100644
index 0000000..c61b514
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/file_wrapper_output.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.
+ */
+
+// Defines utility allowing files for bitcode output wrapping.
+
+#ifndef FILE_WRAPPER_OUTPUT_H__
+#define FILE_WRAPPER_OUTPUT_H__
+
+#include <stdio.h>
+
+#include "bcinfo/Wrap/support_macros.h"
+#include "bcinfo/Wrap/wrapper_output.h"
+
+// Define a class to wrap named files. */
+class FileWrapperOutput : public WrapperOutput {
+ public:
+  explicit FileWrapperOutput(const char* name);
+  ~FileWrapperOutput();
+  // Writes a single byte, returning false if unable to write.
+  virtual bool Write(uint8_t byte);
+  // Writes the specified number of bytes in the buffer to
+  // output. Returns false if unable to write.
+  virtual bool Write(const uint8_t* buffer, size_t buffer_size);
+ private:
+  // The name of the file
+  const char* _name;
+  // The corresponding (opened) file.
+  FILE* _file;
+ private:
+  DISALLOW_CLASS_COPY_AND_ASSIGN(FileWrapperOutput);
+};
+#endif  // FILE_WRAPPER_OUTPUT_H__
diff --git a/libbcc/include/bcinfo/Wrap/in_memory_wrapper_input.h b/libbcc/include/bcinfo/Wrap/in_memory_wrapper_input.h
new file mode 100644
index 0000000..634dd40
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/in_memory_wrapper_input.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+// Defines utility allowing in-memory buffers for bitcode input wrapping.
+
+#ifndef IN_MEMORY_WRAPPER_INPUT_H__
+#define IN_MEMORY_WRAPPER_INPUT_H__
+
+#include <stdio.h>
+
+#include "bcinfo/Wrap/support_macros.h"
+#include "bcinfo/Wrap/wrapper_input.h"
+
+// Define a class to wrap named files.
+class InMemoryWrapperInput : public WrapperInput {
+ public:
+  InMemoryWrapperInput(const char* buffer, size_t size);
+  ~InMemoryWrapperInput();
+  // Tries to read the requested number of bytes into the buffer. Returns the
+  // actual number of bytes read.
+  virtual size_t Read(uint8_t* buffer, size_t wanted);
+  // Returns true if at end of buffer. Note: May return false
+  // until Read is called, and returns 0.
+  virtual bool AtEof();
+  // Returns the size of the buffer (in bytes).
+  virtual off_t Size();
+  // Moves to the given offset within the buffer. Returns
+  // false if unable to move to that position.
+  virtual bool Seek(uint32_t pos);
+ private:
+  // The actual in-memory buffer
+  const char* _buffer;
+  // The position in the buffer
+  size_t _pos;
+  // True once eof has been encountered.
+  bool _at_eof;
+  // The size of the buffer.
+  size_t _size;
+ private:
+  DISALLOW_CLASS_COPY_AND_ASSIGN(InMemoryWrapperInput);
+};
+
+#endif // IN_MEMORY_WRAPPER_INPUT_H__
diff --git a/libbcc/include/bcinfo/Wrap/support_macros.h b/libbcc/include/bcinfo/Wrap/support_macros.h
new file mode 100644
index 0000000..5681ed8
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/support_macros.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define support macros for defining classes, etc.
+
+#ifndef LLVM_SUPPORT_SUPPORT_MACROS_H__
+#define LLVM_SUPPORT_SUPPORT_MACROS_H__
+
+// Define macro, to use within a class declaration,  to disallow constructor
+// copy. Defines copy constructor declaration under the assumption that it
+// is never defined.
+// NOLINT: Do not add parentheses around 'class_name'.
+#define DISALLOW_CLASS_COPY(class_name) \
+  class_name(class_name& arg)  // NOLINT, Do not implement
+
+// Define macro, to use within a class declaration,  to disallow assignment.
+// Defines assignment operation declaration under the assumption that it
+// is never defined.
+#define DISALLOW_CLASS_ASSIGN(class_name) \
+  void operator=(class_name& arg)  // NOLINT, Do not implement
+
+// Define macro to add copy and assignment declarations to a class file,
+// for which no bodies will be defined, effectively disallowing these from
+// being defined in the class.
+#define DISALLOW_CLASS_COPY_AND_ASSIGN(class_name) \
+  DISALLOW_CLASS_COPY(class_name); \
+  DISALLOW_CLASS_ASSIGN(class_name)
+
+#endif  // LLVM_SUPPORT_SUPPORT_MACROS_H__
diff --git a/libbcc/include/bcinfo/Wrap/wrapper_input.h b/libbcc/include/bcinfo/Wrap/wrapper_input.h
new file mode 100644
index 0000000..d3330df
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/wrapper_input.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define a generic interface to a file/memory region that contains
+// a bitcode file, a wrapped bitcode file, or a data file to wrap.
+
+#ifndef LLVM_WRAP_WRAPPER_INPUT_H__
+#define LLVM_WRAP_WRAPPER_INPUT_H__
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "support_macros.h"
+
+// The following is a generic interface to a file/memory region that contains
+// a bitcode file, a wrapped bitcode file, or data file to wrap.
+class WrapperInput {
+ public:
+  WrapperInput() {}
+  virtual ~WrapperInput() {}
+  // Tries to read the requested number of bytes into the buffer. Returns the
+  // actual number of bytes read.
+  virtual size_t Read(uint8_t* buffer, size_t wanted) = 0;
+  // Returns true if at end of input. Note: May return false until
+  // Read is called, and returns 0.
+  virtual bool AtEof() = 0;
+  // Returns the size of the input (in bytes).
+  virtual off_t Size() = 0;
+  // Moves to the given offset within the input region. Returns false
+  // if unable to move to that position.
+  virtual bool Seek(uint32_t pos) = 0;
+ private:
+  DISALLOW_CLASS_COPY_AND_ASSIGN(WrapperInput);
+};
+
+#endif  // LLVM_WRAP_WRAPPER_INPUT_H__
diff --git a/libbcc/include/bcinfo/Wrap/wrapper_output.h b/libbcc/include/bcinfo/Wrap/wrapper_output.h
new file mode 100644
index 0000000..6498805
--- /dev/null
+++ b/libbcc/include/bcinfo/Wrap/wrapper_output.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.
+ */
+
+// Defines a generic interface to a file/memory region that
+// contains a generated wrapped bitcode file, bitcode file,
+// or data file.
+
+#ifndef LLVM_WRAP_WRAPPER_OUTPUT_H__
+#define LLVM_WRAP_WRAPPER_OUTPUT_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "bcinfo/Wrap/support_macros.h"
+
+// The following is a generic interface to a file/memory region
+// that contains a generated bitcode file, wrapped bitcode file,
+// or a data file.
+class WrapperOutput {
+ public:
+  WrapperOutput() {}
+  virtual ~WrapperOutput() {}
+  // Writes a single byte, returning false if unable to write.
+  virtual bool Write(uint8_t byte) = 0;
+  // Writes the specified number of bytes in the buffer to
+  // output. Returns false if unable to write.
+  virtual bool Write(const uint8_t* buffer, size_t buffer_size);
+ private:
+  DISALLOW_CLASS_COPY_AND_ASSIGN(WrapperOutput);
+};
+
+#endif  // LLVM_WRAP_WRAPPER_OUTPUT_H__
diff --git a/libbcc/lib/Android.mk b/libbcc/lib/Android.mk
new file mode 100644
index 0000000..9073ac3
--- /dev/null
+++ b/libbcc/lib/Android.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libbcc/lib/Core/Android.mk b/libbcc/lib/Core/Android.mk
new file mode 100644
index 0000000..d48fd0e
--- /dev/null
+++ b/libbcc/lib/Core/Android.mk
@@ -0,0 +1,65 @@
+#
+# 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.
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+
+#=====================================================================
+# Common: libbccCore
+#=====================================================================
+
+libbcc_core_SRC_FILES := \
+  BCCContext.cpp \
+  BCCContextImpl.cpp \
+  Compiler.cpp \
+  Script.cpp \
+  Source.cpp
+
+#=====================================================================
+# Device Static Library: libbccCore
+#=====================================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccCore
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+LOCAL_SRC_FILES := $(libbcc_core_SRC_FILES)
+
+include $(LIBBCC_DEVICE_BUILD_MK)
+include $(LLVM_DEVICE_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_STATIC_LIBRARY)
+endif
+
+#=====================================================================
+# Host Static Library: libbccCore
+#=====================================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccCore
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+LOCAL_SRC_FILES := $(libbcc_core_SRC_FILES)
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libbcc/lib/Core/BCCContext.cpp b/libbcc/lib/Core/BCCContext.cpp
new file mode 100644
index 0000000..c0a307f
--- /dev/null
+++ b/libbcc/lib/Core/BCCContext.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/BCCContext.h"
+
+#include <new>
+
+#include "bcc/Source.h"
+#include "bcc/Support/Log.h"
+
+#include "BCCContextImpl.h"
+
+using namespace bcc;
+
+static BCCContext *GlobalContext = nullptr;
+
+BCCContext *BCCContext::GetOrCreateGlobalContext() {
+  if (GlobalContext == nullptr) {
+    GlobalContext = new (std::nothrow) BCCContext();
+    if (GlobalContext == nullptr) {
+      ALOGE("Out of memory when allocating global BCCContext!");
+    }
+  }
+  return GlobalContext;
+}
+
+void BCCContext::DestroyGlobalContext() {
+  delete GlobalContext;
+  GlobalContext = nullptr;
+}
+
+BCCContext::BCCContext() : mImpl(new BCCContextImpl(*this)) { }
+
+BCCContext::~BCCContext() {
+  delete mImpl;
+  if (this == GlobalContext) {
+    // We're deleting the context returned from GetOrCreateGlobalContext().
+    // Reset the GlobalContext.
+    GlobalContext = nullptr;
+  }
+}
+
+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/libbcc/lib/Core/BCCContextImpl.cpp b/libbcc/lib/Core/BCCContextImpl.cpp
new file mode 100644
index 0000000..1278d97
--- /dev/null
+++ b/libbcc/lib/Core/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 "bcc/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/libbcc/lib/Core/BCCContextImpl.h b/libbcc/lib/Core/BCCContextImpl.h
new file mode 100644
index 0000000..93700f8
--- /dev/null
+++ b/libbcc/lib/Core/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_CORE_CONTEXT_IMPL_H
+#define BCC_CORE_CONTEXT_IMPL_H
+
+#include <llvm/ADT/SmallPtrSet.h>
+#include <llvm/IR/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;
+
+  explicit BCCContextImpl(BCCContext &pContext) { }
+  ~BCCContextImpl();
+};
+
+} // namespace bcc
+
+#endif  // BCC_CORE_CONTEXT_IMPL_H
diff --git a/libbcc/lib/Core/Compiler.cpp b/libbcc/lib/Core/Compiler.cpp
new file mode 100644
index 0000000..759844f
--- /dev/null
+++ b/libbcc/lib/Core/Compiler.cpp
@@ -0,0 +1,475 @@
+/*
+ * 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 "bcc/Compiler.h"
+
+#include <llvm/Analysis/Passes.h>
+#include <llvm/Analysis/TargetTransformInfo.h>
+#include <llvm/CodeGen/RegAllocRegistry.h>
+#include <llvm/IR/LegacyPassManager.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/Target/TargetSubtargetInfo.h>
+#include <llvm/Target/TargetMachine.h>
+#include <llvm/Transforms/IPO.h>
+#include <llvm/Transforms/IPO/PassManagerBuilder.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Transforms/Vectorize.h>
+
+#include "bcc/Assert.h"
+#include "bcc/Config/Config.h"
+#include "bcc/Renderscript/RSScript.h"
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Renderscript/RSUtils.h"
+#include "bcc/Script.h"
+#include "bcc/Source.h"
+#include "bcc/Support/CompilerConfig.h"
+#include "bcc/Support/Log.h"
+#include "bcc/Support/OutputFile.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "rsDefines.h"
+
+#include <string>
+
+using namespace bcc;
+
+const char *Compiler::GetErrorString(enum ErrorCode pErrCode) {
+  switch (pErrCode) {
+  case kSuccess:
+    return "Successfully compiled.";
+  case kInvalidConfigNoTarget:
+    return "Invalid compiler config supplied (getTarget() returns nullptr.) "
+           "(missing call to CompilerConfig::initialize()?)";
+  case kErrCreateTargetMachine:
+    return "Failed to create llvm::TargetMachine.";
+  case kErrSwitchTargetMachine:
+    return  "Failed to switch llvm::TargetMachine.";
+  case kErrNoTargetMachine:
+    return "Failed to compile the script since there's no available "
+           "TargetMachine. (missing call to Compiler::config()?)";
+  case kErrMaterialization:
+    return "Failed to materialize the module.";
+  case kErrInvalidOutputFileState:
+    return "Supplied output file was invalid (in the error state.)";
+  case kErrPrepareOutput:
+    return "Failed to prepare file for output.";
+  case kPrepareCodeGenPass:
+    return "Failed to construct pass list for code-generation.";
+  case kErrCustomPasses:
+    return "Error occurred while adding custom passes.";
+  case kErrInvalidSource:
+    return "Error loading input bitcode";
+  case kIllegalGlobalFunction:
+    return "Use of undefined external function";
+  case kErrInvalidTargetMachine:
+    return "Invalid/unexpected llvm::TargetMachine.";
+  }
+
+  // This assert should never be reached as the compiler verifies that the
+  // above switch coveres all enum values.
+  bccAssert(false && "Unknown error code encountered");
+  return  "";
+}
+
+//===----------------------------------------------------------------------===//
+// Instance Methods
+//===----------------------------------------------------------------------===//
+Compiler::Compiler() : mTarget(nullptr), mEnableOpt(true) {
+  return;
+}
+
+Compiler::Compiler(const CompilerConfig &pConfig) : mTarget(nullptr),
+                                                    mEnableOpt(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;
+}
+
+enum Compiler::ErrorCode Compiler::config(const CompilerConfig &pConfig) {
+  if (pConfig.getTarget() == nullptr) {
+    return kInvalidConfigNoTarget;
+  }
+
+  llvm::TargetMachine *new_target =
+      (pConfig.getTarget())->createTargetMachine(pConfig.getTriple(),
+                                                 pConfig.getCPU(),
+                                                 pConfig.getFeatureString(),
+                                                 pConfig.getTargetOptions(),
+                                                 pConfig.getRelocationModel(),
+                                                 pConfig.getCodeModel(),
+                                                 pConfig.getOptimizationLevel());
+
+  if (new_target == nullptr) {
+    return ((mTarget != nullptr) ? 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
+  if ((pConfig.getOptimizationLevel() == llvm::CodeGenOpt::None)) {
+    llvm::RegisterRegAlloc::setDefault(llvm::createFastRegisterAllocator);
+  } else {
+    llvm::RegisterRegAlloc::setDefault(llvm::createGreedyRegisterAllocator);
+  }
+
+  return kSuccess;
+}
+
+Compiler::~Compiler() {
+  delete mTarget;
+}
+
+
+// This function has complete responsibility for creating and executing the
+// exact list of compiler passes.
+enum Compiler::ErrorCode Compiler::runPasses(Script &pScript,
+                                             llvm::raw_pwrite_stream &pResult) {
+  // Pass manager for link-time optimization
+  llvm::legacy::PassManager transformPasses;
+
+  // Empty MCContext.
+  llvm::MCContext *mc_context = nullptr;
+
+  transformPasses.add(
+      createTargetTransformInfoWrapperPass(mTarget->getTargetIRAnalysis()));
+
+  // Add some initial custom passes.
+  addInvokeHelperPass(transformPasses);
+  addExpandKernelPass(transformPasses);
+  addDebugInfoPass(pScript, transformPasses);
+  addInvariantPass(transformPasses);
+  if (mTarget->getOptLevel() != llvm::CodeGenOpt::None) {
+    if (!addInternalizeSymbolsPass(pScript, transformPasses))
+      return kErrCustomPasses;
+  }
+  addGlobalInfoPass(pScript, transformPasses);
+
+  if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) {
+    transformPasses.add(llvm::createGlobalOptimizerPass());
+    transformPasses.add(llvm::createConstantMergePass());
+
+  } else {
+    // FIXME: Figure out which passes should be executed.
+    llvm::PassManagerBuilder Builder;
+    Builder.Inliner = llvm::createFunctionInliningPass();
+    Builder.populateLTOPassManager(transformPasses);
+
+    /* FIXME: Reenable autovectorization after rebase.
+       bug 19324423
+    // Add vectorization passes after LTO passes are in
+    // additional flag: -unroll-runtime
+    transformPasses.add(llvm::createLoopUnrollPass(-1, 16, 0, 1));
+    // Need to pass appropriate flags here: -scalarize-load-store
+    transformPasses.add(llvm::createScalarizerPass());
+    transformPasses.add(llvm::createCFGSimplificationPass());
+    transformPasses.add(llvm::createScopedNoAliasAAPass());
+    transformPasses.add(llvm::createScalarEvolutionAliasAnalysisPass());
+    // additional flags: -slp-vectorize-hor -slp-vectorize-hor-store (unnecessary?)
+    transformPasses.add(llvm::createSLPVectorizerPass());
+    transformPasses.add(llvm::createDeadCodeEliminationPass());
+    transformPasses.add(llvm::createInstructionCombiningPass());
+    */
+  }
+
+  // These passes have to come after LTO, since we don't want to examine
+  // functions that are never actually called.
+  if (llvm::Triple(getTargetMachine().getTargetTriple()).getArch() == llvm::Triple::x86_64)
+    transformPasses.add(createRSX86_64CallConvPass());  // Add pass to correct calling convention for X86-64.
+  transformPasses.add(createRSIsThreadablePass());      // Add pass to mark script as threadable.
+
+  // RSEmbedInfoPass needs to come after we have scanned for non-threadable
+  // functions.
+  // Script passed to RSCompiler must be a RSScript.
+  RSScript &script = static_cast<RSScript &>(pScript);
+  if (script.getEmbedInfo())
+    transformPasses.add(createRSEmbedInfoPass());
+
+  // Execute the passes.
+  transformPasses.run(pScript.getSource().getModule());
+
+  // Run backend separately to avoid interference between debug metadata
+  // generation and backend initialization.
+  llvm::legacy::PassManager codeGenPasses;
+
+  // Add passes to the pass manager to emit machine code through MC layer.
+  if (mTarget->addPassesToEmitMC(codeGenPasses, mc_context, pResult,
+                                 /* DisableVerify */false)) {
+    return kPrepareCodeGenPass;
+  }
+
+  // Execute the passes.
+  codeGenPasses.run(pScript.getSource().getModule());
+
+  return kSuccess;
+}
+
+enum Compiler::ErrorCode Compiler::compile(Script &pScript,
+                                           llvm::raw_pwrite_stream &pResult,
+                                           llvm::raw_ostream *IRStream) {
+  llvm::Module &module = pScript.getSource().getModule();
+  enum ErrorCode err;
+
+  if (mTarget == nullptr) {
+    return kErrNoTargetMachine;
+  }
+
+  const std::string &triple = module.getTargetTriple();
+  const llvm::DataLayout dl = getTargetMachine().createDataLayout();
+  unsigned int pointerSize = dl.getPointerSizeInBits();
+  if (triple == "armv7-none-linux-gnueabi") {
+    if (pointerSize != 32) {
+      return kErrInvalidSource;
+    }
+  } else if (triple == "aarch64-none-linux-gnueabi") {
+    if (pointerSize != 64) {
+      return kErrInvalidSource;
+    }
+  } else {
+    return kErrInvalidSource;
+  }
+
+  if (getTargetMachine().getTargetTriple().getArch() == llvm::Triple::x86) {
+    // Detect and fail if TargetMachine datalayout is different than what we
+    // expect.  This is to detect changes in default target layout for x86 and
+    // update X86_CUSTOM_DL_STRING in include/bcc/Config/Config.h appropriately.
+    if (dl.getStringRepresentation().compare(X86_DEFAULT_DL_STRING) != 0) {
+      return kErrInvalidTargetMachine;
+    }
+  }
+
+  // Sanitize module's target information.
+  module.setTargetTriple(getTargetMachine().getTargetTriple().str());
+  module.setDataLayout(getTargetMachine().createDataLayout());
+
+  // Materialize the bitcode module.
+  if (module.getMaterializer() != nullptr) {
+    // A module with non-null materializer means that it is a lazy-load module.
+    // Materialize it now.  This function returns false when the materialization
+    // is successful.
+    std::error_code ec = module.materializeAll();
+    if (ec) {
+      ALOGE("Failed to materialize the module `%s'! (%s)",
+            module.getModuleIdentifier().c_str(), ec.message().c_str());
+      return kErrMaterialization;
+    }
+  }
+
+  if ((err = runPasses(pScript, pResult)) != kSuccess) {
+    return err;
+  }
+
+  if (IRStream) {
+    *IRStream << module;
+  }
+
+  return kSuccess;
+}
+
+enum Compiler::ErrorCode Compiler::compile(Script &pScript,
+                                           OutputFile &pResult,
+                                           llvm::raw_ostream *IRStream) {
+  // Check the state of the specified output file.
+  if (pResult.hasError()) {
+    return kErrInvalidOutputFileState;
+  }
+
+  // Open the output file decorated in llvm::raw_ostream.
+  llvm::raw_pwrite_stream *out = pResult.dup();
+  if (out == nullptr) {
+    return kErrPrepareOutput;
+  }
+
+  // Delegate the request.
+  enum Compiler::ErrorCode err = compile(pScript, *out, IRStream);
+
+  // Close the output before return.
+  delete out;
+
+  return err;
+}
+
+bool Compiler::addInternalizeSymbolsPass(Script &pScript, llvm::legacy::PassManager &pPM) {
+  // Add a pass to internalize the symbols that don't need to have global
+  // visibility.
+  RSScript &script = static_cast<RSScript &>(pScript);
+  llvm::Module &module = script.getSource().getModule();
+  bcinfo::MetadataExtractor me(&module);
+  if (!me.extract()) {
+    bccAssert(false && "Could not extract metadata for module!");
+    return false;
+  }
+
+  // The vector contains the symbols that should not be internalized.
+  std::vector<const char *> export_symbols;
+
+  const char *sf[] = {
+    kRoot,               // Graphics drawing function or compute kernel.
+    kInit,               // Initialization routine called implicitly on startup.
+    kRsDtor,             // Static global destructor for a script instance.
+    kRsInfo,             // Variable containing string of RS metadata info.
+    kRsGlobalEntries,    // Optional number of global variables.
+    kRsGlobalNames,      // Optional global variable name info.
+    kRsGlobalAddresses,  // Optional global variable address info.
+    kRsGlobalSizes,      // Optional global variable size info.
+    kRsGlobalProperties, // Optional global variable properties.
+    nullptr              // Must be nullptr-terminated.
+  };
+  const char **special_functions = sf;
+  // Special RS functions should always be global symbols.
+  while (*special_functions != nullptr) {
+    export_symbols.push_back(*special_functions);
+    special_functions++;
+  }
+
+  // Visibility of symbols appeared in rs_export_var and rs_export_func should
+  // also be preserved.
+  size_t exportVarCount = me.getExportVarCount();
+  size_t exportFuncCount = me.getExportFuncCount();
+  size_t exportForEachCount = me.getExportForEachSignatureCount();
+  size_t exportReduceCount = me.getExportReduceCount();
+  const char **exportVarNameList = me.getExportVarNameList();
+  const char **exportFuncNameList = me.getExportFuncNameList();
+  const char **exportForEachNameList = me.getExportForEachNameList();
+  const bcinfo::MetadataExtractor::Reduce *exportReduceList = me.getExportReduceList();
+  size_t i;
+
+  for (i = 0; i < exportVarCount; ++i) {
+    export_symbols.push_back(exportVarNameList[i]);
+  }
+
+  for (i = 0; i < exportFuncCount; ++i) {
+    export_symbols.push_back(exportFuncNameList[i]);
+  }
+
+  // Expanded foreach functions should not be internalized; nor should
+  // general reduction initializer, combiner, and outconverter
+  // functions. keep_funcs keeps the names of these functions around
+  // until createInternalizePass() is finished making its own copy of
+  // the visible symbols.
+  std::vector<std::string> keep_funcs;
+  keep_funcs.reserve(exportForEachCount + exportReduceCount*4);
+
+  for (i = 0; i < exportForEachCount; ++i) {
+    keep_funcs.push_back(std::string(exportForEachNameList[i]) + ".expand");
+  }
+  auto keepFuncsPushBackIfPresent = [&keep_funcs](const char *Name) {
+    if (Name) keep_funcs.push_back(Name);
+  };
+  for (i = 0; i < exportReduceCount; ++i) {
+    keep_funcs.push_back(std::string(exportReduceList[i].mAccumulatorName) + ".expand");
+    keepFuncsPushBackIfPresent(exportReduceList[i].mInitializerName);
+    if (exportReduceList[i].mCombinerName != nullptr) {
+      keep_funcs.push_back(exportReduceList[i].mCombinerName);
+    } else {
+      keep_funcs.push_back(nameReduceCombinerFromAccumulator(exportReduceList[i].mAccumulatorName));
+    }
+    keepFuncsPushBackIfPresent(exportReduceList[i].mOutConverterName);
+  }
+
+  for (auto &symbol_name : keep_funcs) {
+    export_symbols.push_back(symbol_name.c_str());
+  }
+
+  // http://b/26165616 - WAR for this bug defines the __truncxfhf2 function in
+  // frameworks/rs/driver/runtime.  Don't internalize this function for x86, so
+  // that a script can find and link against it.
+  llvm::Triple triple(getTargetMachine().getTargetTriple());
+  if (triple.getArch() == llvm::Triple::x86) {
+    export_symbols.push_back("__truncxfhf2");
+  }
+
+  pPM.add(llvm::createInternalizePass(export_symbols));
+
+  return true;
+}
+
+void Compiler::addInvokeHelperPass(llvm::legacy::PassManager &pPM) {
+  llvm::Triple arch(getTargetMachine().getTargetTriple());
+  if (arch.isArch64Bit()) {
+    pPM.add(createRSInvokeHelperPass());
+  }
+}
+
+void Compiler::addDebugInfoPass(Script &pScript, llvm::legacy::PassManager &pPM) {
+  if (pScript.getSource().getDebugInfoEnabled())
+    pPM.add(createRSAddDebugInfoPass());
+}
+
+void Compiler::addExpandKernelPass(llvm::legacy::PassManager &pPM) {
+  // Expand ForEach and reduce on CPU path to reduce launch overhead.
+  bool pEnableStepOpt = true;
+  pPM.add(createRSKernelExpandPass(pEnableStepOpt));
+}
+
+void Compiler::addGlobalInfoPass(Script &pScript, llvm::legacy::PassManager &pPM) {
+  // Add additional information about RS global variables inside the Module.
+  RSScript &script = static_cast<RSScript &>(pScript);
+  if (script.getEmbedGlobalInfo()) {
+    pPM.add(createRSGlobalInfoPass(script.getEmbedGlobalInfoSkipConstant()));
+  }
+}
+
+void Compiler::addInvariantPass(llvm::legacy::PassManager &pPM) {
+  // Mark Loads from RsExpandKernelDriverInfo as "load.invariant".
+  // Should run after ExpandForEach and before inlining.
+  pPM.add(createRSInvariantPass());
+}
+
+enum Compiler::ErrorCode Compiler::screenGlobalFunctions(Script &pScript) {
+  llvm::Module &module = pScript.getSource().getModule();
+
+  // Materialize the bitcode module in case this is a lazy-load module.  Do not
+  // clear the materializer by calling materializeAllPermanently since the
+  // runtime library has not been merged into the module yet.
+  if (module.getMaterializer() != nullptr) {
+    std::error_code ec = module.materializeAll();
+    if (ec) {
+      ALOGE("Failed to materialize module `%s' when screening globals! (%s)",
+            module.getModuleIdentifier().c_str(), ec.message().c_str());
+      return kErrMaterialization;
+    }
+  }
+
+  // Add pass to check for illegal function calls.
+  llvm::legacy::PassManager pPM;
+  pPM.add(createRSScreenFunctionsPass());
+  pPM.run(module);
+
+  return kSuccess;
+
+}
+
+void Compiler::translateGEPs(Script &pScript) {
+  llvm::legacy::PassManager pPM;
+  pPM.add(createRSX86TranslateGEPPass());
+
+  // Materialization done in screenGlobalFunctions above.
+  pPM.run(pScript.getSource().getModule());
+}
diff --git a/libbcc/lib/Core/Script.cpp b/libbcc/lib/Core/Script.cpp
new file mode 100644
index 0000000..22d173b
--- /dev/null
+++ b/libbcc/lib/Core/Script.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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 "bcc/Script.h"
+
+#include "bcc/Source.h"
+
+using namespace bcc;
+
+bool Script::reset(Source &pSource, bool pPreserveCurrent) {
+  if (mSource == &pSource) {
+    return false;
+  }
+
+  if (!pPreserveCurrent) {
+    delete mSource;
+  }
+  mSource = &pSource;
+  return doReset();
+}
+
+bool Script::mergeSource(Source &pSource) {
+  return mSource->merge(pSource);
+}
diff --git a/libbcc/lib/Core/Source.cpp b/libbcc/lib/Core/Source.cpp
new file mode 100644
index 0000000..d4c0e74
--- /dev/null
+++ b/libbcc/lib/Core/Source.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Source.h"
+
+#include <new>
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Verifier.h>
+#include <llvm/Linker/Linker.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include "llvm/Support/raw_ostream.h"
+
+#include "bcc/BCCContext.h"
+#include "bcc/Support/Log.h"
+
+#include "bcinfo/MetadataExtractor.h"
+
+#include "BCCContextImpl.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 nullptr and will NOT take the ownership of pInput.
+static inline std::unique_ptr<llvm::Module> helper_load_bitcode(llvm::LLVMContext &pContext,
+                                                std::unique_ptr<llvm::MemoryBuffer> &&pInput) {
+  llvm::ErrorOr<std::unique_ptr<llvm::Module> > moduleOrError
+      = llvm::getLazyBitcodeModule(std::move(pInput), pContext);
+  if (std::error_code ec = moduleOrError.getError()) {
+    ALOGE("Unable to parse the given bitcode file `%s'! (%s)",
+          pInput->getBufferIdentifier(), ec.message().c_str());
+  }
+
+  return std::move(moduleOrError.get());
+}
+
+} // end anonymous namespace
+
+namespace bcc {
+
+void Source::setModule(llvm::Module *pModule) {
+  if (!mNoDelete && (mModule != pModule)) delete mModule;
+  mModule = pModule;
+}
+
+Source *Source::CreateFromBuffer(BCCContext &pContext,
+                                 const char *pName,
+                                 const char *pBitcode,
+                                 size_t pBitcodeSize) {
+  llvm::StringRef input_data(pBitcode, pBitcodeSize);
+  std::unique_ptr<llvm::MemoryBuffer> input_memory =
+      llvm::MemoryBuffer::getMemBuffer(input_data, "", false);
+
+  if (input_memory == nullptr) {
+    ALOGE("Unable to load bitcode `%s' from buffer!", pName);
+    return nullptr;
+  }
+
+  auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext,
+                                           std::move(input_memory));
+
+  // Release the managed llvm::Module* since this object gets deleted either in
+  // the error check below or in ~Source() (since pNoDelete is false).
+  llvm::Module *module = managedModule.release();
+  if (module == nullptr) {
+    return nullptr;
+  }
+
+  Source *result = CreateFromModule(pContext, pName, *module, /* pNoDelete */false);
+  if (result == nullptr) {
+    delete module;
+  }
+
+  return result;
+}
+
+Source *Source::CreateFromFile(BCCContext &pContext, const std::string &pPath) {
+
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error =
+      llvm::MemoryBuffer::getFile(pPath);
+  if (mb_or_error.getError()) {
+    ALOGE("Failed to load bitcode from path %s! (%s)", pPath.c_str(),
+          mb_or_error.getError().message().c_str());
+    return nullptr;
+  }
+  std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get());
+
+  std::unique_ptr<llvm::MemoryBuffer> input_memory(input_data.release());
+  auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext,
+                                           std::move(input_memory));
+
+  // Release the managed llvm::Module* since this object gets deleted either in
+  // the error check below or in ~Source() (since pNoDelete is false).
+  llvm::Module *module = managedModule.release();
+  if (module == nullptr) {
+    return nullptr;
+  }
+
+  Source *result = CreateFromModule(pContext, pPath.c_str(), *module, /* pNoDelete */false);
+  if (result == nullptr) {
+    delete module;
+  }
+
+  return result;
+}
+
+Source *Source::CreateFromModule(BCCContext &pContext, const char* name, llvm::Module &pModule,
+                                 bool pNoDelete) {
+  std::string ErrorInfo;
+  llvm::raw_string_ostream ErrorStream(ErrorInfo);
+  pModule.materializeAll();
+  if (llvm::verifyModule(pModule, &ErrorStream)) {
+    ALOGE("Bitcode of RenderScript module does not pass verification: `%s'!",
+          ErrorStream.str().c_str());
+    return nullptr;
+  }
+
+  Source *result = new (std::nothrow) Source(name, pContext, pModule, pNoDelete);
+  if (result == nullptr) {
+    ALOGE("Out of memory during Source object allocation for `%s'!",
+          pModule.getModuleIdentifier().c_str());
+  }
+  return result;
+}
+
+Source::Source(const char* name, BCCContext &pContext, llvm::Module &pModule,
+               bool pNoDelete)
+    : mName(name), mContext(pContext), mModule(&pModule), mMetadata(nullptr),
+      mNoDelete(pNoDelete), mIsModuleDestroyed(false) {
+    pContext.addSource(*this);
+}
+
+Source::~Source() {
+  mContext.removeSource(*this);
+  if (!mNoDelete && !mIsModuleDestroyed)
+    delete mModule;
+  delete mMetadata;
+}
+
+bool Source::merge(Source &pSource) {
+  // TODO(srhines): Add back logging of actual diagnostics from linking.
+  if (llvm::Linker::linkModules(*mModule, std::unique_ptr<llvm::Module>(&pSource.getModule())) != 0) {
+    ALOGE("Failed to link source `%s' with `%s'!",
+          getIdentifier().c_str(), pSource.getIdentifier().c_str());
+    return false;
+  }
+  // pSource.getModule() is destroyed after linking.
+  pSource.markModuleDestroyed();
+
+  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 == nullptr) {
+    ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str());
+    return nullptr;
+  }
+
+  Source *result = CreateFromModule(pContext, pName.c_str(), *module, /* pNoDelete */false);
+  if (result == nullptr) {
+    delete module;
+  }
+
+  return result;
+}
+
+const std::string &Source::getIdentifier() const {
+  return mModule->getModuleIdentifier();
+}
+
+void Source::addBuildChecksumMetadata(const char *buildChecksum) const {
+    llvm::LLVMContext &context = mContext.mImpl->mLLVMContext;
+    llvm::MDString *val = llvm::MDString::get(context, buildChecksum);
+    llvm::NamedMDNode *node =
+        mModule->getOrInsertNamedMetadata("#rs_build_checksum");
+    node->addOperand(llvm::MDNode::get(context, val));
+}
+
+bool Source::getDebugInfoEnabled() const {
+  return mModule->getNamedMetadata("llvm.dbg.cu") != nullptr;
+}
+
+bool Source::extractMetadata() {
+  mMetadata = new bcinfo::MetadataExtractor(mModule);
+  return mMetadata->extract();
+}
+
+} // namespace bcc
diff --git a/libbcc/lib/Renderscript/Android.mk b/libbcc/lib/Renderscript/Android.mk
new file mode 100644
index 0000000..e392994
--- /dev/null
+++ b/libbcc/lib/Renderscript/Android.mk
@@ -0,0 +1,75 @@
+#
+# 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.
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+
+#=====================================================================
+# Common: libbccRenderscript
+#=====================================================================
+
+libbcc_renderscript_SRC_FILES := \
+  RSAddDebugInfoPass.cpp \
+  RSCompilerDriver.cpp \
+  RSEmbedInfo.cpp \
+  RSKernelExpand.cpp \
+  RSGlobalInfoPass.cpp \
+  RSInvariant.cpp \
+  RSScript.cpp \
+  RSInvokeHelperPass.cpp \
+  RSIsThreadablePass.cpp \
+  RSScreenFunctionsPass.cpp \
+  RSStubsWhiteList.cpp \
+  RSScriptGroupFusion.cpp \
+  RSX86CallConvPass.cpp \
+  RSX86TranslateGEPPass.cpp
+
+#=====================================================================
+# Device Static Library: libbccRenderscript
+#=====================================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccRenderscript
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+LOCAL_SRC_FILES := $(libbcc_renderscript_SRC_FILES)
+
+include $(LIBBCC_DEVICE_BUILD_MK)
+include $(LLVM_DEVICE_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_STATIC_LIBRARY)
+endif
+
+#=====================================================================
+# Host Static Library: libbccRenderscript
+#=====================================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccRenderscript
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_IS_HOST_MODULE := true
+
+LOCAL_SRC_FILES := $(libbcc_renderscript_SRC_FILES)
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libbcc/lib/Renderscript/RSAddDebugInfoPass.cpp b/libbcc/lib/Renderscript/RSAddDebugInfoPass.cpp
new file mode 100644
index 0000000..e89af4e
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSAddDebugInfoPass.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Support/Log.h"
+#include "bcinfo/MetadataExtractor.h"
+
+#include <llvm/Pass.h>
+#include <llvm/IR/DIBuilder.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/InstIterator.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Module.h>
+
+namespace {
+
+const char DEBUG_SOURCE_PATH[] = "/opt/renderscriptdebugger/1";
+const char DEBUG_GENERATED_FILE[] = "generated.rs";
+const char DEBUG_PROTOTYPE_VAR_NAME[] = "rsDebugOuterForeachT";
+const char DEBUG_COMPILE_UNIT_MDNAME[] = "llvm.dbg.cu";
+
+/*
+ * LLVM pass to attach debug information to the bits of code
+ * generated by the compiler.
+ */
+class RSAddDebugInfoPass : public llvm::ModulePass {
+
+public:
+  // Pass ID
+  static char ID;
+
+  RSAddDebugInfoPass() : ModulePass(ID), kernelTypeMD(nullptr),
+      sourceFileName(nullptr), emptyExpr(nullptr), abiMetaCU(nullptr),
+      indexVarType(nullptr) {
+  }
+
+  virtual bool runOnModule(llvm::Module &Module) {
+    // Gather information about this bcc module.
+    bcinfo::MetadataExtractor me(&Module);
+    if (!me.extract()) {
+      ALOGE("Could not extract metadata from module!");
+      return false;
+    }
+
+    size_t nForEachKernels = me.getExportForEachSignatureCount();
+    const char **forEachKernels = me.getExportForEachNameList();
+
+    // Set up the debug info builder.
+    llvm::DIBuilder DebugInfo(Module);
+
+    initializeDebugInfo(DebugInfo, Module);
+
+    // Attach DI metadata to each generated function.
+    for (size_t i = 0; i < nForEachKernels; ++i) {
+      std::string expandedName = forEachKernels[i];
+      expandedName += ".expand";
+
+      if (llvm::Function *kernelFunc = Module.getFunction(expandedName))
+        attachDebugInfo(DebugInfo, *kernelFunc);
+    }
+
+    DebugInfo.finalize();
+
+    cleanupDebugInfo(Module);
+
+    return true;
+  }
+
+private:
+
+  // @brief Initialize the debug info generation.
+  //
+  // This method does a couple of things:
+  // * Look up debug metadata for kernel ABI and store it if present.
+  // * Store a couple of useful pieces of debug metadata in member
+  //   variables so they do not have to be created multiple times.
+  void initializeDebugInfo(llvm::DIBuilder &DebugInfo,
+                           const llvm::Module &Module) {
+    llvm::LLVMContext &ctx = Module.getContext();
+
+    // Start generating debug information for bcc-generated code.
+    DebugInfo.createCompileUnit(llvm::dwarf::DW_LANG_GOOGLE_RenderScript,
+                                DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH,
+                                "RS", false, "", 0);
+
+    // Pre-generate and save useful pieces of debug metadata.
+    sourceFileName = DebugInfo.createFile(DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH);
+    emptyExpr = DebugInfo.createExpression();
+
+    // Lookup compile unit with kernel ABI debug metadata.
+    llvm::NamedMDNode *mdCompileUnitList =
+        Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
+    bccAssert(mdCompileUnitList != nullptr &&
+        "DebugInfo pass could not find any existing compile units.");
+
+    llvm::DIGlobalVariable *kernelPrototypeVarMD = nullptr;
+    for (llvm::MDNode* CUNode : mdCompileUnitList->operands()) {
+      if (auto *CU = llvm::dyn_cast<llvm::DICompileUnit>(CUNode)) {
+        for (llvm::DIGlobalVariable* GV : CU->getGlobalVariables()) {
+          if (GV->getDisplayName() == DEBUG_PROTOTYPE_VAR_NAME) {
+            kernelPrototypeVarMD = GV;
+            abiMetaCU = CU;
+            break;
+          }
+        }
+        if (kernelPrototypeVarMD != nullptr)
+          break;
+      }
+    }
+
+    // Lookup the expanded function interface type metadata.
+    llvm::MDTuple *kernelPrototypeMD = nullptr;
+    if (kernelPrototypeVarMD != nullptr) {
+      // Dig into the metadata to look for function prototype.
+      llvm::DIDerivedType *DT = nullptr;
+      DT = llvm::cast<llvm::DIDerivedType>(kernelPrototypeVarMD->getType());
+      DT = llvm::cast<llvm::DIDerivedType>(DT->getBaseType());
+      llvm::DISubroutineType *ST = llvm::cast<llvm::DISubroutineType>(DT->getBaseType());
+      kernelPrototypeMD = llvm::cast<llvm::MDTuple>(ST->getRawTypeArray());
+
+      indexVarType = llvm::dyn_cast_or_null<llvm::DIType>(
+          kernelPrototypeMD->getOperand(2));
+    }
+    // Fall back to the function type of void() if there is no proper debug info.
+    if (kernelPrototypeMD == nullptr)
+      kernelPrototypeMD = llvm::MDTuple::get(ctx, {nullptr});
+    // Fall back to unspecified type if we don't have a proper index type.
+    if (indexVarType == nullptr)
+      indexVarType = DebugInfo.createBasicType("uint32_t", 32, 32,
+          llvm::dwarf::DW_ATE_unsigned);
+
+    // Capture the expanded kernel type debug info.
+    kernelTypeMD = DebugInfo.createSubroutineType(kernelPrototypeMD);
+  }
+
+  /// @brief Add debug information to a generated function.
+  ///
+  /// This procedure adds the following pieces of debug information
+  /// to the function specified by Func:
+  /// * Entry for the function to the current compile unit.
+  /// * Adds debug info entries for each function argument.
+  /// * Adds debug info entry for the rsIndex local variable.
+  /// * File/line information to each instruction set to generates.rs:1.
+  void attachDebugInfo(llvm::DIBuilder &DebugInfo, llvm::Function &Func) {
+    // Lookup the current thread coordinate variable.
+    llvm::AllocaInst* indexVar = nullptr;
+    for (llvm::Instruction &inst : llvm::instructions(Func)) {
+      if (auto *allocaInst = llvm::dyn_cast<llvm::AllocaInst>(&inst)) {
+        if (allocaInst->getName() == bcc::BCC_INDEX_VAR_NAME) {
+          indexVar = allocaInst;
+          break;
+        }
+      }
+    }
+
+    // Create function-level debug metadata.
+    llvm::DISubprogram *ExpandedFunc = DebugInfo.createFunction(
+        sourceFileName, // scope
+        Func.getName(), Func.getName(),
+        sourceFileName, 1, kernelTypeMD,
+        false, true, 1, 0, false
+    );
+    Func.setSubprogram(ExpandedFunc);
+
+    // IRBuilder for allocating variables for arguments.
+    llvm::IRBuilder<> ir(&*Func.getEntryBlock().begin());
+
+    // Walk through the argument list and expanded function prototype
+    // debuginfo in lockstep to create debug entries for
+    // the expanded function arguments.
+    unsigned argIdx = 1;
+    llvm::MDTuple *argTypes = kernelTypeMD->getTypeArray().get();
+    for (llvm::Argument &arg : Func.getArgumentList()) {
+      // Stop processing arguments if we run out of debug info.
+      if (argIdx >= argTypes->getNumOperands())
+        break;
+
+      // Create debuginfo entry for the argument and advance.
+      llvm::DILocalVariable *argVarDI = DebugInfo.createParameterVariable(
+          ExpandedFunc, arg.getName(), argIdx, sourceFileName, 1,
+          llvm::cast<llvm::DIType>(argTypes->getOperand(argIdx).get()),
+          true, 0
+      );
+
+      // Annotate the argument variable in the IR.
+      llvm::AllocaInst *argVar =
+          ir.CreateAlloca(arg.getType(), nullptr, arg.getName() + ".var");
+      llvm::StoreInst *argStore = ir.CreateStore(&arg, argVar);
+      llvm::LoadInst *loadedVar = ir.CreateLoad(argVar, arg.getName() + ".l");
+      DebugInfo.insertDeclare(argVar, argVarDI, emptyExpr,
+          llvm::DebugLoc::get(1, 1, ExpandedFunc), loadedVar);
+      for (llvm::Use &u : arg.uses())
+        if (u.getUser() != argStore)
+          u.set(loadedVar);
+      argIdx++;
+    }
+
+    // Annotate the index variable with metadata.
+    if (indexVar) {
+      // Debug information for loop index variable.
+      llvm::DILocalVariable *indexVarDI = DebugInfo.createAutoVariable(
+          ExpandedFunc, bcc::BCC_INDEX_VAR_NAME, sourceFileName, 1,
+          indexVarType, true
+      );
+
+      // Insert declaration annotation in the instruction stream.
+      llvm::Instruction *decl = DebugInfo.insertDeclare(
+          indexVar, indexVarDI, emptyExpr,
+          llvm::DebugLoc::get(1, 1, ExpandedFunc), indexVar);
+      indexVar->moveBefore(decl);
+    }
+
+    // Attach location information to each instruction in the function.
+    for (llvm::Instruction &inst : llvm::instructions(Func)) {
+      inst.setDebugLoc(llvm::DebugLoc::get(1, 1, ExpandedFunc));
+    }
+  }
+
+  // @brief Clean up the debug info.
+  //
+  // At the moment, it only finds the compile unit for the expanded function
+  // metadata generated by clang and removes it.
+  void cleanupDebugInfo(llvm::Module& Module) {
+    if (abiMetaCU == nullptr)
+      return;
+
+    // Remove the compile unit with the runtime interface DI.
+    llvm::SmallVector<llvm::MDNode*, 4> unitsTmp;
+    llvm::NamedMDNode *debugMD =
+        Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
+    for (llvm::MDNode *cu : debugMD->operands())
+      if (cu != abiMetaCU)
+        unitsTmp.push_back(cu);
+    debugMD->eraseFromParent();
+    debugMD = Module.getOrInsertNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
+    for (llvm::MDNode *cu : unitsTmp)
+      debugMD->addOperand(cu);
+  }
+
+private:
+  // private attributes
+  llvm::DISubroutineType* kernelTypeMD;
+  llvm::DIFile *sourceFileName;
+  llvm::DIExpression *emptyExpr;
+  llvm::DICompileUnit *abiMetaCU;
+  llvm::DIType *indexVarType;
+
+}; // end class RSAddDebugInfoPass
+
+char RSAddDebugInfoPass::ID = 0;
+static llvm::RegisterPass<RSAddDebugInfoPass> X("addrsdi", "Add RS DebugInfo Pass");
+
+} // end anonymous namespace
+
+namespace bcc {
+
+llvm::ModulePass * createRSAddDebugInfoPass() {
+  return new RSAddDebugInfoPass();
+}
+
+} // end namespace bcc
diff --git a/libbcc/lib/Renderscript/RSCompilerDriver.cpp b/libbcc/lib/Renderscript/RSCompilerDriver.cpp
new file mode 100644
index 0000000..1dfc699
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSCompilerDriver.cpp
@@ -0,0 +1,433 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Renderscript/RSCompilerDriver.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/AssemblyAnnotationWriter.h"
+#include <llvm/IR/Module.h>
+#include "llvm/Linker/Linker.h"
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/Path.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Target/TargetMachine.h>
+
+#include "bcinfo/BitcodeWrapper.h"
+#include "bcc/Assert.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "bcc/BCCContext.h"
+#include "bcc/Compiler.h"
+#include "bcc/Config/Config.h"
+#include "bcc/Renderscript/RSScript.h"
+#include "bcc/Renderscript/RSScriptGroupFusion.h"
+#include "bcc/Support/CompilerConfig.h"
+#include "bcc/Source.h"
+#include "bcc/Support/FileMutex.h"
+#include "bcc/Support/Log.h"
+#include "bcc/Support/InputFile.h"
+#include "bcc/Support/Initialization.h"
+#include "bcc/Support/OutputFile.h"
+
+#include <sstream>
+#include <string>
+
+#ifdef __ANDROID__
+#include <cutils/properties.h>
+#endif
+#include <utils/StopWatch.h>
+
+using namespace bcc;
+
+RSCompilerDriver::RSCompilerDriver() :
+    mConfig(nullptr), mCompiler(), mDebugContext(false),
+    mLinkRuntimeCallback(nullptr), mEnableGlobalMerge(true),
+    mEmbedGlobalInfo(false), mEmbedGlobalInfoSkipConstant(false) {
+  init::Initialize();
+}
+
+RSCompilerDriver::~RSCompilerDriver() {
+  delete mConfig;
+}
+
+
+#if defined(PROVIDE_ARM_CODEGEN)
+extern llvm::cl::opt<bool> EnableGlobalMerge;
+#endif
+
+bool RSCompilerDriver::setupConfig(const RSScript &pScript) {
+  bool changed = false;
+
+  const llvm::CodeGenOpt::Level script_opt_level =
+      static_cast<llvm::CodeGenOpt::Level>(pScript.getOptimizationLevel());
+
+#if defined(PROVIDE_ARM_CODEGEN)
+  EnableGlobalMerge = mEnableGlobalMerge;
+#endif
+
+  if (mConfig != nullptr) {
+    // Renderscript bitcode may have their optimization flag configuration
+    // different than the previous run of RS compilation.
+    if (mConfig->getOptimizationLevel() != script_opt_level) {
+      mConfig->setOptimizationLevel(script_opt_level);
+      changed = true;
+    }
+  } else {
+    // Haven't run the compiler ever.
+    mConfig = new (std::nothrow) CompilerConfig(DEFAULT_TARGET_TRIPLE_STRING);
+    if (mConfig == nullptr) {
+      // Return false since mConfig remains NULL and out-of-memory.
+      return false;
+    }
+    mConfig->setOptimizationLevel(script_opt_level);
+    changed = true;
+  }
+
+#if defined(PROVIDE_ARM_CODEGEN)
+  bcinfo::MetadataExtractor me(&pScript.getSource().getModule());
+  if (!me.extract()) {
+    bccAssert("Could not extract RS pragma metadata for module!");
+  }
+
+  bool script_full_prec = (me.getRSFloatPrecision() == bcinfo::RS_FP_Full);
+  if (mConfig->getFullPrecision() != script_full_prec) {
+    mConfig->setFullPrecision(script_full_prec);
+    changed = true;
+  }
+#endif
+
+  return changed;
+}
+
+Compiler::ErrorCode RSCompilerDriver::compileScript(RSScript& pScript, const char* pScriptName,
+                                                    const char* pOutputPath,
+                                                    const char* pRuntimePath,
+                                                    const char* pBuildChecksum,
+                                                    bool pDumpIR) {
+  // embed build checksum metadata into the source
+  if (pBuildChecksum != nullptr && strlen(pBuildChecksum) > 0) {
+    pScript.getSource().addBuildChecksumMetadata(pBuildChecksum);
+  }
+
+  // Verify that the only external functions in pScript are Renderscript
+  // functions.  Fail if verification returns an error.
+  if (mCompiler.screenGlobalFunctions(pScript) != Compiler::kSuccess) {
+    return Compiler::kErrInvalidSource;
+  }
+
+  // For (32-bit) x86, translate GEPs on structs or arrays of structs to GEPs on
+  // int8* with byte offsets.  This is to ensure that layout of structs with
+  // 64-bit scalar fields matches frontend-generated code that adheres to ARM
+  // data layout.
+  //
+  // The translation is done before RenderScript runtime library is linked
+  // (during LinkRuntime below) to ensure that RenderScript-driver-provided
+  // structs (like Allocation_t) don't get forced into using the ARM layout
+  // rules.
+  if (mCompiler.getTargetMachine().getTargetTriple().getArch() == llvm::Triple::x86) {
+    mCompiler.translateGEPs(pScript);
+  }
+
+  //===--------------------------------------------------------------------===//
+  // Link RS script with Renderscript runtime.
+  //===--------------------------------------------------------------------===//
+  if (!RSScript::LinkRuntime(pScript, pRuntimePath)) {
+    ALOGE("Failed to link script '%s' with Renderscript runtime %s!",
+          pScriptName, pRuntimePath);
+    return Compiler::kErrInvalidSource;
+  }
+
+  {
+    // FIXME(srhines): Windows compilation can't use locking like this, but
+    // we also don't need to worry about concurrent writers of the same file.
+#ifndef USE_MINGW
+    //===------------------------------------------------------------------===//
+    // Acquire the write lock for writing output object file.
+    //===------------------------------------------------------------------===//
+    FileMutex<FileBase::kWriteLock> write_output_mutex(pOutputPath);
+
+    if (write_output_mutex.hasError() || !write_output_mutex.lock()) {
+      ALOGE("Unable to acquire the lock for writing %s! (%s)",
+            pOutputPath, write_output_mutex.getErrorMessage().c_str());
+      return Compiler::kErrInvalidSource;
+    }
+#endif
+
+    // Open the output file for write.
+    OutputFile output_file(pOutputPath,
+                           FileBase::kTruncate | FileBase::kBinary);
+
+    if (output_file.hasError()) {
+        ALOGE("Unable to open %s for write! (%s)", pOutputPath,
+              output_file.getErrorMessage().c_str());
+      return Compiler::kErrInvalidSource;
+    }
+
+    // Setup the config to the compiler.
+    bool compiler_need_reconfigure = setupConfig(pScript);
+
+    if (mConfig == nullptr) {
+      ALOGE("Failed to setup config for RS compiler to compile %s!",
+            pOutputPath);
+      return Compiler::kErrInvalidSource;
+    }
+
+    if (compiler_need_reconfigure) {
+      Compiler::ErrorCode err = mCompiler.config(*mConfig);
+      if (err != Compiler::kSuccess) {
+        ALOGE("Failed to config the RS compiler for %s! (%s)",pOutputPath,
+              Compiler::GetErrorString(err));
+        return Compiler::kErrInvalidSource;
+      }
+    }
+
+    OutputFile *ir_file = nullptr;
+    llvm::raw_fd_ostream *IRStream = nullptr;
+    if (pDumpIR) {
+      std::string path(pOutputPath);
+      path.append(".ll");
+      ir_file = new OutputFile(path.c_str(), FileBase::kTruncate);
+      IRStream = ir_file->dup();
+    }
+
+    // Run the compiler.
+    Compiler::ErrorCode compile_result =
+        mCompiler.compile(pScript, output_file, IRStream);
+
+    if (ir_file) {
+      ir_file->close();
+      delete ir_file;
+    }
+
+    if (compile_result != Compiler::kSuccess) {
+      ALOGE("Unable to compile the source to file %s! (%s)", pOutputPath,
+            Compiler::GetErrorString(compile_result));
+      return Compiler::kErrInvalidSource;
+    }
+  }
+
+  return Compiler::kSuccess;
+}
+
+bool RSCompilerDriver::build(BCCContext &pContext,
+                             const char *pCacheDir,
+                             const char *pResName,
+                             const char *pBitcode,
+                             size_t pBitcodeSize,
+                             const char *pBuildChecksum,
+                             const char *pRuntimePath,
+                             RSLinkRuntimeCallback pLinkRuntimeCallback,
+                             bool pDumpIR) {
+    //  android::StopWatch build_time("bcc: RSCompilerDriver::build time");
+  //===--------------------------------------------------------------------===//
+  // Check parameters.
+  //===--------------------------------------------------------------------===//
+  if ((pCacheDir == nullptr) || (pResName == nullptr)) {
+    ALOGE("Invalid parameter passed to RSCompilerDriver::build()! (cache dir: "
+          "%s, resource name: %s)", ((pCacheDir) ? pCacheDir : "(null)"),
+                                    ((pResName) ? pResName : "(null)"));
+    return false;
+  }
+
+  if ((pBitcode == nullptr) || (pBitcodeSize <= 0)) {
+    ALOGE("No bitcode supplied! (bitcode: %p, size of bitcode: %u)",
+          pBitcode, static_cast<unsigned>(pBitcodeSize));
+    return false;
+  }
+
+  //===--------------------------------------------------------------------===//
+  // Construct output path.
+  // {pCacheDir}/{pResName}.o
+  //===--------------------------------------------------------------------===//
+  llvm::SmallString<80> output_path(pCacheDir);
+  llvm::sys::path::append(output_path, pResName);
+  llvm::sys::path::replace_extension(output_path, ".o");
+
+  //===--------------------------------------------------------------------===//
+  // Load the bitcode and create script.
+  //===--------------------------------------------------------------------===//
+  Source *source = Source::CreateFromBuffer(pContext, pResName,
+                                            pBitcode, pBitcodeSize);
+  if (source == nullptr) {
+    return false;
+  }
+
+  RSScript script(*source, getConfig());
+  if (pLinkRuntimeCallback) {
+    setLinkRuntimeCallback(pLinkRuntimeCallback);
+  }
+
+  script.setLinkRuntimeCallback(getLinkRuntimeCallback());
+
+  script.setEmbedGlobalInfo(mEmbedGlobalInfo);
+  script.setEmbedGlobalInfoSkipConstant(mEmbedGlobalInfoSkipConstant);
+
+  // Read information from bitcode wrapper.
+  bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
+  script.setCompilerVersion(wrapper.getCompilerVersion());
+  script.setOptimizationLevel(static_cast<RSScript::OptimizationLevel>(
+                              wrapper.getOptimizationLevel()));
+
+// Assertion-enabled builds can't compile legacy bitcode (due to the use of
+// getName() with anonymous structure definitions).
+#ifdef FORCE_BUILD_LLVM_DISABLE_NDEBUG
+  static const uint32_t kSlangMinimumFixedStructureNames = 2310;
+  uint32_t version = wrapper.getCompilerVersion();
+  if (version < kSlangMinimumFixedStructureNames) {
+    ALOGE("Found invalid legacy bitcode compiled with a version %u llvm-rs-cc "
+          "used with an assertion build", version);
+    ALOGE("Please recompile this apk with a more recent llvm-rs-cc "
+          "(at least %u)", kSlangMinimumFixedStructureNames);
+    return false;
+  }
+#endif
+
+  //===--------------------------------------------------------------------===//
+  // Compile the script
+  //===--------------------------------------------------------------------===//
+  Compiler::ErrorCode status = compileScript(script, pResName,
+                                             output_path.c_str(),
+                                             pRuntimePath,
+                                             pBuildChecksum,
+                                             pDumpIR);
+
+  return status == Compiler::kSuccess;
+}
+
+bool RSCompilerDriver::buildScriptGroup(
+    BCCContext& Context, const char* pOutputFilepath, const char* pRuntimePath,
+    const char* pRuntimeRelaxedPath, bool dumpIR, const char* buildChecksum,
+    const std::vector<Source*>& sources,
+    const std::list<std::list<std::pair<int, int>>>& toFuse,
+    const std::list<std::string>& fused,
+    const std::list<std::list<std::pair<int, int>>>& invokes,
+    const std::list<std::string>& invokeBatchNames) {
+
+  // Read and store metadata before linking the modules together
+  std::vector<bcinfo::MetadataExtractor*> metadata;
+  for (Source* source : sources) {
+    if (!source->extractMetadata()) {
+      ALOGE("Cannot extract metadata from module");
+      return false;
+    }
+  }
+
+  // ---------------------------------------------------------------------------
+  // Link all input modules into a single module
+  // ---------------------------------------------------------------------------
+
+  llvm::LLVMContext& context = Context.getLLVMContext();
+  llvm::Module module("Merged Script Group", context);
+
+  llvm::Linker linker(module);
+  for (Source* source : sources) {
+    std::unique_ptr<llvm::Module> sourceModule(&source->getModule());
+    if (linker.linkInModule(std::move(sourceModule))) {
+      ALOGE("Linking for module in source failed.");
+      return false;
+    }
+    // source->getModule() is destroyed after linking.
+    source->markModuleDestroyed();
+  }
+
+  // ---------------------------------------------------------------------------
+  // Create fused kernels
+  // ---------------------------------------------------------------------------
+
+  auto inputIter = toFuse.begin();
+  for (const std::string& nameOfFused : fused) {
+    auto inputKernels = *inputIter++;
+    std::vector<Source*> sourcesToFuse;
+    std::vector<int> slots;
+
+    for (auto p : inputKernels) {
+      sourcesToFuse.push_back(sources[p.first]);
+      slots.push_back(p.second);
+    }
+
+    if (!fuseKernels(Context, sourcesToFuse, slots, nameOfFused, &module)) {
+      return false;
+    }
+  }
+
+  // ---------------------------------------------------------------------------
+  // Rename invokes
+  // ---------------------------------------------------------------------------
+
+  auto invokeIter = invokes.begin();
+  for (const std::string& newName : invokeBatchNames) {
+    auto inputInvoke = *invokeIter++;
+    auto p = inputInvoke.front();
+    Source* source = sources[p.first];
+    int slot = p.second;
+
+    if (!renameInvoke(Context, source, slot, newName, &module)) {
+      return false;
+    }
+  }
+
+  // ---------------------------------------------------------------------------
+  // Compile the new module with fused kernels
+  // ---------------------------------------------------------------------------
+
+  const std::unique_ptr<Source> source(
+      Source::CreateFromModule(Context, pOutputFilepath, module, true));
+  RSScript script(*source);
+
+  // Embed the info string directly in the ELF
+  script.setEmbedInfo(true);
+  script.setOptimizationLevel(RSScript::kOptLvl3);
+  script.setEmbedGlobalInfo(mEmbedGlobalInfo);
+  script.setEmbedGlobalInfoSkipConstant(mEmbedGlobalInfoSkipConstant);
+
+  llvm::SmallString<80> output_path(pOutputFilepath);
+  llvm::sys::path::replace_extension(output_path, ".o");
+
+  // Pick the right runtime lib
+  const char* coreLibPath = pRuntimePath;
+  if (strcmp(pRuntimeRelaxedPath, "")) {
+      bcinfo::MetadataExtractor me(&module);
+      me.extract();
+      if (me.getRSFloatPrecision() == bcinfo::RS_FP_Relaxed) {
+          coreLibPath = pRuntimeRelaxedPath;
+      }
+  }
+
+  compileScript(script, pOutputFilepath, output_path.c_str(), coreLibPath,
+                buildChecksum, dumpIR);
+
+  return true;
+}
+
+bool RSCompilerDriver::buildForCompatLib(RSScript &pScript, const char *pOut,
+                                         const char *pBuildChecksum,
+                                         const char *pRuntimePath,
+                                         bool pDumpIR) {
+  // Embed the info string directly in the ELF, since this path is for an
+  // offline (host) compilation.
+  pScript.setEmbedInfo(true);
+
+  pScript.setEmbedGlobalInfo(mEmbedGlobalInfo);
+  pScript.setEmbedGlobalInfoSkipConstant(mEmbedGlobalInfoSkipConstant);
+  pScript.setLinkRuntimeCallback(getLinkRuntimeCallback());
+
+  Compiler::ErrorCode status = compileScript(pScript, pOut, pOut, pRuntimePath,
+                                             pBuildChecksum, pDumpIR);
+  if (status != Compiler::kSuccess) {
+    return false;
+  }
+
+  return true;
+}
diff --git a/libbcc/lib/Renderscript/RSEmbedInfo.cpp b/libbcc/lib/Renderscript/RSEmbedInfo.cpp
new file mode 100644
index 0000000..081bed6
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSEmbedInfo.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Config/Config.h"
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Renderscript/RSUtils.h"
+#include "bcc/Support/Log.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "rsDefines.h"
+
+#include <cstdlib>
+#include <vector>
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Pass.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/IR/Type.h>
+
+using namespace bcc;
+
+namespace {
+
+/* RSEmbedInfoPass - This pass operates on the entire module and embeds a
+ * string constaining relevant metadata directly as a global variable.
+ * This information does not need to be consistent across Android releases,
+ * because the standalone compiler + compatibility driver or system driver
+ * will be using the same format (i.e. bcc_compat + libRSSupport.so or
+ * bcc + libRSCpuRef are always paired together for installation).
+ */
+class RSEmbedInfoPass : public llvm::ModulePass {
+private:
+  static char ID;
+
+  llvm::Module *M;
+  llvm::LLVMContext *C;
+
+public:
+  RSEmbedInfoPass()
+      : ModulePass(ID),
+        M(nullptr) {
+  }
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  static std::string getRSInfoString(const llvm::Module *module) {
+    std::string str;
+    llvm::raw_string_ostream s(str);
+    bcinfo::MetadataExtractor me(module);
+    if (!me.extract()) {
+      bccAssert(false && "Could not extract RS metadata for module!");
+      return std::string("");
+    }
+
+    size_t exportVarCount = me.getExportVarCount();
+    size_t exportFuncCount = me.getExportFuncCount();
+    size_t exportForEachCount = me.getExportForEachSignatureCount();
+    size_t exportReduceCount = me.getExportReduceCount();
+    size_t objectSlotCount = me.getObjectSlotCount();
+    size_t pragmaCount = me.getPragmaCount();
+    const char **exportVarNameList = me.getExportVarNameList();
+    const char **exportFuncNameList = me.getExportFuncNameList();
+    const char **exportForEachNameList = me.getExportForEachNameList();
+    const uint32_t *exportForEachSignatureList =
+        me.getExportForEachSignatureList();
+    const bcinfo::MetadataExtractor::Reduce *exportReduceList =
+        me.getExportReduceList();
+    const uint32_t *objectSlotList = me.getObjectSlotList();
+    const char **pragmaKeyList = me.getPragmaKeyList();
+    const char **pragmaValueList = me.getPragmaValueList();
+    bool isThreadable = me.isThreadable();
+    const char *buildChecksum = me.getBuildChecksum();
+
+    size_t i;
+
+    // We use a simple text format here that the compatibility library
+    // can easily parse. Each section starts out with its name
+    // followed by a count.  The count denotes the number of lines to
+    // parse for that particular category. Variables and Functions
+    // merely put the appropriate identifier on the line. ForEach
+    // kernels have the encoded int signature, followed by a hyphen
+    // followed by the identifier (function to look up). General
+    // reduce kernels have the encoded int signature, followed by a
+    // hyphen followed by the accumulator data size, followed by a
+    // hyphen followed by the identifier (reduction name); and then
+    // for each possible constituent function, a hyphen followed by
+    // the identifier (function name) -- in the case where the
+    // function is omitted, "." is used in place of the identifier.
+    // Object Slots are just listed as one integer per line.
+
+    s << "exportVarCount: " << exportVarCount << "\n";
+    for (i = 0; i < exportVarCount; ++i) {
+      s << exportVarNameList[i] << "\n";
+    }
+
+    s << "exportFuncCount: " << exportFuncCount << "\n";
+    for (i = 0; i < exportFuncCount; ++i) {
+      s << exportFuncNameList[i] << "\n";
+    }
+
+    s << "exportForEachCount: " << exportForEachCount << "\n";
+    for (i = 0; i < exportForEachCount; ++i) {
+      s << exportForEachSignatureList[i] << " - "
+        << exportForEachNameList[i] << "\n";
+    }
+
+    s << "exportReduceCount: " << exportReduceCount << "\n";
+    auto reduceFnName = [](const char *Name) { return Name ? Name : "."; };
+    for (i = 0; i < exportReduceCount; ++i) {
+      const bcinfo::MetadataExtractor::Reduce &reduce = exportReduceList[i];
+      s << reduce.mSignature << " - "
+        << reduce.mAccumulatorDataSize << " - "
+        << reduce.mReduceName << " - "
+        << reduceFnName(reduce.mInitializerName) << " - "
+        << reduceFnName(reduce.mAccumulatorName) << " - "
+        << ((reduce.mCombinerName != nullptr)
+            ? reduce.mCombinerName
+            : nameReduceCombinerFromAccumulator(reduce.mAccumulatorName)) << " - "
+        << reduceFnName(reduce.mOutConverterName) << " - "
+        << reduceFnName(reduce.mHalterName)
+        << "\n";
+    }
+
+    s << "objectSlotCount: " << objectSlotCount << "\n";
+    for (i = 0; i < objectSlotCount; ++i) {
+      s << objectSlotList[i] << "\n";
+    }
+
+    s << "pragmaCount: " << pragmaCount << "\n";
+    for (i = 0; i < pragmaCount; ++i) {
+      s << pragmaKeyList[i] << " - "
+        << pragmaValueList[i] << "\n";
+    }
+    s << "isThreadable: " << ((isThreadable) ? "yes" : "no") << "\n";
+
+    if (buildChecksum != nullptr && buildChecksum[0]) {
+      s << "buildChecksum: " << buildChecksum << "\n";
+    }
+
+    s.flush();
+    return str;
+  }
+
+  virtual bool runOnModule(llvm::Module &M) {
+    this->M = &M;
+    C = &M.getContext();
+
+    // Embed this as the global variable .rs.info so that it will be
+    // accessible from the shared object later.
+    llvm::Constant *Init = llvm::ConstantDataArray::getString(*C,
+                                                              getRSInfoString(&M));
+    llvm::GlobalVariable *InfoGV =
+        new llvm::GlobalVariable(M, Init->getType(), true,
+                                 llvm::GlobalValue::ExternalLinkage, Init,
+                                 kRsInfo);
+    (void) InfoGV;
+
+    return true;
+  }
+
+  virtual const char *getPassName() const {
+    return "Embed Renderscript Info";
+  }
+
+};  // end RSEmbedInfoPass
+
+}  // end anonymous namespace
+
+char RSEmbedInfoPass::ID = 0;
+
+namespace bcc {
+
+llvm::ModulePass *
+createRSEmbedInfoPass() {
+  return new RSEmbedInfoPass();
+}
+
+}  // end namespace bcc
diff --git a/libbcc/lib/Renderscript/RSGlobalInfoPass.cpp b/libbcc/lib/Renderscript/RSGlobalInfoPass.cpp
new file mode 100644
index 0000000..23a3013
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSGlobalInfoPass.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSUtils.h"
+#include "bcc/Support/Log.h"
+
+#include "rsDefines.h"
+
+#include <llvm/IR/Constant.h>
+#include <llvm/IR/Constants.h>
+#include <llvm/IR/Type.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Function.h>
+#include <llvm/Pass.h>
+
+#include <sstream>
+#include <vector>
+
+namespace {
+
+const bool kDebugGlobalInfo = false;
+
+/* RSGlobalInfoPass: Embeds additional information about RenderScript global
+ * variables into the Module. The 5 variables added are specified as follows:
+ * 1) .rs.global_entries
+ *    i32 - int
+ *    Optional number of global variables.
+ * 2) .rs.global_names
+ *    [N * i8*] - const char *[N]
+ *    Optional global variable name info. Each entry corresponds to the name
+ *    of 1 of the N global variables.
+ * 3) .rs.global_addresses
+ *    [N * i8*] - void*[N] or void**
+ *    Optional global variable address info. Each entry corresponds to the
+ *    address of 1 of the N global variables.
+ * 4) .rs.global_sizes
+ *    [N * i32] or [N * i64] - size_t[N]
+ *    Optional global variable size info. Each entry corresponds to the size
+ *    of 1 of the N global variables.
+ * 5) .rs.global_properties
+ *    [N * i32]
+ *    Optional global properties. Each entry corresponds to the properties
+ *    for 1 of the N global variables. The 32-bit integer for properties
+ *    can be broken down as follows:
+ *    bit(s)    Encoded value
+ *    ------    -------------
+ *        18    Pointer (1 is pointer, 0 is non-pointer)
+ *        17    Static (1 is static, 0 is extern)
+ *        16    Constant (1 is const, 0 is non-const)
+ *    15 - 0    RsDataType (see frameworks/rs/rsDefines.h for more info)
+ */
+class RSGlobalInfoPass: public llvm::ModulePass {
+private:
+  // If true, we don't include information about immutable global variables
+  // in our various exported data structures.
+  bool mSkipConstants;
+
+  // Encodes properties of the GlobalVariable into a uint32_t.
+  // These values are used to populate the .rs.global_properties array.
+  static uint32_t getEncodedProperties(const llvm::GlobalVariable &GV) {
+    auto GlobalType = GV.getType()->getPointerElementType();
+
+    // We start by getting the RsDataType and placing it into our result.
+    uint32_t result = getRsDataTypeForType(GlobalType);
+    bccAssert(!(result & ~RS_GLOBAL_TYPE));  // Can only alter lower 16-bits.
+
+    if (GlobalType->isPointerTy()) {
+      // Global variables that are pointers can all be used with "bind".
+      result |= RS_GLOBAL_POINTER;
+    }
+
+    if (GV.isConstant()) {
+      result |= RS_GLOBAL_CONSTANT;
+    }
+
+    if (GV.getLinkage() == llvm::GlobalValue::InternalLinkage) {
+      // We only have internal linkage in RS to signify static.
+      result |= RS_GLOBAL_STATIC;
+    }
+
+    return result;
+  }
+
+public:
+  static char ID;
+
+  explicit RSGlobalInfoPass(bool pSkipConstants = false)
+    : ModulePass (ID), mSkipConstants(pSkipConstants) {
+  }
+
+  void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    // This pass does not use any other analysis passes, but it does
+    // add new global variables.
+  }
+
+  bool runOnModule(llvm::Module &M) override {
+    std::vector<llvm::Constant *> GVAddresses;
+    std::vector<llvm::Constant *> GVNames;
+    std::vector<std::string> GVNameStrings;
+    std::vector<uint32_t> GVSizes32;
+    std::vector<uint64_t> GVSizes64;
+    std::vector<uint32_t> GVProperties;
+
+    const llvm::DataLayout &DL = M.getDataLayout();
+    const size_t PointerSizeInBits = DL.getPointerSizeInBits();
+
+    bccAssert(PointerSizeInBits == 32 || PointerSizeInBits == 64);
+
+    int GlobalNumber = 0;
+
+    // i8* - LLVM uses this to represent void* and char*
+    llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(M.getContext());
+
+    // i32
+    llvm::Type *Int32Ty = llvm::Type::getInt32Ty(M.getContext());
+
+    // i32 or i64 depending on our actual size_t
+    llvm::Type *SizeTy = llvm::Type::getIntNTy(M.getContext(),
+                                               PointerSizeInBits);
+
+    for (auto &GV : M.globals()) {
+      // Skip constant variables if we were configured to do so.
+      if (mSkipConstants && GV.isConstant()) {
+        continue;
+      }
+
+      // Skip intrinsic variables.
+      if (GV.getName().startswith("llvm.")) {
+        continue;
+      }
+
+      // In LLVM, an instance of GlobalVariable is actually a Value
+      // corresponding to the address of it.
+      GVAddresses.push_back(llvm::ConstantExpr::getBitCast(&GV, VoidPtrTy));
+      GVNameStrings.push_back(GV.getName());
+
+      // Since these are all global variables, their type is actually a
+      // pointer to the underlying data. We can extract the total underlying
+      // storage size by looking at the first contained type.
+      auto GlobalType = GV.getType()->getPointerElementType();
+      auto TypeSize = DL.getTypeAllocSize(GlobalType);
+      if (PointerSizeInBits == 32) {
+        GVSizes32.push_back(TypeSize);
+      } else {
+        GVSizes64.push_back(TypeSize);
+      }
+
+      GVProperties.push_back(getEncodedProperties(GV));
+    }
+
+    // Create the new strings for storing the names of the global variables.
+    // This has to be done as a separate pass (over the original global
+    // variables), because these strings are new global variables themselves.
+    for (const auto &GVN : GVNameStrings) {
+      llvm::Constant *C =
+          llvm::ConstantDataArray::getString(M.getContext(), GVN);
+      std::stringstream VarName;
+      VarName << ".rs.name_str_" << GlobalNumber++;
+      llvm::Value *V = M.getOrInsertGlobal(VarName.str(), C->getType());
+      llvm::GlobalVariable *VarAsStr = llvm::dyn_cast<llvm::GlobalVariable>(V);
+      VarAsStr->setInitializer(C);
+      VarAsStr->setConstant(true);
+      VarAsStr->setLinkage(llvm::GlobalValue::PrivateLinkage);
+      VarAsStr->setUnnamedAddr(true);
+      // VarAsStr has type [_ x i8]*. Cast to i8* for storing in
+      // .rs.global_names.
+      GVNames.push_back(llvm::ConstantExpr::getBitCast(VarAsStr, VoidPtrTy));
+    }
+
+    if (PointerSizeInBits == 32) {
+      bccAssert(GVAddresses.size() == GVSizes32.size());
+      bccAssert(GVSizes64.size() == 0);
+      bccAssert(GVAddresses.size() == GVProperties.size());
+    } else {
+      bccAssert(GVSizes32.size() == 0);
+      bccAssert(GVAddresses.size() == GVSizes64.size());
+      bccAssert(GVAddresses.size() == GVProperties.size());
+    }
+
+    size_t NumGlobals = GVAddresses.size();
+
+    // [NumGlobals * i8*]
+    llvm::ArrayType *VoidPtrArrayTy = llvm::ArrayType::get(VoidPtrTy,
+                                                           NumGlobals);
+    // [NumGlobals * i32] or [NumGlobals * i64]
+    llvm::ArrayType *SizeArrayTy = llvm::ArrayType::get(SizeTy, NumGlobals);
+
+    // [NumGlobals * i32]
+    llvm::ArrayType *Int32ArrayTy = llvm::ArrayType::get(Int32Ty, NumGlobals);
+
+    // 1) @.rs.global_entries = constant i32 NumGlobals
+    llvm::Value *V = M.getOrInsertGlobal(kRsGlobalEntries, Int32Ty);
+    llvm::GlobalVariable *GlobalEntries =
+        llvm::dyn_cast<llvm::GlobalVariable>(V);
+    llvm::Constant *GlobalEntriesInit =
+        llvm::ConstantInt::get(Int32Ty, NumGlobals);
+    GlobalEntries->setInitializer(GlobalEntriesInit);
+    GlobalEntries->setConstant(true);
+
+    // 2) @.rs.global_names = constant [N * i8*] [...]
+    V = M.getOrInsertGlobal(kRsGlobalNames, VoidPtrArrayTy);
+    llvm::GlobalVariable *GlobalNames =
+        llvm::dyn_cast<llvm::GlobalVariable>(V);
+    llvm::Constant *GlobalNamesInit =
+        llvm::ConstantArray::get(VoidPtrArrayTy, GVNames);
+    GlobalNames->setInitializer(GlobalNamesInit);
+    GlobalNames->setConstant(true);
+
+    // 3) @.rs.global_addresses = constant [N * i8*] [...]
+    V = M.getOrInsertGlobal(kRsGlobalAddresses, VoidPtrArrayTy);
+    llvm::GlobalVariable *GlobalAddresses =
+        llvm::dyn_cast<llvm::GlobalVariable>(V);
+    llvm::Constant *GlobalAddressesInit =
+        llvm::ConstantArray::get(VoidPtrArrayTy, GVAddresses);
+    GlobalAddresses->setInitializer(GlobalAddressesInit);
+    GlobalAddresses->setConstant(true);
+
+
+    // 4) @.rs.global_sizes = constant [N * i32 or i64] [...]
+    V = M.getOrInsertGlobal(kRsGlobalSizes, SizeArrayTy);
+    llvm::GlobalVariable *GlobalSizes =
+        llvm::dyn_cast<llvm::GlobalVariable>(V);
+    llvm::Constant *GlobalSizesInit;
+    if (PointerSizeInBits == 32) {
+      GlobalSizesInit = llvm::ConstantDataArray::get(M.getContext(), GVSizes32);
+    } else {
+      GlobalSizesInit = llvm::ConstantDataArray::get(M.getContext(), GVSizes64);
+    }
+    GlobalSizes->setInitializer(GlobalSizesInit);
+    GlobalSizes->setConstant(true);
+
+    // 5) @.rs.global_properties = constant i32 NumGlobals
+    V = M.getOrInsertGlobal(kRsGlobalProperties, Int32ArrayTy);
+    llvm::GlobalVariable *GlobalProperties =
+        llvm::dyn_cast<llvm::GlobalVariable>(V);
+    llvm::Constant *GlobalPropertiesInit =
+        llvm::ConstantDataArray::get(M.getContext(), GVProperties);
+    GlobalProperties->setInitializer(GlobalPropertiesInit);
+    GlobalProperties->setConstant(true);
+
+    if (kDebugGlobalInfo) {
+      GlobalEntries->dump();
+      GlobalNames->dump();
+      GlobalAddresses->dump();
+      GlobalSizes->dump();
+      GlobalProperties->dump();
+    }
+
+    // Upon completion, this pass has always modified the Module.
+    return true;
+  }
+};
+
+}
+
+char RSGlobalInfoPass::ID = 0;
+
+static llvm::RegisterPass<RSGlobalInfoPass> X("embed-rs-global-info",
+  "Embed additional information about RenderScript global variables");
+
+namespace bcc {
+
+llvm::ModulePass * createRSGlobalInfoPass(bool pSkipConstants) {
+  return new RSGlobalInfoPass(pSkipConstants);
+}
+
+}
diff --git a/libbcc/lib/Renderscript/RSInvariant.cpp b/libbcc/lib/Renderscript/RSInvariant.cpp
new file mode 100644
index 0000000..eb11d7e
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSInvariant.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Renderscript/RSUtils.h"
+
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Metadata.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Pass.h>
+
+namespace {
+
+/*
+ * RSInvariantPass - This pass looks for Loads that access
+ * RsExpandKernelDriverInfo instances (which should never be written by
+ * a script, only by the driver) and marks them "invariant.load".
+ *
+ * There should be only two sources of Loads from such instances:
+ * - An instance can appear as an argument of type
+ *   "RsExpandKernelDriverInfoPfx*" passed to a .expand function by
+ *   the driver.
+ * - An instance can appear as an argument of type
+ *   "rs_kernel_context_t*" passed to an API query function by the
+ *   user.
+ * Only the compiler-generated .expand functions and the API query
+ * functions can see the fields of RsExpandKernelDriverInfo --
+ * rs_kernel_context_t is opaque to user code, so there cannot be any
+ * Loads from it in user code.
+ *
+ * This pass should be run
+ * - after foreachexp, so that it can see the Loads generated within
+ *   .expand functions
+ * - before inlining, so that it can recognize API query function
+ *   arguments.
+ *
+ * WARNINGS:
+ * - If user code or APIs can modify RsExpandKernelDriverInfo
+ *   instances, this pass MAY ALLOW ILLEGAL OPTIMIZATION.
+ * - If this pass runs at a different time, it may be ineffective
+ *   (fail to mark some or all eligible Loads, and thereby cost
+ *   performance).
+ * - If the names of the data types change, this pass may be
+ *   ineffective.
+ * - If the patterns by which fields are loaded from
+ *   RsExpandKernelDriverInfo instances change, this pass may be
+ *   ineffective.
+ */
+class RSInvariantPass : public llvm::FunctionPass {
+public:
+  static char ID;
+
+  RSInvariantPass() : FunctionPass(ID), EmptyMDNode(nullptr) { }
+
+  virtual bool doInitialization(llvm::Module &M) {
+    EmptyMDNode = llvm::MDNode::get(M.getContext(), llvm::None);
+    return true;
+  }
+
+  virtual bool runOnFunction(llvm::Function &F) {
+    bool Changed = false;
+
+    for (llvm::Value &Arg : F.args()) {
+      const llvm::Type *ArgType = Arg.getType();
+      if (ArgType->isPointerTy()) {
+        const llvm::Type *ArgPtrDomainType =  ArgType->getPointerElementType();
+        if (auto ArgPtrDomainStructType = llvm::dyn_cast<llvm::StructType>(ArgPtrDomainType)) {
+          if (!ArgPtrDomainStructType->isLiteral()) {
+            const llvm::StringRef StructName = getUnsuffixedStructName(ArgPtrDomainStructType);
+            if (StructName.equals("struct.rs_kernel_context_t") || StructName.equals("RsExpandKernelDriverInfoPfx")) {
+              Changed |= markInvariantUserLoads(&Arg);
+            }
+          }
+        }
+      }
+    }
+
+    return Changed;
+  }
+
+  virtual const char *getPassName() const {
+    return "Renderscript Invariant Load Annotation";
+  }
+
+private:
+
+  /*
+   * Follow def->use chains rooted at Value through calculations
+   * "based on" Value (see the "based on" definition at
+   * http://llvm.org/docs/LangRef.html#pointer-aliasing-rules).  If a
+   * chain reaches the pointer operand of a Load, mark that Load as
+   * "invariant.load" -- i.e., it accesses memory which does not
+   * change.
+   */
+  bool markInvariantUserLoads(llvm::Value *Value) {
+    bool Changed = false;
+    for (llvm::Use &Use : Value->uses()) {
+      llvm::Instruction *Inst = llvm::cast<llvm::Instruction>(Use.getUser());
+
+      /*
+       * We only examine a small set of opcodes here, because these
+       * are the opcodes that currently appear in the patterns of
+       * interest (foreachexp-generated code, and
+       * rsGet*(rs_kernel_context_t*) APIs).  Other opcodes could be
+       * added if necessary.
+       */
+      if (auto BitCast = llvm::dyn_cast<llvm::BitCastInst>(Inst)) {
+        Changed |= markInvariantUserLoads(BitCast);
+      } else if (auto GetElementPtr = llvm::dyn_cast<llvm::GetElementPtrInst>(Inst)) {
+        if (Use.get() == GetElementPtr->getPointerOperand())
+          Changed |= markInvariantUserLoads(GetElementPtr);
+      } else if (auto Load = llvm::dyn_cast<llvm::LoadInst>(Inst)) {
+        if (Use.get() == Load->getPointerOperand()) {
+          Load->setMetadata("invariant.load", EmptyMDNode);
+          Changed = true;
+        }
+      }
+    }
+    return Changed;
+  }
+
+  // Pointer to empty metadata node used for "invariant.load" marking.
+  llvm::MDNode *EmptyMDNode;
+}; // end RSInvariantPass
+
+char RSInvariantPass::ID = 0;
+llvm::RegisterPass<RSInvariantPass> X("rsinvariant", "RS Invariant Load Pass");
+
+} // end anonymous namespace
+
+namespace bcc {
+
+llvm::FunctionPass *
+createRSInvariantPass() {
+  return new RSInvariantPass();
+}
+
+} // end namespace bcc
diff --git a/libbcc/lib/Renderscript/RSInvokeHelperPass.cpp b/libbcc/lib/Renderscript/RSInvokeHelperPass.cpp
new file mode 100644
index 0000000..af72ff1
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSInvokeHelperPass.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Renderscript/RSUtils.h"
+#include "rsDefines.h"
+
+#include <cstdlib>
+
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/MDBuilder.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Pass.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Transforms/Utils/BasicBlockUtils.h>
+
+#include "bcc/Config/Config.h"
+#include "bcc/Support/Log.h"
+
+#include "bcinfo/MetadataExtractor.h"
+
+using namespace bcc;
+
+namespace {
+
+class RSInvokeHelperPass : public llvm::FunctionPass {
+private:
+  static char ID;
+
+  llvm::StructType* rsAllocationType;
+  llvm::StructType* rsElementType;
+  llvm::StructType* rsSamplerType;
+  llvm::StructType* rsScriptType;
+  llvm::StructType* rsTypeType;
+
+  llvm::Constant* rsAllocationSetObj;
+  llvm::Constant* rsElementSetObj;
+  llvm::Constant* rsSamplerSetObj;
+  llvm::Constant* rsScriptSetObj;
+  llvm::Constant* rsTypeSetObj;
+
+
+public:
+  RSInvokeHelperPass()
+    : FunctionPass(ID) {
+
+    }
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    // This pass does not use any other analysis passes, but it does
+    // modify the existing functions in the module (thus altering the CFG).
+  }
+
+  virtual bool doInitialization(llvm::Module &M) override {
+    llvm::FunctionType * SetObjType = nullptr;
+    llvm::SmallVector<llvm::Type*, 4> rsBaseObj;
+    rsBaseObj.append(4, llvm::Type::getInt64PtrTy(M.getContext()));
+
+    rsAllocationType = llvm::StructType::create(rsBaseObj, kAllocationTypeName);
+    rsElementType = llvm::StructType::create(rsBaseObj, kElementTypeName);
+    rsSamplerType = llvm::StructType::create(rsBaseObj, kSamplerTypeName);
+    rsScriptType = llvm::StructType::create(rsBaseObj, kScriptTypeName);
+    rsTypeType = llvm::StructType::create(rsBaseObj, kTypeTypeName);
+
+    llvm::SmallVector<llvm::Value*, 1> SetObjParams;
+    llvm::SmallVector<llvm::Type*, 2> SetObjTypeParams;
+
+    // get rsSetObject(rs_allocation*, rs_allocation*)
+    // according to AArch64 calling convention, these are both pointers because of the size of the struct
+    SetObjTypeParams.push_back(rsAllocationType->getPointerTo());
+    SetObjTypeParams.push_back(rsAllocationType->getPointerTo());
+    SetObjType = llvm::FunctionType::get(llvm::Type::getVoidTy(M.getContext()), SetObjTypeParams, false);
+    rsAllocationSetObj = M.getOrInsertFunction("_Z11rsSetObjectP13rs_allocationS_", SetObjType);
+    SetObjTypeParams.clear();
+
+    SetObjTypeParams.push_back(rsElementType->getPointerTo());
+    SetObjTypeParams.push_back(rsElementType->getPointerTo());
+    SetObjType = llvm::FunctionType::get(llvm::Type::getVoidTy(M.getContext()), SetObjTypeParams, false);
+    rsElementSetObj = M.getOrInsertFunction("_Z11rsSetObjectP10rs_elementS_", SetObjType);
+    SetObjTypeParams.clear();
+
+    SetObjTypeParams.push_back(rsSamplerType->getPointerTo());
+    SetObjTypeParams.push_back(rsSamplerType->getPointerTo());
+    SetObjType = llvm::FunctionType::get(llvm::Type::getVoidTy(M.getContext()), SetObjTypeParams, false);
+    rsSamplerSetObj = M.getOrInsertFunction("_Z11rsSetObjectP10rs_samplerS_", SetObjType);
+    SetObjTypeParams.clear();
+
+    SetObjTypeParams.push_back(rsScriptType->getPointerTo());
+    SetObjTypeParams.push_back(rsScriptType->getPointerTo());
+    SetObjType = llvm::FunctionType::get(llvm::Type::getVoidTy(M.getContext()), SetObjTypeParams, false);
+    rsScriptSetObj = M.getOrInsertFunction("_Z11rsSetObjectP9rs_scriptS_", SetObjType);
+    SetObjTypeParams.clear();
+
+    SetObjTypeParams.push_back(rsTypeType->getPointerTo());
+    SetObjTypeParams.push_back(rsTypeType->getPointerTo());
+    SetObjType = llvm::FunctionType::get(llvm::Type::getVoidTy(M.getContext()), SetObjTypeParams, false);
+    rsTypeSetObj = M.getOrInsertFunction("_Z11rsSetObjectP7rs_typeS_", SetObjType);
+    SetObjTypeParams.clear();
+
+    return true;
+  }
+
+  bool insertSetObjectHelper(llvm::CallInst *Call, llvm::Value *V, enum RsDataType DT) {
+    llvm::Constant *SetObj = nullptr;
+    llvm::StructType *RSStructType = nullptr;
+    switch (DT) {
+    case RS_TYPE_ALLOCATION:
+      SetObj = rsAllocationSetObj;
+      RSStructType = rsAllocationType;
+      break;
+    case RS_TYPE_ELEMENT:
+      SetObj = rsElementSetObj;
+      RSStructType = rsElementType;
+      break;
+    case RS_TYPE_SAMPLER:
+      SetObj = rsSamplerSetObj;
+      RSStructType = rsSamplerType;
+      break;
+    case RS_TYPE_SCRIPT:
+      SetObj = rsScriptSetObj;
+      RSStructType = rsScriptType;
+      break;
+    case RS_TYPE_TYPE:
+      SetObj = rsTypeSetObj;
+      RSStructType = rsTypeType;
+      break;
+    default:
+      return false; // this is for graphics types and matrices; do nothing
+    }
+
+
+    llvm::CastInst* CastedValue = llvm::CastInst::CreatePointerCast(V, RSStructType->getPointerTo(), "", Call);
+
+    llvm::SmallVector<llvm::Value*, 2> SetObjParams;
+    SetObjParams.push_back(CastedValue);
+    SetObjParams.push_back(CastedValue);
+
+    llvm::CallInst::Create(SetObj, SetObjParams, "", Call);
+
+
+    return true;
+  }
+
+
+  // this only modifies .helper functions that take certain RS base object types
+  virtual bool runOnFunction(llvm::Function &F) override {
+    if (!F.getName().startswith(".helper"))
+      return false;
+
+    bool changed = false;
+    const llvm::Function::ArgumentListType &argList(F.getArgumentList());
+    bool containsBaseObj = false;
+
+    // .helper methods should have one arg only, an anonymous struct
+    // that struct may contain BaseObjs
+    for (auto arg = argList.begin(); arg != argList.end(); arg++) {
+      llvm::Type *argType = arg->getType();
+      if (!argType->isPointerTy() || !argType->getPointerElementType()->isStructTy())
+        continue;
+
+      llvm::StructType *argStructType = llvm::dyn_cast<llvm::StructType>(argType->getPointerElementType());
+
+      for (unsigned int i = 0; i < argStructType->getNumElements(); i++) {
+        llvm::Type *currentType = argStructType->getElementType(i);
+        if (currentType->isStructTy() && currentType->getStructName().startswith("struct.rs_")) {
+          containsBaseObj = true;
+        }
+      }
+      break;
+    }
+
+
+    if (containsBaseObj) {
+      // modify the thing that should not be
+      auto &BBList(F.getBasicBlockList());
+      for (auto &BB : BBList) {
+        auto &InstList(BB.getInstList());
+        for (auto &Inst : InstList) {
+          // don't care about anything except call instructions that we didn't already add
+          if (llvm::CallInst *call = llvm::dyn_cast<llvm::CallInst>(&Inst)) {
+            for (unsigned int i = 0; i < call->getNumArgOperands(); i++) {
+              llvm::Value *V = call->getArgOperand(i);
+              llvm::Type *T = V->getType();
+              enum RsDataType DT = RS_TYPE_NONE;
+              if (T->isPointerTy() && T->getPointerElementType()->isStructTy()) {
+                DT = getRsDataTypeForType(T->getPointerElementType());
+              }
+              if (DT != RS_TYPE_NONE) {
+                // generate the new call instruction and insert it
+                changed |= insertSetObjectHelper(call, V, DT);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return changed;
+  }
+
+  virtual const char *getPassName() const override {
+    return ".helper method expansion for large RS objects";
+  }
+}; // end RSInvokeHelperPass class
+} // end anonymous namespace
+
+char RSInvokeHelperPass::ID = 0;
+
+namespace bcc {
+
+llvm::FunctionPass *
+createRSInvokeHelperPass(){
+  return new RSInvokeHelperPass();
+}
+
+}
diff --git a/libbcc/lib/Renderscript/RSIsThreadablePass.cpp b/libbcc/lib/Renderscript/RSIsThreadablePass.cpp
new file mode 100644
index 0000000..c136880
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSIsThreadablePass.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Support/Log.h"
+
+#include <cstdlib>
+
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Metadata.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Function.h>
+#include <llvm/Pass.h>
+
+namespace { // anonymous namespace
+
+// Create a Module pass that screens all the global functions in the module and
+// check if any non-threadable function is callable.  If so, we mark the
+// Module as non-threadable by adding a metadata flag '#rs_is_threadable'
+
+class RSIsThreadablePass : public llvm::ModulePass {
+private:
+  static char ID;
+
+  std::vector<std::string> nonThreadableFns = {
+    "_Z22rsgBindProgramFragment19rs_program_fragment",
+    "_Z19rsgBindProgramStore16rs_program_store",
+    "_Z20rsgBindProgramVertex17rs_program_vertex",
+    "_Z20rsgBindProgramRaster17rs_program_raster",
+    "_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler",
+    "_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation",
+    "_Z15rsgBindConstant19rs_program_fragmentj13rs_allocation",
+    "_Z15rsgBindConstant17rs_program_vertexj13rs_allocation",
+    "_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4",
+    "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4",
+    "_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4",
+    "_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4",
+    "_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff",
+    "_Z11rsgGetWidthv",
+    "_Z12rsgGetHeightv",
+    "_Z11rsgDrawRectfffff",
+    "_Z11rsgDrawQuadffffffffffff",
+    "_Z20rsgDrawQuadTexCoordsffffffffffffffffffff",
+    "_Z24rsgDrawSpriteScreenspacefffff",
+    "_Z11rsgDrawMesh7rs_mesh",
+    "_Z11rsgDrawMesh7rs_meshj",
+    "_Z11rsgDrawMesh7rs_meshjjj",
+    "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_",
+    "_Z11rsgDrawPath7rs_path",
+    "_Z13rsgClearColorffff",
+    "_Z13rsgClearDepthf",
+    "_Z11rsgDrawTextPKcii",
+    "_Z11rsgDrawText13rs_allocationii",
+    "_Z14rsgMeasureTextPKcPiS1_S1_S1_",
+    "_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_",
+    "_Z11rsgBindFont7rs_font",
+    "_Z12rsgFontColorffff",
+    "_Z18rsgBindColorTarget13rs_allocationj",
+    "_Z18rsgBindDepthTarget13rs_allocation",
+    "_Z19rsgClearColorTargetj",
+    "_Z19rsgClearDepthTargetv",
+    "_Z24rsgClearAllRenderTargetsv",
+    "_Z7rsGetDtv",
+    "_Z5colorffff",
+    "_Z9rsgFinishv",
+  };
+
+  bool isPresent(std::vector<std::string> &list, const std::string &name) {
+    auto lower = std::lower_bound(list.begin(),
+                                  list.end(),
+                                  name);
+
+    if (lower != list.end() && name.compare(*lower) == 0)
+      return true;
+    return false;
+  }
+
+public:
+  RSIsThreadablePass()
+    : ModulePass (ID) {
+      std::sort(nonThreadableFns.begin(), nonThreadableFns.end());
+  }
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  bool runOnModule(llvm::Module &M) override {
+    bool threadable = true;
+
+    auto &FunctionList(M.getFunctionList());
+    for (auto &F: FunctionList) {
+      if (isPresent(nonThreadableFns, F.getName().str())) {
+        threadable = false;
+        break;
+      }
+    }
+
+    llvm::LLVMContext &context = M.getContext();
+    llvm::MDString *val =
+      llvm::MDString::get(context, (threadable) ? "yes" : "no");
+    llvm::NamedMDNode *node =
+        M.getOrInsertNamedMetadata("#rs_is_threadable");
+    node->addOperand(llvm::MDNode::get(context, val));
+
+    return false;
+  }
+
+};
+
+}
+
+char RSIsThreadablePass::ID = 0;
+
+namespace bcc {
+
+llvm::ModulePass *
+createRSIsThreadablePass () {
+  return new RSIsThreadablePass();
+}
+
+}
diff --git a/libbcc/lib/Renderscript/RSKernelExpand.cpp b/libbcc/lib/Renderscript/RSKernelExpand.cpp
new file mode 100644
index 0000000..21e4503
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSKernelExpand.cpp
@@ -0,0 +1,1453 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Renderscript/RSUtils.h"
+
+#include <cstdlib>
+#include <functional>
+#include <unordered_set>
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/MDBuilder.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Pass.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Transforms/Utils/BasicBlockUtils.h>
+
+#include "bcc/Config/Config.h"
+#include "bcc/Support/Log.h"
+
+#include "bcinfo/MetadataExtractor.h"
+
+#ifndef __DISABLE_ASSERTS
+// Only used in bccAssert()
+const int kNumExpandedForeachParams = 4;
+const int kNumExpandedReduceAccumulatorParams = 4;
+#endif
+
+const char kRenderScriptTBAARootName[] = "RenderScript Distinct TBAA";
+const char kRenderScriptTBAANodeName[] = "RenderScript TBAA";
+
+using namespace bcc;
+
+namespace {
+
+static const bool gEnableRsTbaa = true;
+
+/* RSKernelExpandPass
+ *
+ * This pass generates functions used to implement calls via
+ * rsForEach(), "foreach_<NAME>", or "reduce_<NAME>". We create an
+ * inner loop for the function to be invoked over the appropriate data
+ * cells of the input/output allocations (adjusting other relevant
+ * parameters as we go). We support doing this for any forEach or
+ * reduce style compute kernels.
+ *
+ * In the case of a foreach kernel or a simple reduction kernel, the
+ * new function name is the original function name "<NAME>" followed
+ * by ".expand" -- "<NAME>.expand".
+ *
+ * In the case of a general reduction kernel, the kernel's accumulator
+ * function is the one transformed, and the new function name is the
+ * original accumulator function name "<ACCUMFN>" followed by
+ * ".expand" -- "<ACCUMFN>.expand". Using the name "<ACCUMFN>.expand"
+ * for the function generated from the accumulator should not
+ * introduce any possibility for name clashes today: The accumulator
+ * function <ACCUMFN> must be static, so it cannot also serve as a
+ * foreach kernel; and the code for <ACCUMFN>.expand depends only on
+ * <ACCUMFN>, not on any other properties of the reduction kernel, so
+ * any reduction kernels that share the accumulator <ACCUMFN> can
+ * share <ACCUMFN>.expand also.
+ *
+ * Note that this pass does not delete the original function <NAME> or
+ * <ACCUMFN>. However, if it is inlined into the newly-generated
+ * function and not otherwise referenced, then a subsequent pass may
+ * delete it.
+ */
+class RSKernelExpandPass : public llvm::ModulePass {
+public:
+  static char ID;
+
+private:
+  static const size_t RS_KERNEL_INPUT_LIMIT = 8; // see frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h
+
+  typedef std::unordered_set<llvm::Function *> FunctionSet;
+
+  enum RsLaunchDimensionsField {
+    RsLaunchDimensionsFieldX,
+    RsLaunchDimensionsFieldY,
+    RsLaunchDimensionsFieldZ,
+    RsLaunchDimensionsFieldLod,
+    RsLaunchDimensionsFieldFace,
+    RsLaunchDimensionsFieldArray,
+
+    RsLaunchDimensionsFieldCount
+  };
+
+  enum RsExpandKernelDriverInfoPfxField {
+    RsExpandKernelDriverInfoPfxFieldInPtr,
+    RsExpandKernelDriverInfoPfxFieldInStride,
+    RsExpandKernelDriverInfoPfxFieldInLen,
+    RsExpandKernelDriverInfoPfxFieldOutPtr,
+    RsExpandKernelDriverInfoPfxFieldOutStride,
+    RsExpandKernelDriverInfoPfxFieldOutLen,
+    RsExpandKernelDriverInfoPfxFieldDim,
+    RsExpandKernelDriverInfoPfxFieldCurrent,
+    RsExpandKernelDriverInfoPfxFieldUsr,
+    RsExpandKernelDriverInfoPfxFieldUsLenr,
+
+    RsExpandKernelDriverInfoPfxFieldCount
+  };
+
+  llvm::Module *Module;
+  llvm::LLVMContext *Context;
+
+  /*
+   * Pointers to LLVM type information for the the function signatures
+   * for expanded functions. These must be re-calculated for each module
+   * the pass is run on.
+   */
+  llvm::FunctionType *ExpandedForEachType;
+  llvm::Type *RsExpandKernelDriverInfoPfxTy;
+
+  uint32_t mExportForEachCount;
+  const char **mExportForEachNameList;
+  const uint32_t *mExportForEachSignatureList;
+
+  // Turns on optimization of allocation stride values.
+  bool mEnableStepOpt;
+
+  uint32_t getRootSignature(llvm::Function *Function) {
+    const llvm::NamedMDNode *ExportForEachMetadata =
+        Module->getNamedMetadata("#rs_export_foreach");
+
+    if (!ExportForEachMetadata) {
+      llvm::SmallVector<llvm::Type*, 8> RootArgTys;
+      for (llvm::Function::arg_iterator B = Function->arg_begin(),
+                                        E = Function->arg_end();
+           B != E;
+           ++B) {
+        RootArgTys.push_back(B->getType());
+      }
+
+      // For pre-ICS bitcode, we may not have signature information. In that
+      // case, we use the size of the RootArgTys to select the number of
+      // arguments.
+      return (1 << RootArgTys.size()) - 1;
+    }
+
+    if (ExportForEachMetadata->getNumOperands() == 0) {
+      return 0;
+    }
+
+    bccAssert(ExportForEachMetadata->getNumOperands() > 0);
+
+    // We only handle the case for legacy root() functions here, so this is
+    // hard-coded to look at only the first such function.
+    llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(0);
+    if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
+      llvm::Metadata *SigMD = SigNode->getOperand(0);
+      if (llvm::MDString *SigS = llvm::dyn_cast<llvm::MDString>(SigMD)) {
+        llvm::StringRef SigString = SigS->getString();
+        uint32_t Signature = 0;
+        if (SigString.getAsInteger(10, Signature)) {
+          ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
+          return 0;
+        }
+        return Signature;
+      }
+    }
+
+    return 0;
+  }
+
+  bool isStepOptSupported(llvm::Type *AllocType) {
+
+    llvm::PointerType *PT = llvm::dyn_cast<llvm::PointerType>(AllocType);
+    llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(*Context);
+
+    if (mEnableStepOpt) {
+      return false;
+    }
+
+    if (AllocType == VoidPtrTy) {
+      return false;
+    }
+
+    if (!PT) {
+      return false;
+    }
+
+    // remaining conditions are 64-bit only
+    if (VoidPtrTy->getPrimitiveSizeInBits() == 32) {
+      return true;
+    }
+
+    // coerce suggests an upconverted struct type, which we can't support
+    if (AllocType->getStructName().find("coerce") != llvm::StringRef::npos) {
+      return false;
+    }
+
+    // 2xi64 and i128 suggest an upconverted struct type, which are also unsupported
+    llvm::Type *V2xi64Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(*Context), 2);
+    llvm::Type *Int128Ty = llvm::Type::getIntNTy(*Context, 128);
+    if (AllocType == V2xi64Ty || AllocType == Int128Ty) {
+      return false;
+    }
+
+    return true;
+  }
+
+  // Get the actual value we should use to step through an allocation.
+  //
+  // Normally the value we use to step through an allocation is given to us by
+  // the driver. However, for certain primitive data types, we can derive an
+  // integer constant for the step value. We use this integer constant whenever
+  // possible to allow further compiler optimizations to take place.
+  //
+  // DL - Target Data size/layout information.
+  // T - Type of allocation (should be a pointer).
+  // OrigStep - Original step increment (root.expand() input from driver).
+  llvm::Value *getStepValue(llvm::DataLayout *DL, llvm::Type *AllocType,
+                            llvm::Value *OrigStep) {
+    bccAssert(DL);
+    bccAssert(AllocType);
+    bccAssert(OrigStep);
+    llvm::PointerType *PT = llvm::dyn_cast<llvm::PointerType>(AllocType);
+    if (isStepOptSupported(AllocType)) {
+      llvm::Type *ET = PT->getElementType();
+      uint64_t ETSize = DL->getTypeAllocSize(ET);
+      llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
+      return llvm::ConstantInt::get(Int32Ty, ETSize);
+    } else {
+      return OrigStep;
+    }
+  }
+
+  /// Builds the types required by the pass for the given context.
+  void buildTypes(void) {
+    // Create the RsLaunchDimensionsTy and RsExpandKernelDriverInfoPfxTy structs.
+
+    llvm::Type *Int8Ty                   = llvm::Type::getInt8Ty(*Context);
+    llvm::Type *Int8PtrTy                = Int8Ty->getPointerTo();
+    llvm::Type *Int8PtrArrayInputLimitTy = llvm::ArrayType::get(Int8PtrTy, RS_KERNEL_INPUT_LIMIT);
+    llvm::Type *Int32Ty                  = llvm::Type::getInt32Ty(*Context);
+    llvm::Type *Int32ArrayInputLimitTy   = llvm::ArrayType::get(Int32Ty, RS_KERNEL_INPUT_LIMIT);
+    llvm::Type *VoidPtrTy                = llvm::Type::getInt8PtrTy(*Context);
+    llvm::Type *Int32Array4Ty            = llvm::ArrayType::get(Int32Ty, 4);
+
+    /* Defined in frameworks/base/libs/rs/cpu_ref/rsCpuCore.h:
+     *
+     * struct RsLaunchDimensions {
+     *   uint32_t x;
+     *   uint32_t y;
+     *   uint32_t z;
+     *   uint32_t lod;
+     *   uint32_t face;
+     *   uint32_t array[4];
+     * };
+     */
+    llvm::SmallVector<llvm::Type*, RsLaunchDimensionsFieldCount> RsLaunchDimensionsTypes;
+    RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t x
+    RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t y
+    RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t z
+    RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t lod
+    RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t face
+    RsLaunchDimensionsTypes.push_back(Int32Array4Ty); // uint32_t array[4]
+    llvm::StructType *RsLaunchDimensionsTy =
+        llvm::StructType::create(RsLaunchDimensionsTypes, "RsLaunchDimensions");
+
+    /* Defined as the beginning of RsExpandKernelDriverInfo in frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h:
+     *
+     * struct RsExpandKernelDriverInfoPfx {
+     *     const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT];
+     *     uint32_t inStride[RS_KERNEL_INPUT_LIMIT];
+     *     uint32_t inLen;
+     *
+     *     uint8_t *outPtr[RS_KERNEL_INPUT_LIMIT];
+     *     uint32_t outStride[RS_KERNEL_INPUT_LIMIT];
+     *     uint32_t outLen;
+     *
+     *     // Dimension of the launch
+     *     RsLaunchDimensions dim;
+     *
+     *     // The walking iterator of the launch
+     *     RsLaunchDimensions current;
+     *
+     *     const void *usr;
+     *     uint32_t usrLen;
+     *
+     *     // Items below this line are not used by the compiler and can be change in the driver.
+     *     // So the compiler must assume there are an unknown number of fields of unknown type
+     *     // beginning here.
+     * };
+     *
+     * The name "RsExpandKernelDriverInfoPfx" is known to RSInvariantPass (RSInvariant.cpp).
+     */
+    llvm::SmallVector<llvm::Type*, RsExpandKernelDriverInfoPfxFieldCount> RsExpandKernelDriverInfoPfxTypes;
+    RsExpandKernelDriverInfoPfxTypes.push_back(Int8PtrArrayInputLimitTy); // const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT]
+    RsExpandKernelDriverInfoPfxTypes.push_back(Int32ArrayInputLimitTy);   // uint32_t inStride[RS_KERNEL_INPUT_LIMIT]
+    RsExpandKernelDriverInfoPfxTypes.push_back(Int32Ty);                  // uint32_t inLen
+    RsExpandKernelDriverInfoPfxTypes.push_back(Int8PtrArrayInputLimitTy); // uint8_t *outPtr[RS_KERNEL_INPUT_LIMIT]
+    RsExpandKernelDriverInfoPfxTypes.push_back(Int32ArrayInputLimitTy);   // uint32_t outStride[RS_KERNEL_INPUT_LIMIT]
+    RsExpandKernelDriverInfoPfxTypes.push_back(Int32Ty);                  // uint32_t outLen
+    RsExpandKernelDriverInfoPfxTypes.push_back(RsLaunchDimensionsTy);     // RsLaunchDimensions dim
+    RsExpandKernelDriverInfoPfxTypes.push_back(RsLaunchDimensionsTy);     // RsLaunchDimensions current
+    RsExpandKernelDriverInfoPfxTypes.push_back(VoidPtrTy);                // const void *usr
+    RsExpandKernelDriverInfoPfxTypes.push_back(Int32Ty);                  // uint32_t usrLen
+    RsExpandKernelDriverInfoPfxTy =
+        llvm::StructType::create(RsExpandKernelDriverInfoPfxTypes, "RsExpandKernelDriverInfoPfx");
+
+    // Create the function type for expanded kernels.
+    llvm::Type *VoidTy = llvm::Type::getVoidTy(*Context);
+
+    llvm::Type *RsExpandKernelDriverInfoPfxPtrTy = RsExpandKernelDriverInfoPfxTy->getPointerTo();
+    // void (const RsExpandKernelDriverInfoPfxTy *p, uint32_t x1, uint32_t x2, uint32_t outstep)
+    ExpandedForEachType = llvm::FunctionType::get(VoidTy,
+        {RsExpandKernelDriverInfoPfxPtrTy, Int32Ty, Int32Ty, Int32Ty}, false);
+  }
+
+  /// @brief Create skeleton of the expanded foreach kernel.
+  ///
+  /// This creates a function with the following signature:
+  ///
+  ///   void (const RsForEachStubParamStruct *p, uint32_t x1, uint32_t x2,
+  ///         uint32_t outstep)
+  ///
+  llvm::Function *createEmptyExpandedForEachKernel(llvm::StringRef OldName) {
+    llvm::Function *ExpandedFunction =
+      llvm::Function::Create(ExpandedForEachType,
+                             llvm::GlobalValue::ExternalLinkage,
+                             OldName + ".expand", Module);
+    bccAssert(ExpandedFunction->arg_size() == kNumExpandedForeachParams);
+    llvm::Function::arg_iterator AI = ExpandedFunction->arg_begin();
+    (AI++)->setName("p");
+    (AI++)->setName("x1");
+    (AI++)->setName("x2");
+    (AI++)->setName("arg_outstep");
+    llvm::BasicBlock *Begin = llvm::BasicBlock::Create(*Context, "Begin",
+                                                       ExpandedFunction);
+    llvm::IRBuilder<> Builder(Begin);
+    Builder.CreateRetVoid();
+    return ExpandedFunction;
+  }
+
+  // Create skeleton of a general reduce kernel's expanded accumulator.
+  //
+  // This creates a function with the following signature:
+  //
+  //  void @func.expand(%RsExpandKernelDriverInfoPfx* nocapture %p,
+  //                    i32 %x1, i32 %x2, accumType* nocapture %accum)
+  //
+  llvm::Function *createEmptyExpandedReduceAccumulator(llvm::StringRef OldName,
+                                                       llvm::Type *AccumArgTy) {
+    llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
+    llvm::Type *VoidTy = llvm::Type::getVoidTy(*Context);
+    llvm::FunctionType *ExpandedReduceAccumulatorType =
+        llvm::FunctionType::get(VoidTy,
+                                {RsExpandKernelDriverInfoPfxTy->getPointerTo(),
+                                 Int32Ty, Int32Ty, AccumArgTy}, false);
+    llvm::Function *FnExpandedAccumulator =
+      llvm::Function::Create(ExpandedReduceAccumulatorType,
+                             llvm::GlobalValue::ExternalLinkage,
+                             OldName + ".expand", Module);
+    bccAssert(FnExpandedAccumulator->arg_size() == kNumExpandedReduceAccumulatorParams);
+
+    llvm::Function::arg_iterator AI = FnExpandedAccumulator->arg_begin();
+
+    using llvm::Attribute;
+
+    llvm::Argument *Arg_p = &(*AI++);
+    Arg_p->setName("p");
+    Arg_p->addAttr(llvm::AttributeSet::get(*Context, Arg_p->getArgNo() + 1,
+                                           llvm::makeArrayRef(Attribute::NoCapture)));
+
+    llvm::Argument *Arg_x1 = &(*AI++);
+    Arg_x1->setName("x1");
+
+    llvm::Argument *Arg_x2 = &(*AI++);
+    Arg_x2->setName("x2");
+
+    llvm::Argument *Arg_accum = &(*AI++);
+    Arg_accum->setName("accum");
+    Arg_accum->addAttr(llvm::AttributeSet::get(*Context, Arg_accum->getArgNo() + 1,
+                                               llvm::makeArrayRef(Attribute::NoCapture)));
+
+    llvm::BasicBlock *Begin = llvm::BasicBlock::Create(*Context, "Begin",
+                                                       FnExpandedAccumulator);
+    llvm::IRBuilder<> Builder(Begin);
+    Builder.CreateRetVoid();
+
+    return FnExpandedAccumulator;
+  }
+
+  /// @brief Create an empty loop
+  ///
+  /// Create a loop of the form:
+  ///
+  /// for (i = LowerBound; i < UpperBound; i++)
+  ///   ;
+  ///
+  /// After the loop has been created, the builder is set such that
+  /// instructions can be added to the loop body.
+  ///
+  /// @param Builder The builder to use to build this loop. The current
+  ///                position of the builder is the position the loop
+  ///                will be inserted.
+  /// @param LowerBound The first value of the loop iterator
+  /// @param UpperBound The maximal value of the loop iterator
+  /// @param LoopIV A reference that will be set to the loop iterator.
+  /// @return The BasicBlock that will be executed after the loop.
+  llvm::BasicBlock *createLoop(llvm::IRBuilder<> &Builder,
+                               llvm::Value *LowerBound,
+                               llvm::Value *UpperBound,
+                               llvm::Value **LoopIV) {
+    bccAssert(LowerBound->getType() == UpperBound->getType());
+
+    llvm::BasicBlock *CondBB, *AfterBB, *HeaderBB;
+    llvm::Value *Cond, *IVNext, *IV, *IVVar;
+
+    CondBB = Builder.GetInsertBlock();
+    AfterBB = llvm::SplitBlock(CondBB, &*Builder.GetInsertPoint(), nullptr, nullptr);
+    HeaderBB = llvm::BasicBlock::Create(*Context, "Loop", CondBB->getParent());
+
+    CondBB->getTerminator()->eraseFromParent();
+    Builder.SetInsertPoint(CondBB);
+
+    // decltype(LowerBound) *ivvar = alloca(sizeof(int))
+    // *ivvar = LowerBound
+    IVVar = Builder.CreateAlloca(LowerBound->getType(), nullptr, BCC_INDEX_VAR_NAME);
+    Builder.CreateStore(LowerBound, IVVar);
+
+    // if (LowerBound < Upperbound)
+    //   goto LoopHeader
+    // else
+    //   goto AfterBB
+    Cond = Builder.CreateICmpULT(LowerBound, UpperBound);
+    Builder.CreateCondBr(Cond, HeaderBB, AfterBB);
+
+    // LoopHeader:
+    //   iv = *ivvar
+    //   <insertion point here>
+    //   iv.next = iv + 1
+    //   *ivvar = iv.next
+    //   if (iv.next < Upperbound)
+    //     goto LoopHeader
+    //   else
+    //     goto AfterBB
+    // AfterBB:
+    Builder.SetInsertPoint(HeaderBB);
+    IV = Builder.CreateLoad(IVVar, "X");
+    IVNext = Builder.CreateNUWAdd(IV, Builder.getInt32(1));
+    Builder.CreateStore(IVNext, IVVar);
+    Cond = Builder.CreateICmpULT(IVNext, UpperBound);
+    Builder.CreateCondBr(Cond, HeaderBB, AfterBB);
+    AfterBB->setName("Exit");
+    Builder.SetInsertPoint(llvm::cast<llvm::Instruction>(IVNext));
+
+    // Record information about this loop.
+    *LoopIV = IV;
+    return AfterBB;
+  }
+
+  // Finish building the outgoing argument list for calling a ForEach-able function.
+  //
+  // ArgVector - on input, the non-special arguments
+  //             on output, the non-special arguments combined with the special arguments
+  //               from SpecialArgVector
+  // SpecialArgVector - special arguments (from ExpandSpecialArguments())
+  // SpecialArgContextIdx - return value of ExpandSpecialArguments()
+  //                          (position of context argument in SpecialArgVector)
+  // CalleeFunction - the ForEach-able function being called
+  // Builder - for inserting code into the caller function
+  template<unsigned int ArgVectorLen, unsigned int SpecialArgVectorLen>
+  void finishArgList(      llvm::SmallVector<llvm::Value *, ArgVectorLen>        &ArgVector,
+                     const llvm::SmallVector<llvm::Value *, SpecialArgVectorLen> &SpecialArgVector,
+                     const int SpecialArgContextIdx,
+                     const llvm::Function &CalleeFunction,
+                     llvm::IRBuilder<> &CallerBuilder) {
+    /* The context argument (if any) is a pointer to an opaque user-visible type that differs from
+     * the RsExpandKernelDriverInfoPfx type used in the function we are generating (although the
+     * two types represent the same thing).  Therefore, we must introduce a pointer cast when
+     * generating a call to the kernel function.
+     */
+    const int ArgContextIdx =
+        SpecialArgContextIdx >= 0 ? (ArgVector.size() + SpecialArgContextIdx) : SpecialArgContextIdx;
+    ArgVector.append(SpecialArgVector.begin(), SpecialArgVector.end());
+    if (ArgContextIdx >= 0) {
+      llvm::Type *ContextArgType = nullptr;
+      int ArgIdx = ArgContextIdx;
+      for (const auto &Arg : CalleeFunction.getArgumentList()) {
+        if (!ArgIdx--) {
+          ContextArgType = Arg.getType();
+          break;
+        }
+      }
+      bccAssert(ContextArgType);
+      ArgVector[ArgContextIdx] = CallerBuilder.CreatePointerCast(ArgVector[ArgContextIdx], ContextArgType);
+    }
+  }
+
+  // GEPHelper() returns a SmallVector of values suitable for passing
+  // to IRBuilder::CreateGEP(), and SmallGEPIndices is a typedef for
+  // the returned data type. It is sized so that the SmallVector
+  // returned by GEPHelper() never needs to do a heap allocation for
+  // any list of GEP indices it encounters in the code.
+  typedef llvm::SmallVector<llvm::Value *, 3> SmallGEPIndices;
+
+  // Helper for turning a list of constant integer GEP indices into a
+  // SmallVector of llvm::Value*. The return value is suitable for
+  // passing to a GetElementPtrInst constructor or IRBuilder::CreateGEP().
+  //
+  // Inputs:
+  //   I32Args should be integers which represent the index arguments
+  //   to a GEP instruction.
+  //
+  // Returns:
+  //   Returns a SmallVector of ConstantInts.
+  SmallGEPIndices GEPHelper(const std::initializer_list<int32_t> I32Args) {
+    SmallGEPIndices Out(I32Args.size());
+    llvm::IntegerType *I32Ty = llvm::Type::getInt32Ty(*Context);
+    std::transform(I32Args.begin(), I32Args.end(), Out.begin(),
+                   [I32Ty](int32_t Arg) { return llvm::ConstantInt::get(I32Ty, Arg); });
+    return Out;
+  }
+
+public:
+  explicit RSKernelExpandPass(bool pEnableStepOpt = true)
+      : ModulePass(ID), Module(nullptr), Context(nullptr),
+        mEnableStepOpt(pEnableStepOpt) {
+
+  }
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    // This pass does not use any other analysis passes, but it does
+    // add/wrap the existing functions in the module (thus altering the CFG).
+  }
+
+  // Build contribution to outgoing argument list for calling a
+  // ForEach-able function or a general reduction accumulator
+  // function, based on the special parameters of that function.
+  //
+  // Signature - metadata bits for the signature of the callee
+  // X, Arg_p - values derived directly from expanded function,
+  //            suitable for computing arguments for the callee
+  // CalleeArgs - contribution is accumulated here
+  // Bump - invoked once for each contributed outgoing argument
+  // LoopHeaderInsertionPoint - an Instruction in the loop header, before which
+  //                            this function can insert loop-invariant loads
+  //
+  // Return value is the (zero-based) position of the context (Arg_p)
+  // argument in the CalleeArgs vector, or a negative value if the
+  // context argument is not placed in the CalleeArgs vector.
+  int ExpandSpecialArguments(uint32_t Signature,
+                             llvm::Value *X,
+                             llvm::Value *Arg_p,
+                             llvm::IRBuilder<> &Builder,
+                             llvm::SmallVector<llvm::Value*, 8> &CalleeArgs,
+                             const std::function<void ()> &Bump,
+                             llvm::Instruction *LoopHeaderInsertionPoint) {
+
+    bccAssert(CalleeArgs.empty());
+
+    int Return = -1;
+    if (bcinfo::MetadataExtractor::hasForEachSignatureCtxt(Signature)) {
+      CalleeArgs.push_back(Arg_p);
+      Bump();
+      Return = CalleeArgs.size() - 1;
+    }
+
+    if (bcinfo::MetadataExtractor::hasForEachSignatureX(Signature)) {
+      CalleeArgs.push_back(X);
+      Bump();
+    }
+
+    if (bcinfo::MetadataExtractor::hasForEachSignatureY(Signature) ||
+        bcinfo::MetadataExtractor::hasForEachSignatureZ(Signature)) {
+      bccAssert(LoopHeaderInsertionPoint);
+
+      // Y and Z are loop invariant, so they can be hoisted out of the
+      // loop. Set the IRBuilder insertion point to the loop header.
+      auto OldInsertionPoint = Builder.saveIP();
+      Builder.SetInsertPoint(LoopHeaderInsertionPoint);
+
+      if (bcinfo::MetadataExtractor::hasForEachSignatureY(Signature)) {
+        SmallGEPIndices YValueGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldCurrent,
+          RsLaunchDimensionsFieldY}));
+        llvm::Value *YAddr = Builder.CreateInBoundsGEP(Arg_p, YValueGEP, "Y.gep");
+        CalleeArgs.push_back(Builder.CreateLoad(YAddr, "Y"));
+        Bump();
+      }
+
+      if (bcinfo::MetadataExtractor::hasForEachSignatureZ(Signature)) {
+        SmallGEPIndices ZValueGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldCurrent,
+          RsLaunchDimensionsFieldZ}));
+        llvm::Value *ZAddr = Builder.CreateInBoundsGEP(Arg_p, ZValueGEP, "Z.gep");
+        CalleeArgs.push_back(Builder.CreateLoad(ZAddr, "Z"));
+        Bump();
+      }
+
+      Builder.restoreIP(OldInsertionPoint);
+    }
+
+    return Return;
+  }
+
+  // Generate loop-invariant input processing setup code for an expanded
+  // ForEach-able function or an expanded general reduction accumulator
+  // function.
+  //
+  // LoopHeader - block at the end of which the setup code will be inserted
+  // Arg_p - RSKernelDriverInfo pointer passed to the expanded function
+  // TBAAPointer - metadata for marking loads of pointer values out of RSKernelDriverInfo
+  // ArgIter - iterator pointing to first input of the UNexpanded function
+  // NumInputs - number of inputs (NOT number of ARGUMENTS)
+  //
+  // InTypes[] - this function saves input type, they will be used in ExpandInputsBody().
+  // InBufPtrs[] - this function sets each array element to point to the first cell / byte
+  //               (byte for x86, cell for other platforms) of the corresponding input allocation
+  // InStructTempSlots[] - this function sets each array element either to nullptr
+  //                       or to the result of an alloca (for the case where the
+  //                       calling convention dictates that a value must be passed
+  //                       by reference, and so we need a stacked temporary to hold
+  //                       a copy of that value)
+  void ExpandInputsLoopInvariant(llvm::IRBuilder<> &Builder, llvm::BasicBlock *LoopHeader,
+                                 llvm::Value *Arg_p,
+                                 llvm::MDNode *TBAAPointer,
+                                 llvm::Function::arg_iterator ArgIter,
+                                 const size_t NumInputs,
+                                 llvm::SmallVectorImpl<llvm::Type *> &InTypes,
+                                 llvm::SmallVectorImpl<llvm::Value *> &InBufPtrs,
+                                 llvm::SmallVectorImpl<llvm::Value *> &InStructTempSlots) {
+    bccAssert(NumInputs <= RS_KERNEL_INPUT_LIMIT);
+
+    // Extract information about input slots. The work done
+    // here is loop-invariant, so we can hoist the operations out of the loop.
+    auto OldInsertionPoint = Builder.saveIP();
+    Builder.SetInsertPoint(LoopHeader->getTerminator());
+
+    for (size_t InputIndex = 0; InputIndex < NumInputs; ++InputIndex, ArgIter++) {
+      llvm::Type *InType = ArgIter->getType();
+
+      /*
+       * AArch64 calling conventions dictate that structs of sufficient size
+       * get passed by pointer instead of passed by value.  This, combined
+       * with the fact that we don't allow kernels to operate on pointer
+       * data means that if we see a kernel with a pointer parameter we know
+       * that it is a struct input that has been promoted.  As such we don't
+       * need to convert its type to a pointer.  Later we will need to know
+       * to create a temporary copy on the stack, so we save this information
+       * in InStructTempSlots.
+       */
+      if (auto PtrType = llvm::dyn_cast<llvm::PointerType>(InType)) {
+        llvm::Type *ElementType = PtrType->getElementType();
+        InStructTempSlots.push_back(Builder.CreateAlloca(ElementType, nullptr,
+                                                         "input_struct_slot"));
+      } else {
+        InType = InType->getPointerTo();
+        InStructTempSlots.push_back(nullptr);
+      }
+
+      SmallGEPIndices InBufPtrGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldInPtr,
+                                             static_cast<int32_t>(InputIndex)}));
+      llvm::Value    *InBufPtrAddr = Builder.CreateInBoundsGEP(Arg_p, InBufPtrGEP, "input_buf.gep");
+      llvm::LoadInst *InBufPtr = Builder.CreateLoad(InBufPtrAddr, "input_buf");
+
+      llvm::Value *CastInBufPtr = nullptr;
+      if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
+        CastInBufPtr = Builder.CreatePointerCast(InBufPtr, InType, "casted_in");
+      } else {
+        // The disagreement between module and x86 target machine datalayout
+        // causes mismatched input/output data offset between slang reflected
+        // code and bcc codegen for GetElementPtr. To solve this issue, skip the
+        // cast to InType and leave CastInBufPtr as an int8_t*.  The buffer is
+        // later indexed with an explicit byte offset computed based on
+        // X86_CUSTOM_DL_STRING and then bitcast it to actual input type.
+        CastInBufPtr = InBufPtr;
+      }
+
+      if (gEnableRsTbaa) {
+        InBufPtr->setMetadata("tbaa", TBAAPointer);
+      }
+
+      InTypes.push_back(InType);
+      InBufPtrs.push_back(CastInBufPtr);
+    }
+
+    Builder.restoreIP(OldInsertionPoint);
+  }
+
+  // Generate loop-varying input processing code for an expanded ForEach-able function
+  // or an expanded general reduction accumulator function.  Also, for the call to the
+  // UNexpanded function, collect the portion of the argument list corresponding to the
+  // inputs.
+  //
+  // Arg_x1 - first X coordinate to be processed by the expanded function
+  // TBAAAllocation - metadata for marking loads of input values out of allocations
+  // NumInputs -- number of inputs (NOT number of ARGUMENTS)
+  // InTypes[] - this function uses the saved input types in ExpandInputsLoopInvariant()
+  //             to convert the pointer of byte InPtr to its real type.
+  // InBufPtrs[] - this function consumes the information produced by ExpandInputsLoopInvariant()
+  // InStructTempSlots[] - this function consumes the information produced by ExpandInputsLoopInvariant()
+  // IndVar - value of loop induction variable (X coordinate) for a given loop iteration
+  //
+  // RootArgs - this function sets this to the list of outgoing argument values corresponding
+  //            to the inputs
+  void ExpandInputsBody(llvm::IRBuilder<> &Builder,
+                        llvm::Value *Arg_x1,
+                        llvm::MDNode *TBAAAllocation,
+                        const size_t NumInputs,
+                        const llvm::SmallVectorImpl<llvm::Type *> &InTypes,
+                        const llvm::SmallVectorImpl<llvm::Value *> &InBufPtrs,
+                        const llvm::SmallVectorImpl<llvm::Value *> &InStructTempSlots,
+                        llvm::Value *IndVar,
+                        llvm::SmallVectorImpl<llvm::Value *> &RootArgs) {
+    llvm::Value *Offset = Builder.CreateSub(IndVar, Arg_x1);
+    llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
+
+    for (size_t Index = 0; Index < NumInputs; ++Index) {
+
+      llvm::Value *InPtr = nullptr;
+      if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
+        InPtr = Builder.CreateInBoundsGEP(InBufPtrs[Index], Offset);
+      } else {
+        // Treat x86 input buffer as byte[], get indexed pointer with explicit
+        // byte offset computed using a datalayout based on
+        // X86_CUSTOM_DL_STRING, then bitcast it to actual input type.
+        llvm::DataLayout DL(X86_CUSTOM_DL_STRING);
+        llvm::Type *InTy = InTypes[Index];
+        uint64_t InStep = DL.getTypeAllocSize(InTy->getPointerElementType());
+        llvm::Value *OffsetInBytes = Builder.CreateMul(Offset, llvm::ConstantInt::get(Int32Ty, InStep));
+        InPtr = Builder.CreateInBoundsGEP(InBufPtrs[Index], OffsetInBytes);
+        InPtr = Builder.CreatePointerCast(InPtr, InTy);
+      }
+
+      llvm::Value *Input;
+      llvm::LoadInst *InputLoad = Builder.CreateLoad(InPtr, "input");
+
+      if (gEnableRsTbaa) {
+        InputLoad->setMetadata("tbaa", TBAAAllocation);
+      }
+
+      if (llvm::Value *TemporarySlot = InStructTempSlots[Index]) {
+        // Pass a pointer to a temporary on the stack, rather than
+        // passing a pointer to the original value. We do not want
+        // the kernel to potentially modify the input data.
+
+        // Note: don't annotate with TBAA, since the kernel might
+        // have its own TBAA annotations for the pointer argument.
+        Builder.CreateStore(InputLoad, TemporarySlot);
+        Input = TemporarySlot;
+      } else {
+        Input = InputLoad;
+      }
+
+      RootArgs.push_back(Input);
+    }
+  }
+
+  /* Performs the actual optimization on a selected function. On success, the
+   * Module will contain a new function of the name "<NAME>.expand" that
+   * invokes <NAME>() in a loop with the appropriate parameters.
+   */
+  bool ExpandOldStyleForEach(llvm::Function *Function, uint32_t Signature) {
+    ALOGV("Expanding ForEach-able Function %s",
+          Function->getName().str().c_str());
+
+    if (!Signature) {
+      Signature = getRootSignature(Function);
+      if (!Signature) {
+        // We couldn't determine how to expand this function based on its
+        // function signature.
+        return false;
+      }
+    }
+
+    llvm::DataLayout DL(Module);
+    if (Module->getTargetTriple() == DEFAULT_X86_TRIPLE_STRING) {
+      DL.reset(X86_CUSTOM_DL_STRING);
+    }
+
+    llvm::Function *ExpandedFunction =
+      createEmptyExpandedForEachKernel(Function->getName());
+
+    /*
+     * Extract the expanded function's parameters.  It is guaranteed by
+     * createEmptyExpandedForEachKernel that there will be four parameters.
+     */
+
+    bccAssert(ExpandedFunction->arg_size() == kNumExpandedForeachParams);
+
+    llvm::Function::arg_iterator ExpandedFunctionArgIter =
+      ExpandedFunction->arg_begin();
+
+    llvm::Value *Arg_p       = &*(ExpandedFunctionArgIter++);
+    llvm::Value *Arg_x1      = &*(ExpandedFunctionArgIter++);
+    llvm::Value *Arg_x2      = &*(ExpandedFunctionArgIter++);
+    llvm::Value *Arg_outstep = &*(ExpandedFunctionArgIter);
+
+    llvm::Value *InStep  = nullptr;
+    llvm::Value *OutStep = nullptr;
+
+    // Construct the actual function body.
+    llvm::IRBuilder<> Builder(&*ExpandedFunction->getEntryBlock().begin());
+
+    // Collect and construct the arguments for the kernel().
+    // Note that we load any loop-invariant arguments before entering the Loop.
+    llvm::Function::arg_iterator FunctionArgIter = Function->arg_begin();
+
+    llvm::Type  *InTy      = nullptr;
+    llvm::Value *InBufPtr = nullptr;
+    if (bcinfo::MetadataExtractor::hasForEachSignatureIn(Signature)) {
+      SmallGEPIndices InStepGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldInStride, 0}));
+      llvm::LoadInst *InStepArg  = Builder.CreateLoad(
+        Builder.CreateInBoundsGEP(Arg_p, InStepGEP, "instep_addr.gep"), "instep_addr");
+
+      InTy = (FunctionArgIter++)->getType();
+      InStep = getStepValue(&DL, InTy, InStepArg);
+
+      InStep->setName("instep");
+
+      SmallGEPIndices InputAddrGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldInPtr, 0}));
+      InBufPtr = Builder.CreateLoad(
+        Builder.CreateInBoundsGEP(Arg_p, InputAddrGEP, "input_buf.gep"), "input_buf");
+    }
+
+    llvm::Type *OutTy = nullptr;
+    llvm::Value *OutBasePtr = nullptr;
+    if (bcinfo::MetadataExtractor::hasForEachSignatureOut(Signature)) {
+      OutTy = (FunctionArgIter++)->getType();
+      OutStep = getStepValue(&DL, OutTy, Arg_outstep);
+      OutStep->setName("outstep");
+      SmallGEPIndices OutBaseGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldOutPtr, 0}));
+      OutBasePtr = Builder.CreateLoad(Builder.CreateInBoundsGEP(Arg_p, OutBaseGEP, "out_buf.gep"));
+    }
+
+    llvm::Value *UsrData = nullptr;
+    if (bcinfo::MetadataExtractor::hasForEachSignatureUsrData(Signature)) {
+      llvm::Type *UsrDataTy = (FunctionArgIter++)->getType();
+      llvm::Value *UsrDataPointerAddr = Builder.CreateStructGEP(nullptr, Arg_p, RsExpandKernelDriverInfoPfxFieldUsr);
+      UsrData = Builder.CreatePointerCast(Builder.CreateLoad(UsrDataPointerAddr), UsrDataTy);
+      UsrData->setName("UsrData");
+    }
+
+    llvm::BasicBlock *LoopHeader = Builder.GetInsertBlock();
+    llvm::Value *IV;
+    createLoop(Builder, Arg_x1, Arg_x2, &IV);
+
+    llvm::SmallVector<llvm::Value*, 8> CalleeArgs;
+    const int CalleeArgsContextIdx = ExpandSpecialArguments(Signature, IV, Arg_p, Builder, CalleeArgs,
+                                                            [&FunctionArgIter]() { FunctionArgIter++; },
+                                                            LoopHeader->getTerminator());
+
+    bccAssert(FunctionArgIter == Function->arg_end());
+
+    // Populate the actual call to kernel().
+    llvm::SmallVector<llvm::Value*, 8> RootArgs;
+
+    llvm::Value *InPtr  = nullptr;
+    llvm::Value *OutPtr = nullptr;
+
+    // Calculate the current input and output pointers
+    //
+    // We always calculate the input/output pointers with a GEP operating on i8
+    // values and only cast at the very end to OutTy. This is because the step
+    // between two values is given in bytes.
+    //
+    // TODO: We could further optimize the output by using a GEP operation of
+    // type 'OutTy' in cases where the element type of the allocation allows.
+    if (OutBasePtr) {
+      llvm::Value *OutOffset = Builder.CreateSub(IV, Arg_x1);
+      OutOffset = Builder.CreateMul(OutOffset, OutStep);
+      OutPtr = Builder.CreateInBoundsGEP(OutBasePtr, OutOffset);
+      OutPtr = Builder.CreatePointerCast(OutPtr, OutTy);
+    }
+
+    if (InBufPtr) {
+      llvm::Value *InOffset = Builder.CreateSub(IV, Arg_x1);
+      InOffset = Builder.CreateMul(InOffset, InStep);
+      InPtr = Builder.CreateInBoundsGEP(InBufPtr, InOffset);
+      InPtr = Builder.CreatePointerCast(InPtr, InTy);
+    }
+
+    if (InPtr) {
+      RootArgs.push_back(InPtr);
+    }
+
+    if (OutPtr) {
+      RootArgs.push_back(OutPtr);
+    }
+
+    if (UsrData) {
+      RootArgs.push_back(UsrData);
+    }
+
+    finishArgList(RootArgs, CalleeArgs, CalleeArgsContextIdx, *Function, Builder);
+
+    Builder.CreateCall(Function, RootArgs);
+
+    return true;
+  }
+
+  /* Expand a pass-by-value foreach kernel.
+   */
+  bool ExpandForEach(llvm::Function *Function, uint32_t Signature) {
+    bccAssert(bcinfo::MetadataExtractor::hasForEachSignatureKernel(Signature));
+    ALOGV("Expanding kernel Function %s", Function->getName().str().c_str());
+
+    // TODO: Refactor this to share functionality with ExpandOldStyleForEach.
+    llvm::DataLayout DL(Module);
+    if (Module->getTargetTriple() == DEFAULT_X86_TRIPLE_STRING) {
+      DL.reset(X86_CUSTOM_DL_STRING);
+    }
+    llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
+
+    llvm::Function *ExpandedFunction =
+      createEmptyExpandedForEachKernel(Function->getName());
+
+    /*
+     * Extract the expanded function's parameters.  It is guaranteed by
+     * createEmptyExpandedForEachKernel that there will be four parameters.
+     */
+
+    bccAssert(ExpandedFunction->arg_size() == kNumExpandedForeachParams);
+
+    llvm::Function::arg_iterator ExpandedFunctionArgIter =
+      ExpandedFunction->arg_begin();
+
+    llvm::Value *Arg_p       = &*(ExpandedFunctionArgIter++);
+    llvm::Value *Arg_x1      = &*(ExpandedFunctionArgIter++);
+    llvm::Value *Arg_x2      = &*(ExpandedFunctionArgIter++);
+    // Arg_outstep is not used by expanded new-style forEach kernels.
+
+    // Construct the actual function body.
+    llvm::IRBuilder<> Builder(&*ExpandedFunction->getEntryBlock().begin());
+
+    // Create TBAA meta-data.
+    llvm::MDNode *TBAARenderScriptDistinct, *TBAARenderScript,
+                 *TBAAAllocation, *TBAAPointer;
+    llvm::MDBuilder MDHelper(*Context);
+
+    TBAARenderScriptDistinct =
+      MDHelper.createTBAARoot(kRenderScriptTBAARootName);
+    TBAARenderScript = MDHelper.createTBAANode(kRenderScriptTBAANodeName,
+        TBAARenderScriptDistinct);
+    TBAAAllocation = MDHelper.createTBAAScalarTypeNode("allocation",
+                                                       TBAARenderScript);
+    TBAAAllocation = MDHelper.createTBAAStructTagNode(TBAAAllocation,
+                                                      TBAAAllocation, 0);
+    TBAAPointer = MDHelper.createTBAAScalarTypeNode("pointer",
+                                                    TBAARenderScript);
+    TBAAPointer = MDHelper.createTBAAStructTagNode(TBAAPointer, TBAAPointer, 0);
+
+    /*
+     * Collect and construct the arguments for the kernel().
+     *
+     * Note that we load any loop-invariant arguments before entering the Loop.
+     */
+    size_t NumRemainingInputs = Function->arg_size();
+
+    // No usrData parameter on kernels.
+    bccAssert(
+        !bcinfo::MetadataExtractor::hasForEachSignatureUsrData(Signature));
+
+    llvm::Function::arg_iterator ArgIter = Function->arg_begin();
+
+    // Check the return type
+    llvm::Type     *OutTy            = nullptr;
+    llvm::LoadInst *OutBasePtr       = nullptr;
+    llvm::Value    *CastedOutBasePtr = nullptr;
+
+    bool PassOutByPointer = false;
+
+    if (bcinfo::MetadataExtractor::hasForEachSignatureOut(Signature)) {
+      llvm::Type *OutBaseTy = Function->getReturnType();
+
+      if (OutBaseTy->isVoidTy()) {
+        PassOutByPointer = true;
+        OutTy = ArgIter->getType();
+
+        ArgIter++;
+        --NumRemainingInputs;
+      } else {
+        // We don't increment Args, since we are using the actual return type.
+        OutTy = OutBaseTy->getPointerTo();
+      }
+
+      SmallGEPIndices OutBaseGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldOutPtr, 0}));
+      OutBasePtr = Builder.CreateLoad(Builder.CreateInBoundsGEP(Arg_p, OutBaseGEP, "out_buf.gep"));
+
+      if (gEnableRsTbaa) {
+        OutBasePtr->setMetadata("tbaa", TBAAPointer);
+      }
+
+      if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
+        CastedOutBasePtr = Builder.CreatePointerCast(OutBasePtr, OutTy, "casted_out");
+      } else {
+        // The disagreement between module and x86 target machine datalayout
+        // causes mismatched input/output data offset between slang reflected
+        // code and bcc codegen for GetElementPtr. To solve this issue, skip the
+        // cast to OutTy and leave CastedOutBasePtr as an int8_t*.  The buffer
+        // is later indexed with an explicit byte offset computed based on
+        // X86_CUSTOM_DL_STRING and then bitcast it to actual output type.
+        CastedOutBasePtr = OutBasePtr;
+      }
+    }
+
+    llvm::SmallVector<llvm::Type*,  8> InTypes;
+    llvm::SmallVector<llvm::Value*, 8> InBufPtrs;
+    llvm::SmallVector<llvm::Value*, 8> InStructTempSlots;
+
+    bccAssert(NumRemainingInputs <= RS_KERNEL_INPUT_LIMIT);
+
+    // Create the loop structure.
+    llvm::BasicBlock *LoopHeader = Builder.GetInsertBlock();
+    llvm::Value *IV;
+    createLoop(Builder, Arg_x1, Arg_x2, &IV);
+
+    llvm::SmallVector<llvm::Value*, 8> CalleeArgs;
+    const int CalleeArgsContextIdx =
+      ExpandSpecialArguments(Signature, IV, Arg_p, Builder, CalleeArgs,
+                             [&NumRemainingInputs]() { --NumRemainingInputs; },
+                             LoopHeader->getTerminator());
+
+    // After ExpandSpecialArguments() gets called, NumRemainingInputs
+    // counts the number of arguments to the kernel that correspond to
+    // an array entry from the InPtr field of the DriverInfo
+    // structure.
+    const size_t NumInPtrArguments = NumRemainingInputs;
+
+    if (NumInPtrArguments > 0) {
+      ExpandInputsLoopInvariant(Builder, LoopHeader, Arg_p, TBAAPointer, ArgIter, NumInPtrArguments,
+                                InTypes, InBufPtrs, InStructTempSlots);
+    }
+
+    // Populate the actual call to kernel().
+    llvm::SmallVector<llvm::Value*, 8> RootArgs;
+
+    // Calculate the current input and output pointers.
+
+    // Output
+
+    llvm::Value *OutPtr = nullptr;
+    if (CastedOutBasePtr) {
+      llvm::Value *OutOffset = Builder.CreateSub(IV, Arg_x1);
+
+      if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
+        OutPtr = Builder.CreateInBoundsGEP(CastedOutBasePtr, OutOffset);
+      } else {
+        // Treat x86 output buffer as byte[], get indexed pointer with explicit
+        // byte offset computed using a datalayout based on
+        // X86_CUSTOM_DL_STRING, then bitcast it to actual output type.
+        uint64_t OutStep = DL.getTypeAllocSize(OutTy->getPointerElementType());
+        llvm::Value *OutOffsetInBytes = Builder.CreateMul(OutOffset, llvm::ConstantInt::get(Int32Ty, OutStep));
+        OutPtr = Builder.CreateInBoundsGEP(CastedOutBasePtr, OutOffsetInBytes);
+        OutPtr = Builder.CreatePointerCast(OutPtr, OutTy);
+      }
+
+      if (PassOutByPointer) {
+        RootArgs.push_back(OutPtr);
+      }
+    }
+
+    // Inputs
+
+    if (NumInPtrArguments > 0) {
+      ExpandInputsBody(Builder, Arg_x1, TBAAAllocation, NumInPtrArguments,
+                       InTypes, InBufPtrs, InStructTempSlots, IV, RootArgs);
+    }
+
+    finishArgList(RootArgs, CalleeArgs, CalleeArgsContextIdx, *Function, Builder);
+
+    llvm::Value *RetVal = Builder.CreateCall(Function, RootArgs);
+
+    if (OutPtr && !PassOutByPointer) {
+      RetVal->setName("call.result");
+      llvm::StoreInst *Store = Builder.CreateStore(RetVal, OutPtr);
+      if (gEnableRsTbaa) {
+        Store->setMetadata("tbaa", TBAAAllocation);
+      }
+    }
+
+    return true;
+  }
+
+  // Certain categories of functions that make up a general
+  // reduce-style kernel are called directly from the driver with no
+  // expansion needed.  For a function in such a category, we need to
+  // promote linkage from static to external, to ensure that the
+  // function is visible to the driver in the dynamic symbol table.
+  // This promotion is safe because we don't have any kind of cross
+  // translation unit linkage model (except for linking against
+  // RenderScript libraries), so we do not risk name clashes.
+  bool PromoteReduceFunction(const char *Name, FunctionSet &PromotedFunctions) {
+    if (!Name)  // a presumably-optional function that is not present
+      return false;
+
+    llvm::Function *Fn = Module->getFunction(Name);
+    bccAssert(Fn != nullptr);
+    if (PromotedFunctions.insert(Fn).second) {
+      bccAssert(Fn->getLinkage() == llvm::GlobalValue::InternalLinkage);
+      Fn->setLinkage(llvm::GlobalValue::ExternalLinkage);
+      return true;
+    }
+
+    return false;
+  }
+
+  // Expand the accumulator function for a general reduce-style kernel.
+  //
+  // The input is a function of the form
+  //
+  //   define void @func(accumType* %accum, foo1 in1[, ... fooN inN] [, special arguments])
+  //
+  // where all arguments except the first are the same as for a foreach kernel.
+  //
+  // The input accumulator function gets expanded into a function of the form
+  //
+  //   define void @func.expand(%RsExpandKernelDriverInfoPfx* %p, i32 %x1, i32 %x2, accumType* %accum)
+  //
+  // which performs a serial accumulaion of elements [x1, x2) into *%accum.
+  //
+  // In pseudocode, @func.expand does:
+  //
+  //   for (i = %x1; i < %x2; ++i) {
+  //     func(%accum,
+  //          *((foo1 *)p->inPtr[0] + i)[, ... *((fooN *)p->inPtr[N-1] + i)
+  //          [, p] [, i] [, p->current.y] [, p->current.z]);
+  //   }
+  //
+  // This is very similar to foreach kernel expansion with no output.
+  bool ExpandReduceAccumulator(llvm::Function *FnAccumulator, uint32_t Signature, size_t NumInputs) {
+    ALOGV("Expanding accumulator %s for general reduce kernel",
+          FnAccumulator->getName().str().c_str());
+
+    // Create TBAA meta-data.
+    llvm::MDNode *TBAARenderScriptDistinct, *TBAARenderScript,
+                 *TBAAAllocation, *TBAAPointer;
+    llvm::MDBuilder MDHelper(*Context);
+    TBAARenderScriptDistinct =
+      MDHelper.createTBAARoot(kRenderScriptTBAARootName);
+    TBAARenderScript = MDHelper.createTBAANode(kRenderScriptTBAANodeName,
+        TBAARenderScriptDistinct);
+    TBAAAllocation = MDHelper.createTBAAScalarTypeNode("allocation",
+                                                       TBAARenderScript);
+    TBAAAllocation = MDHelper.createTBAAStructTagNode(TBAAAllocation,
+                                                      TBAAAllocation, 0);
+    TBAAPointer = MDHelper.createTBAAScalarTypeNode("pointer",
+                                                    TBAARenderScript);
+    TBAAPointer = MDHelper.createTBAAStructTagNode(TBAAPointer, TBAAPointer, 0);
+
+    auto AccumulatorArgIter = FnAccumulator->arg_begin();
+
+    // Create empty accumulator function.
+    llvm::Function *FnExpandedAccumulator =
+        createEmptyExpandedReduceAccumulator(FnAccumulator->getName(),
+                                             (AccumulatorArgIter++)->getType());
+
+    // Extract the expanded accumulator's parameters.  It is
+    // guaranteed by createEmptyExpandedReduceAccumulator that
+    // there will be 4 parameters.
+    bccAssert(FnExpandedAccumulator->arg_size() == kNumExpandedReduceAccumulatorParams);
+    auto ExpandedAccumulatorArgIter = FnExpandedAccumulator->arg_begin();
+    llvm::Value *Arg_p     = &*(ExpandedAccumulatorArgIter++);
+    llvm::Value *Arg_x1    = &*(ExpandedAccumulatorArgIter++);
+    llvm::Value *Arg_x2    = &*(ExpandedAccumulatorArgIter++);
+    llvm::Value *Arg_accum = &*(ExpandedAccumulatorArgIter++);
+
+    // Construct the actual function body.
+    llvm::IRBuilder<> Builder(&*FnExpandedAccumulator->getEntryBlock().begin());
+
+    // Create the loop structure.
+    llvm::BasicBlock *LoopHeader = Builder.GetInsertBlock();
+    llvm::Value *IndVar;
+    createLoop(Builder, Arg_x1, Arg_x2, &IndVar);
+
+    llvm::SmallVector<llvm::Value*, 8> CalleeArgs;
+    const int CalleeArgsContextIdx =
+        ExpandSpecialArguments(Signature, IndVar, Arg_p, Builder, CalleeArgs,
+                               [](){}, LoopHeader->getTerminator());
+
+    llvm::SmallVector<llvm::Type*,  8> InTypes;
+    llvm::SmallVector<llvm::Value*, 8> InBufPtrs;
+    llvm::SmallVector<llvm::Value*, 8> InStructTempSlots;
+    ExpandInputsLoopInvariant(Builder, LoopHeader, Arg_p, TBAAPointer, AccumulatorArgIter, NumInputs,
+                              InTypes, InBufPtrs, InStructTempSlots);
+
+    // Populate the actual call to the original accumulator.
+    llvm::SmallVector<llvm::Value*, 8> RootArgs;
+    RootArgs.push_back(Arg_accum);
+    ExpandInputsBody(Builder, Arg_x1, TBAAAllocation, NumInputs, InTypes, InBufPtrs, InStructTempSlots,
+                     IndVar, RootArgs);
+    finishArgList(RootArgs, CalleeArgs, CalleeArgsContextIdx, *FnAccumulator, Builder);
+    Builder.CreateCall(FnAccumulator, RootArgs);
+
+    return true;
+  }
+
+  // Create a combiner function for a general reduce-style kernel that lacks one,
+  // by calling the accumulator function.
+  //
+  // The accumulator function must be of the form
+  //
+  //   define void @accumFn(accumType* %accum, accumType %in)
+  //
+  // A combiner function will be generated of the form
+  //
+  //   define void @accumFn.combiner(accumType* %accum, accumType* %other) {
+  //     %1 = load accumType, accumType* %other
+  //     call void @accumFn(accumType* %accum, accumType %1);
+  //   }
+  bool CreateReduceCombinerFromAccumulator(llvm::Function *FnAccumulator) {
+    ALOGV("Creating combiner from accumulator %s for general reduce kernel",
+          FnAccumulator->getName().str().c_str());
+
+    using llvm::Attribute;
+
+    bccAssert(FnAccumulator->arg_size() == 2);
+    auto AccumulatorArgIter = FnAccumulator->arg_begin();
+    llvm::Value *AccumulatorArg_accum = &*(AccumulatorArgIter++);
+    llvm::Value *AccumulatorArg_in    = &*(AccumulatorArgIter++);
+    llvm::Type *AccumulatorArgType = AccumulatorArg_accum->getType();
+    bccAssert(AccumulatorArgType->isPointerTy());
+
+    llvm::Type *VoidTy = llvm::Type::getVoidTy(*Context);
+    llvm::FunctionType *CombinerType =
+        llvm::FunctionType::get(VoidTy, { AccumulatorArgType, AccumulatorArgType }, false);
+    llvm::Function *FnCombiner =
+        llvm::Function::Create(CombinerType, llvm::GlobalValue::ExternalLinkage,
+                               nameReduceCombinerFromAccumulator(FnAccumulator->getName()),
+                               Module);
+
+    auto CombinerArgIter = FnCombiner->arg_begin();
+
+    llvm::Argument *CombinerArg_accum = &(*CombinerArgIter++);
+    CombinerArg_accum->setName("accum");
+    CombinerArg_accum->addAttr(llvm::AttributeSet::get(*Context, CombinerArg_accum->getArgNo() + 1,
+                                                       llvm::makeArrayRef(Attribute::NoCapture)));
+
+    llvm::Argument *CombinerArg_other = &(*CombinerArgIter++);
+    CombinerArg_other->setName("other");
+    CombinerArg_other->addAttr(llvm::AttributeSet::get(*Context, CombinerArg_other->getArgNo() + 1,
+                                                       llvm::makeArrayRef(Attribute::NoCapture)));
+
+    llvm::BasicBlock *BB = llvm::BasicBlock::Create(*Context, "BB", FnCombiner);
+    llvm::IRBuilder<> Builder(BB);
+
+    if (AccumulatorArg_in->getType()->isPointerTy()) {
+      // Types of sufficient size get passed by pointer-to-copy rather
+      // than passed by value.  An accumulator cannot take a pointer
+      // at the user level; so if we see a pointer here, we know that
+      // we have a pass-by-pointer-to-copy case.
+      llvm::Type *ElementType = AccumulatorArg_in->getType()->getPointerElementType();
+      llvm::Value *TempMem = Builder.CreateAlloca(ElementType, nullptr, "caller_copy");
+      Builder.CreateStore(Builder.CreateLoad(CombinerArg_other), TempMem);
+      Builder.CreateCall(FnAccumulator, { CombinerArg_accum, TempMem });
+    } else {
+      llvm::Value *TypeAdjustedOther = CombinerArg_other;
+      if (AccumulatorArgType->getPointerElementType() != AccumulatorArg_in->getType()) {
+        // Call lowering by frontend has done some type coercion
+        TypeAdjustedOther = Builder.CreatePointerCast(CombinerArg_other,
+                                                      AccumulatorArg_in->getType()->getPointerTo(),
+                                                      "cast");
+      }
+      llvm::Value *DerefOther = Builder.CreateLoad(TypeAdjustedOther);
+      Builder.CreateCall(FnAccumulator, { CombinerArg_accum, DerefOther });
+    }
+    Builder.CreateRetVoid();
+
+    return true;
+  }
+
+  /// @brief Checks if pointers to allocation internals are exposed
+  ///
+  /// This function verifies if through the parameters passed to the kernel
+  /// or through calls to the runtime library the script gains access to
+  /// pointers pointing to data within a RenderScript Allocation.
+  /// If we know we control all loads from and stores to data within
+  /// RenderScript allocations and if we know the run-time internal accesses
+  /// are all annotated with RenderScript TBAA metadata, only then we
+  /// can safely use TBAA to distinguish between generic and from-allocation
+  /// pointers.
+  bool allocPointersExposed(llvm::Module &Module) {
+    // Old style kernel function can expose pointers to elements within
+    // allocations.
+    // TODO: Extend analysis to allow simple cases of old-style kernels.
+    for (size_t i = 0; i < mExportForEachCount; ++i) {
+      const char *Name = mExportForEachNameList[i];
+      uint32_t Signature = mExportForEachSignatureList[i];
+      if (Module.getFunction(Name) &&
+          !bcinfo::MetadataExtractor::hasForEachSignatureKernel(Signature)) {
+        return true;
+      }
+    }
+
+    // Check for library functions that expose a pointer to an Allocation or
+    // that are not yet annotated with RenderScript-specific tbaa information.
+    static const std::vector<const char *> Funcs{
+      // rsGetElementAt(...)
+      "_Z14rsGetElementAt13rs_allocationj",
+      "_Z14rsGetElementAt13rs_allocationjj",
+      "_Z14rsGetElementAt13rs_allocationjjj",
+
+      // rsSetElementAt()
+      "_Z14rsSetElementAt13rs_allocationPvj",
+      "_Z14rsSetElementAt13rs_allocationPvjj",
+      "_Z14rsSetElementAt13rs_allocationPvjjj",
+
+      // rsGetElementAtYuv_uchar_Y()
+      "_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj",
+
+      // rsGetElementAtYuv_uchar_U()
+      "_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj",
+
+      // rsGetElementAtYuv_uchar_V()
+      "_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj",
+    };
+
+    for (auto FI : Funcs) {
+      llvm::Function *Function = Module.getFunction(FI);
+
+      if (!Function) {
+        ALOGE("Missing run-time function '%s'", FI);
+        return true;
+      }
+
+      if (Function->getNumUses() > 0) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  /// @brief Connect RenderScript TBAA metadata to C/C++ metadata
+  ///
+  /// The TBAA metadata used to annotate loads/stores from RenderScript
+  /// Allocations is generated in a separate TBAA tree with a
+  /// "RenderScript Distinct TBAA" root node. LLVM does assume may-alias for
+  /// all nodes in unrelated alias analysis trees. This function makes the
+  /// "RenderScript TBAA" node (which is parented by the Distinct TBAA root),
+  /// a subtree of the normal C/C++ TBAA tree aside of normal C/C++ types. With
+  /// the connected trees every access to an Allocation is resolved to
+  /// must-alias if compared to a normal C/C++ access.
+  void connectRenderScriptTBAAMetadata(llvm::Module &Module) {
+    llvm::MDBuilder MDHelper(*Context);
+    llvm::MDNode *TBAARenderScriptDistinct =
+      MDHelper.createTBAARoot("RenderScript Distinct TBAA");
+    llvm::MDNode *TBAARenderScript = MDHelper.createTBAANode(
+        "RenderScript TBAA", TBAARenderScriptDistinct);
+    llvm::MDNode *TBAARoot     = MDHelper.createTBAARoot("Simple C/C++ TBAA");
+    TBAARenderScript->replaceOperandWith(1, TBAARoot);
+  }
+
+  virtual bool runOnModule(llvm::Module &Module) {
+    bool Changed  = false;
+    this->Module  = &Module;
+    Context = &Module.getContext();
+
+    buildTypes();
+
+    bcinfo::MetadataExtractor me(&Module);
+    if (!me.extract()) {
+      ALOGE("Could not extract metadata from module!");
+      return false;
+    }
+
+    // Expand forEach_* style kernels.
+    mExportForEachCount = me.getExportForEachSignatureCount();
+    mExportForEachNameList = me.getExportForEachNameList();
+    mExportForEachSignatureList = me.getExportForEachSignatureList();
+
+    for (size_t i = 0; i < mExportForEachCount; ++i) {
+      const char *name = mExportForEachNameList[i];
+      uint32_t signature = mExportForEachSignatureList[i];
+      llvm::Function *kernel = Module.getFunction(name);
+      if (kernel) {
+        if (bcinfo::MetadataExtractor::hasForEachSignatureKernel(signature)) {
+          Changed |= ExpandForEach(kernel, signature);
+          kernel->setLinkage(llvm::GlobalValue::InternalLinkage);
+        } else if (kernel->getReturnType()->isVoidTy()) {
+          Changed |= ExpandOldStyleForEach(kernel, signature);
+          kernel->setLinkage(llvm::GlobalValue::InternalLinkage);
+        } else {
+          // There are some graphics root functions that are not
+          // expanded, but that will be called directly. For those
+          // functions, we can not set the linkage to internal.
+        }
+      }
+    }
+
+    // Process general reduce_* style functions.
+    const size_t ExportReduceCount = me.getExportReduceCount();
+    const bcinfo::MetadataExtractor::Reduce *ExportReduceList = me.getExportReduceList();
+    //   Note that functions can be shared between kernels
+    FunctionSet PromotedFunctions, ExpandedAccumulators, AccumulatorsForCombiners;
+
+    for (size_t i = 0; i < ExportReduceCount; ++i) {
+      Changed |= PromoteReduceFunction(ExportReduceList[i].mInitializerName, PromotedFunctions);
+      Changed |= PromoteReduceFunction(ExportReduceList[i].mCombinerName, PromotedFunctions);
+      Changed |= PromoteReduceFunction(ExportReduceList[i].mOutConverterName, PromotedFunctions);
+
+      // Accumulator
+      llvm::Function *accumulator = Module.getFunction(ExportReduceList[i].mAccumulatorName);
+      bccAssert(accumulator != nullptr);
+      if (ExpandedAccumulators.insert(accumulator).second)
+        Changed |= ExpandReduceAccumulator(accumulator,
+                                           ExportReduceList[i].mSignature,
+                                           ExportReduceList[i].mInputCount);
+      if (!ExportReduceList[i].mCombinerName) {
+        if (AccumulatorsForCombiners.insert(accumulator).second)
+          Changed |= CreateReduceCombinerFromAccumulator(accumulator);
+      }
+    }
+
+    if (gEnableRsTbaa && !allocPointersExposed(Module)) {
+      connectRenderScriptTBAAMetadata(Module);
+    }
+
+    return Changed;
+  }
+
+  virtual const char *getPassName() const {
+    return "forEach_* and reduce_* function expansion";
+  }
+
+}; // end RSKernelExpandPass
+
+} // end anonymous namespace
+
+char RSKernelExpandPass::ID = 0;
+static llvm::RegisterPass<RSKernelExpandPass> X("kernelexp", "Kernel Expand Pass");
+
+namespace bcc {
+
+const char BCC_INDEX_VAR_NAME[] = "rsIndex";
+
+llvm::ModulePass *
+createRSKernelExpandPass(bool pEnableStepOpt) {
+  return new RSKernelExpandPass(pEnableStepOpt);
+}
+
+} // end namespace bcc
diff --git a/libbcc/lib/Renderscript/RSScreenFunctionsPass.cpp b/libbcc/lib/Renderscript/RSScreenFunctionsPass.cpp
new file mode 100644
index 0000000..84f2c08
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSScreenFunctionsPass.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Support/Log.h"
+#include "RSStubsWhiteList.h"
+
+#include <cstdlib>
+
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Function.h>
+#include <llvm/Pass.h>
+
+namespace { // anonymous namespace
+
+// Create a Module pass that screens all the global functions in the
+// module and check if any disallowed external function is accessible
+// and potentially callable.
+class RSScreenFunctionsPass : public llvm::ModulePass {
+private:
+  static char ID;
+
+  std::vector<std::string> &whiteList = stubList;
+
+  bool isPresent(std::vector<std::string> &list, const std::string &name) {
+    auto lower = std::lower_bound(list.begin(),
+                                  list.end(),
+                                  name);
+
+    if (lower != list.end() && name.compare(*lower) == 0)
+      return true;
+    return false;
+  }
+
+  bool isLegal(llvm::Function &F) {
+    // A global function symbol is legal if
+    // a. it has a body, i.e. is not empty or
+    // b. its name starts with "llvm." or
+    // c. it is present in the whitelist
+
+    if (!F.empty())
+      return true;
+
+    llvm::StringRef FName = F.getName();
+    if (FName.startswith("llvm."))
+      return true;
+
+    if (isPresent(whiteList, FName.str()))
+      return true;
+
+    return false;
+  }
+
+public:
+  RSScreenFunctionsPass()
+    : ModulePass (ID) {
+      std::sort(whiteList.begin(), whiteList.end());
+  }
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  bool runOnModule(llvm::Module &M) override {
+    bool failed = false;
+
+    auto &FunctionList(M.getFunctionList());
+    for(auto &F: FunctionList) {
+      if (!isLegal(F)) {
+        ALOGE("Call to function %s from RenderScript is disallowed\n",
+              F.getName().str().c_str());
+        failed = true;
+      }
+    }
+
+    if (failed) {
+      llvm::report_fatal_error("Use of undefined external function");
+    }
+
+    return false;
+  }
+
+};
+
+}
+
+char RSScreenFunctionsPass::ID = 0;
+
+namespace bcc {
+
+llvm::ModulePass *
+createRSScreenFunctionsPass() {
+  return new RSScreenFunctionsPass();
+}
+
+}
diff --git a/libbcc/lib/Renderscript/RSScript.cpp b/libbcc/lib/Renderscript/RSScript.cpp
new file mode 100644
index 0000000..e04c35c
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSScript.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Renderscript/RSScript.h"
+
+#include "bcc/Assert.h"
+#include "bcc/Source.h"
+#include "bcc/Support/Log.h"
+#include "bcc/Support/CompilerConfig.h"
+
+using namespace bcc;
+
+bool RSScript::LinkRuntime(RSScript &pScript, const char *core_lib) {
+  bccAssert(core_lib != nullptr);
+
+  // Using the same context with the source in pScript.
+  BCCContext &context = pScript.getSource().getContext();
+
+  Source *libclcore_source = Source::CreateFromFile(context, core_lib);
+  if (libclcore_source == nullptr) {
+    ALOGE("Failed to load Renderscript library '%s' to link!", core_lib);
+    return false;
+  }
+
+  if (pScript.mLinkRuntimeCallback != nullptr) {
+    pScript.mLinkRuntimeCallback(&pScript,
+        &pScript.getSource().getModule(), &libclcore_source->getModule());
+  }
+
+  if (!pScript.getSource().merge(*libclcore_source)) {
+    ALOGE("Failed to link Renderscript library '%s'!", core_lib);
+    delete libclcore_source;
+    return false;
+  }
+
+  return true;
+}
+
+RSScript::RSScript(Source &pSource)
+  : Script(pSource), mCompilerVersion(0),
+    mOptimizationLevel(kOptLvl3), mLinkRuntimeCallback(nullptr),
+    mEmbedInfo(false), mEmbedGlobalInfo(false),
+    mEmbedGlobalInfoSkipConstant(false) { }
+
+RSScript::RSScript(Source &pSource, const CompilerConfig * pCompilerConfig): RSScript(pSource)
+{
+  switch (pCompilerConfig->getOptimizationLevel()) {
+    case llvm::CodeGenOpt::None:    mOptimizationLevel = kOptLvl0; break;
+    case llvm::CodeGenOpt::Less:    mOptimizationLevel = kOptLvl1; break;
+    case llvm::CodeGenOpt::Default: mOptimizationLevel = kOptLvl2; break;
+    case llvm::CodeGenOpt::Aggressive: //Intentional fallthrough
+    default: {
+      mOptimizationLevel = kOptLvl3;
+      break;
+    }
+  }
+}
+
+bool RSScript::doReset() {
+  mCompilerVersion = 0;
+  mOptimizationLevel = kOptLvl3;
+  return true;
+}
diff --git a/libbcc/lib/Renderscript/RSScriptGroupFusion.cpp b/libbcc/lib/Renderscript/RSScriptGroupFusion.cpp
new file mode 100644
index 0000000..20a4b86
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSScriptGroupFusion.cpp
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Renderscript/RSScriptGroupFusion.h"
+
+#include "bcc/Assert.h"
+#include "bcc/BCCContext.h"
+#include "bcc/Source.h"
+#include "bcc/Support/Log.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/raw_ostream.h"
+
+using llvm::Function;
+using llvm::Module;
+
+using std::string;
+
+namespace bcc {
+
+namespace {
+
+const Function* getInvokeFunction(const Source& source, const int slot,
+                                  Module* newModule) {
+
+  bcinfo::MetadataExtractor &metadata = *source.getMetadata();
+  const char* functionName = metadata.getExportFuncNameList()[slot];
+  Function* func = newModule->getFunction(functionName);
+  // Materialize the function so that later the caller can inspect its argument
+  // and return types.
+  newModule->materialize(func);
+  return func;
+}
+
+const Function*
+getFunction(Module* mergedModule, const Source* source, const int slot,
+            uint32_t* signature) {
+
+  bcinfo::MetadataExtractor &metadata = *source->getMetadata();
+  const char* functionName = metadata.getExportForEachNameList()[slot];
+  if (functionName == nullptr || !functionName[0]) {
+    ALOGE("Kernel fusion (module %s slot %d): failed to find kernel function",
+          source->getName().c_str(), slot);
+    return nullptr;
+  }
+
+  if (metadata.getExportForEachInputCountList()[slot] > 1) {
+    ALOGE("Kernel fusion (module %s function %s): cannot handle multiple inputs",
+          source->getName().c_str(), functionName);
+    return nullptr;
+  }
+
+  if (signature != nullptr) {
+    *signature = metadata.getExportForEachSignatureList()[slot];
+  }
+
+  const Function* function = mergedModule->getFunction(functionName);
+
+  return function;
+}
+
+// The whitelist of supported signature bits. Context or user data arguments are
+// not currently supported in kernel fusion. To support them or any new kinds of
+// arguments in the future, it requires not only listing the signature bits here,
+// but also implementing additional necessary fusion logic in the getFusedFuncSig(),
+// getFusedFuncType(), and fuseKernels() functions below.
+constexpr uint32_t ExpectedSignatureBits =
+        bcinfo::MD_SIG_In |
+        bcinfo::MD_SIG_Out |
+        bcinfo::MD_SIG_X |
+        bcinfo::MD_SIG_Y |
+        bcinfo::MD_SIG_Z |
+        bcinfo::MD_SIG_Kernel;
+
+int getFusedFuncSig(const std::vector<Source*>& sources,
+                    const std::vector<int>& slots,
+                    uint32_t* retSig) {
+  *retSig = 0;
+  uint32_t firstSignature = 0;
+  uint32_t signature = 0;
+  auto slotIter = slots.begin();
+  for (const Source* source : sources) {
+    const int slot = *slotIter++;
+    bcinfo::MetadataExtractor &metadata = *source->getMetadata();
+
+    if (metadata.getExportForEachInputCountList()[slot] > 1) {
+      ALOGE("Kernel fusion (module %s slot %d): cannot handle multiple inputs",
+            source->getName().c_str(), slot);
+      return -1;
+    }
+
+    signature = metadata.getExportForEachSignatureList()[slot];
+    if (signature & ~ExpectedSignatureBits) {
+      ALOGE("Kernel fusion (module %s slot %d): Unexpected signature %x",
+            source->getName().c_str(), slot, signature);
+      return -1;
+    }
+
+    if (firstSignature == 0) {
+      firstSignature = signature;
+    }
+
+    *retSig |= signature;
+  }
+
+  if (!bcinfo::MetadataExtractor::hasForEachSignatureIn(firstSignature)) {
+    *retSig &= ~bcinfo::MD_SIG_In;
+  }
+
+  if (!bcinfo::MetadataExtractor::hasForEachSignatureOut(signature)) {
+    *retSig &= ~bcinfo::MD_SIG_Out;
+  }
+
+  return 0;
+}
+
+llvm::FunctionType* getFusedFuncType(bcc::BCCContext& Context,
+                                     const std::vector<Source*>& sources,
+                                     const std::vector<int>& slots,
+                                     Module* M,
+                                     uint32_t* signature) {
+  int error = getFusedFuncSig(sources, slots, signature);
+
+  if (error < 0) {
+    return nullptr;
+  }
+
+  const Function* firstF = getFunction(M, sources.front(), slots.front(), nullptr);
+
+  bccAssert (firstF != nullptr);
+
+  llvm::SmallVector<llvm::Type*, 8> ArgTys;
+
+  if (bcinfo::MetadataExtractor::hasForEachSignatureIn(*signature)) {
+    ArgTys.push_back(firstF->arg_begin()->getType());
+  }
+
+  llvm::Type* I32Ty = llvm::IntegerType::get(Context.getLLVMContext(), 32);
+  if (bcinfo::MetadataExtractor::hasForEachSignatureX(*signature)) {
+    ArgTys.push_back(I32Ty);
+  }
+  if (bcinfo::MetadataExtractor::hasForEachSignatureY(*signature)) {
+    ArgTys.push_back(I32Ty);
+  }
+  if (bcinfo::MetadataExtractor::hasForEachSignatureZ(*signature)) {
+    ArgTys.push_back(I32Ty);
+  }
+
+  const Function* lastF = getFunction(M, sources.back(), slots.back(), nullptr);
+
+  bccAssert (lastF != nullptr);
+
+  llvm::Type* retTy = lastF->getReturnType();
+
+  return llvm::FunctionType::get(retTy, ArgTys, false);
+}
+
+}  // anonymous namespace
+
+bool fuseKernels(bcc::BCCContext& Context,
+                 const std::vector<Source *>& sources,
+                 const std::vector<int>& slots,
+                 const std::string& fusedName,
+                 Module* mergedModule) {
+  bccAssert(sources.size() == slots.size() && "sources and slots differ in size");
+
+  uint32_t fusedFunctionSignature;
+
+  llvm::FunctionType* fusedType =
+          getFusedFuncType(Context, sources, slots, mergedModule, &fusedFunctionSignature);
+
+  if (fusedType == nullptr) {
+    return false;
+  }
+
+  Function* fusedKernel =
+          (Function*)(mergedModule->getOrInsertFunction(fusedName, fusedType));
+
+  llvm::LLVMContext& ctxt = Context.getLLVMContext();
+
+  llvm::BasicBlock* block = llvm::BasicBlock::Create(ctxt, "entry", fusedKernel);
+  llvm::IRBuilder<> builder(block);
+
+  Function::arg_iterator argIter = fusedKernel->arg_begin();
+
+  llvm::Value* dataElement = nullptr;
+  if (bcinfo::MetadataExtractor::hasForEachSignatureIn(fusedFunctionSignature)) {
+    dataElement = &*(argIter++);
+    dataElement->setName("DataIn");
+  }
+
+  llvm::Value* X = nullptr;
+  if (bcinfo::MetadataExtractor::hasForEachSignatureX(fusedFunctionSignature)) {
+    X = &*(argIter++);
+    X->setName("x");
+  }
+
+  llvm::Value* Y = nullptr;
+  if (bcinfo::MetadataExtractor::hasForEachSignatureY(fusedFunctionSignature)) {
+    Y = &*(argIter++);
+    Y->setName("y");
+  }
+
+  llvm::Value* Z = nullptr;
+  if (bcinfo::MetadataExtractor::hasForEachSignatureZ(fusedFunctionSignature)) {
+    Z = &*(argIter++);
+    Z->setName("z");
+  }
+
+  auto slotIter = slots.begin();
+  for (const Source* source : sources) {
+    int slot = *slotIter;
+
+    uint32_t inputFunctionSignature;
+    const Function* inputFunction =
+            getFunction(mergedModule, source, slot, &inputFunctionSignature);
+    if (inputFunction == nullptr) {
+      // Either failed to find the kernel function, or the function has multiple inputs.
+      return false;
+    }
+
+    // Don't try to fuse a non-kernel
+    if (!bcinfo::MetadataExtractor::hasForEachSignatureKernel(inputFunctionSignature)) {
+      ALOGE("Kernel fusion (module %s function %s): not a kernel",
+            source->getName().c_str(), inputFunction->getName().str().c_str());
+      return false;
+    }
+
+    std::vector<llvm::Value*> args;
+
+    if (bcinfo::MetadataExtractor::hasForEachSignatureIn(inputFunctionSignature)) {
+      if (dataElement == nullptr) {
+        ALOGE("Kernel fusion (module %s function %s): expected input, but got null",
+              source->getName().c_str(), inputFunction->getName().str().c_str());
+        return false;
+      }
+
+      const llvm::FunctionType* funcTy = inputFunction->getFunctionType();
+      llvm::Type* firstArgType = funcTy->getParamType(0);
+
+      if (dataElement->getType() != firstArgType) {
+        std::string msg;
+        llvm::raw_string_ostream rso(msg);
+        rso << "Mismatching argument type, expected ";
+        firstArgType->print(rso);
+        rso << ", received ";
+        dataElement->getType()->print(rso);
+        ALOGE("Kernel fusion (module %s function %s): %s", source->getName().c_str(),
+              inputFunction->getName().str().c_str(), rso.str().c_str());
+        return false;
+      }
+
+      args.push_back(dataElement);
+    } else {
+      // Only the first kernel in a batch is allowed to have no input
+      if (slotIter != slots.begin()) {
+        ALOGE("Kernel fusion (module %s function %s): function not first in batch takes no input",
+              source->getName().c_str(), inputFunction->getName().str().c_str());
+        return false;
+      }
+    }
+
+    if (bcinfo::MetadataExtractor::hasForEachSignatureX(inputFunctionSignature)) {
+      args.push_back(X);
+    }
+
+    if (bcinfo::MetadataExtractor::hasForEachSignatureY(inputFunctionSignature)) {
+      args.push_back(Y);
+    }
+
+    if (bcinfo::MetadataExtractor::hasForEachSignatureZ(inputFunctionSignature)) {
+      args.push_back(Z);
+    }
+
+    dataElement = builder.CreateCall((llvm::Value*)inputFunction, args);
+
+    slotIter++;
+  }
+
+  if (fusedKernel->getReturnType()->isVoidTy()) {
+    builder.CreateRetVoid();
+  } else {
+    builder.CreateRet(dataElement);
+  }
+
+  llvm::NamedMDNode* ExportForEachNameMD =
+    mergedModule->getOrInsertNamedMetadata("#rs_export_foreach_name");
+
+  llvm::MDString* nameMDStr = llvm::MDString::get(ctxt, fusedName);
+  llvm::MDNode* nameMDNode = llvm::MDNode::get(ctxt, nameMDStr);
+  ExportForEachNameMD->addOperand(nameMDNode);
+
+  llvm::NamedMDNode* ExportForEachMD =
+    mergedModule->getOrInsertNamedMetadata("#rs_export_foreach");
+  llvm::MDString* sigMDStr = llvm::MDString::get(ctxt,
+                                                 llvm::utostr_32(fusedFunctionSignature));
+  llvm::MDNode* sigMDNode = llvm::MDNode::get(ctxt, sigMDStr);
+  ExportForEachMD->addOperand(sigMDNode);
+
+  return true;
+}
+
+bool renameInvoke(BCCContext& Context, const Source* source, const int slot,
+                  const std::string& newName, Module* module) {
+  const llvm::Function* F = getInvokeFunction(*source, slot, module);
+  std::vector<llvm::Type*> params;
+  for (auto I = F->arg_begin(), E = F->arg_end(); I != E; ++I) {
+    params.push_back(I->getType());
+  }
+  llvm::Type* returnTy = F->getReturnType();
+
+  llvm::FunctionType* batchFuncTy =
+          llvm::FunctionType::get(returnTy, params, false);
+
+  llvm::Function* newF =
+          llvm::Function::Create(batchFuncTy,
+                                 llvm::GlobalValue::ExternalLinkage, newName,
+                                 module);
+
+  llvm::BasicBlock* block = llvm::BasicBlock::Create(Context.getLLVMContext(),
+                                                     "entry", newF);
+  llvm::IRBuilder<> builder(block);
+
+  llvm::Function::arg_iterator argIter = newF->arg_begin();
+  llvm::Value* arg1 = &*(argIter++);
+  builder.CreateCall((llvm::Value*)F, arg1);
+
+  builder.CreateRetVoid();
+
+  llvm::NamedMDNode* ExportFuncNameMD =
+          module->getOrInsertNamedMetadata("#rs_export_func");
+  llvm::MDString* strMD = llvm::MDString::get(module->getContext(), newName);
+  llvm::MDNode* nodeMD = llvm::MDNode::get(module->getContext(), strMD);
+  ExportFuncNameMD->addOperand(nodeMD);
+
+  return true;
+}
+
+}  // namespace bcc
diff --git a/libbcc/lib/Renderscript/RSStubsWhiteList.cpp b/libbcc/lib/Renderscript/RSStubsWhiteList.cpp
new file mode 100644
index 0000000..8c5e231
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSStubsWhiteList.cpp
@@ -0,0 +1,2350 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/generate.sh.
+
+#include "RSStubsWhiteList.h"
+
+std::vector<std::string> stubList = {
+"_Z10half_recipDv2_f",
+"_Z10half_recipDv3_f",
+"_Z10half_recipDv4_f",
+"_Z10half_recipf",
+"_Z10half_rsqrtDv2_f",
+"_Z10half_rsqrtDv3_f",
+"_Z10half_rsqrtDv4_f",
+"_Z10half_rsqrtf",
+"_Z10native_cosDh",
+"_Z10native_cosDv2_Dh",
+"_Z10native_cosDv2_f",
+"_Z10native_cosDv3_Dh",
+"_Z10native_cosDv3_f",
+"_Z10native_cosDv4_Dh",
+"_Z10native_cosDv4_f",
+"_Z10native_cosf",
+"_Z10native_expDh",
+"_Z10native_expDv2_Dh",
+"_Z10native_expDv2_f",
+"_Z10native_expDv3_Dh",
+"_Z10native_expDv3_f",
+"_Z10native_expDv4_Dh",
+"_Z10native_expDv4_f",
+"_Z10native_expf",
+"_Z10native_logDh",
+"_Z10native_logDv2_Dh",
+"_Z10native_logDv2_f",
+"_Z10native_logDv3_Dh",
+"_Z10native_logDv3_f",
+"_Z10native_logDv4_Dh",
+"_Z10native_logDv4_f",
+"_Z10native_logf",
+"_Z10native_sinDh",
+"_Z10native_sinDv2_Dh",
+"_Z10native_sinDv2_f",
+"_Z10native_sinDv3_Dh",
+"_Z10native_sinDv3_f",
+"_Z10native_sinDv4_Dh",
+"_Z10native_sinDv4_f",
+"_Z10native_sinf",
+"_Z10native_tanDh",
+"_Z10native_tanDv2_Dh",
+"_Z10native_tanDv2_f",
+"_Z10native_tanDv3_Dh",
+"_Z10native_tanDv3_f",
+"_Z10native_tanDv4_Dh",
+"_Z10native_tanDv4_f",
+"_Z10native_tanf",
+"_Z10rsAtomicOrPVii",
+"_Z10rsAtomicOrPVjj",
+"_Z10rsIsObject10rs_element",
+"_Z10rsIsObject10rs_sampler",
+"_Z10rsIsObject13rs_allocation",
+"_Z10rsIsObject16rs_program_store",
+"_Z10rsIsObject17rs_program_raster",
+"_Z10rsIsObject17rs_program_vertex",
+"_Z10rsIsObject19rs_program_fragment",
+"_Z10rsIsObject7rs_font",
+"_Z10rsIsObject7rs_mesh",
+"_Z10rsIsObject7rs_type",
+"_Z10rsIsObject9rs_script",
+"_Z11fast_lengthDv2_f",
+"_Z11fast_lengthDv3_f",
+"_Z11fast_lengthDv4_f",
+"_Z11fast_lengthf",
+"_Z11native_acosDh",
+"_Z11native_acosDv2_Dh",
+"_Z11native_acosDv2_f",
+"_Z11native_acosDv3_Dh",
+"_Z11native_acosDv3_f",
+"_Z11native_acosDv4_Dh",
+"_Z11native_acosDv4_f",
+"_Z11native_acosf",
+"_Z11native_asinDh",
+"_Z11native_asinDv2_Dh",
+"_Z11native_asinDv2_f",
+"_Z11native_asinDv3_Dh",
+"_Z11native_asinDv3_f",
+"_Z11native_asinDv4_Dh",
+"_Z11native_asinDv4_f",
+"_Z11native_asinf",
+"_Z11native_atanDh",
+"_Z11native_atanDv2_Dh",
+"_Z11native_atanDv2_f",
+"_Z11native_atanDv3_Dh",
+"_Z11native_atanDv3_f",
+"_Z11native_atanDv4_Dh",
+"_Z11native_atanDv4_f",
+"_Z11native_atanf",
+"_Z11native_cbrtDh",
+"_Z11native_cbrtDv2_Dh",
+"_Z11native_cbrtDv2_f",
+"_Z11native_cbrtDv3_Dh",
+"_Z11native_cbrtDv3_f",
+"_Z11native_cbrtDv4_Dh",
+"_Z11native_cbrtDv4_f",
+"_Z11native_cbrtf",
+"_Z11native_coshDh",
+"_Z11native_coshDv2_Dh",
+"_Z11native_coshDv2_f",
+"_Z11native_coshDv3_Dh",
+"_Z11native_coshDv3_f",
+"_Z11native_coshDv4_Dh",
+"_Z11native_coshDv4_f",
+"_Z11native_coshf",
+"_Z11native_exp2Dh",
+"_Z11native_exp2Dv2_Dh",
+"_Z11native_exp2Dv2_f",
+"_Z11native_exp2Dv3_Dh",
+"_Z11native_exp2Dv3_f",
+"_Z11native_exp2Dv4_Dh",
+"_Z11native_exp2Dv4_f",
+"_Z11native_exp2f",
+"_Z11native_log2Dh",
+"_Z11native_log2Dv2_Dh",
+"_Z11native_log2Dv2_f",
+"_Z11native_log2Dv3_Dh",
+"_Z11native_log2Dv3_f",
+"_Z11native_log2Dv4_Dh",
+"_Z11native_log2Dv4_f",
+"_Z11native_log2f",
+"_Z11native_powrDhDh",
+"_Z11native_powrDv2_DhS_",
+"_Z11native_powrDv2_fS_",
+"_Z11native_powrDv3_DhS_",
+"_Z11native_powrDv3_fS_",
+"_Z11native_powrDv4_DhS_",
+"_Z11native_powrDv4_fS_",
+"_Z11native_powrff",
+"_Z11native_sinhDh",
+"_Z11native_sinhDv2_Dh",
+"_Z11native_sinhDv2_f",
+"_Z11native_sinhDv3_Dh",
+"_Z11native_sinhDv3_f",
+"_Z11native_sinhDv4_Dh",
+"_Z11native_sinhDv4_f",
+"_Z11native_sinhf",
+"_Z11native_sqrtDh",
+"_Z11native_sqrtDv2_Dh",
+"_Z11native_sqrtDv2_f",
+"_Z11native_sqrtDv3_Dh",
+"_Z11native_sqrtDv3_f",
+"_Z11native_sqrtDv4_Dh",
+"_Z11native_sqrtDv4_f",
+"_Z11native_sqrtf",
+"_Z11native_tanhDh",
+"_Z11native_tanhDv2_Dh",
+"_Z11native_tanhDv2_f",
+"_Z11native_tanhDv3_Dh",
+"_Z11native_tanhDv3_f",
+"_Z11native_tanhDv4_Dh",
+"_Z11native_tanhDv4_f",
+"_Z11native_tanhf",
+"_Z11rsAtomicAddPVii",
+"_Z11rsAtomicAddPVjj",
+"_Z11rsAtomicAndPVii",
+"_Z11rsAtomicAndPVjj",
+"_Z11rsAtomicCasPViii",
+"_Z11rsAtomicCasPVjjj",
+"_Z11rsAtomicDecPVi",
+"_Z11rsAtomicDecPVj",
+"_Z11rsAtomicIncPVi",
+"_Z11rsAtomicIncPVj",
+"_Z11rsAtomicMaxPVii",
+"_Z11rsAtomicMaxPVjj",
+"_Z11rsAtomicMinPVii",
+"_Z11rsAtomicMinPVjj",
+"_Z11rsAtomicSubPVii",
+"_Z11rsAtomicSubPVjj",
+"_Z11rsAtomicXorPVii",
+"_Z11rsAtomicXorPVjj",
+"_Z11rsGetArray0PK19rs_kernel_context_t",
+"_Z11rsGetArray1PK19rs_kernel_context_t",
+"_Z11rsGetArray2PK19rs_kernel_context_t",
+"_Z11rsGetArray3PK19rs_kernel_context_t",
+"_Z11rsGetDimLodPK19rs_kernel_context_t",
+"_Z11rsLocaltimeP5rs_tmPKi",
+"_Z11rsLocaltimeP5rs_tmPKl",
+"_Z11rsMatrixGetPK12rs_matrix2x2jj",
+"_Z11rsMatrixGetPK12rs_matrix3x3jj",
+"_Z11rsMatrixGetPK12rs_matrix4x4jj",
+"_Z11rsMatrixSetP12rs_matrix2x2jjf",
+"_Z11rsMatrixSetP12rs_matrix3x3jjf",
+"_Z11rsMatrixSetP12rs_matrix4x4jjf",
+"_Z11rsSetObjectP10rs_elementS_",
+"_Z11rsSetObjectP10rs_samplerS_",
+"_Z11rsSetObjectP13rs_allocationS_",
+"_Z11rsSetObjectP16rs_program_storeS_",
+"_Z11rsSetObjectP17rs_program_rasterS_",
+"_Z11rsSetObjectP17rs_program_vertexS_",
+"_Z11rsSetObjectP19rs_program_fragmentS_",
+"_Z11rsSetObjectP7rs_fontS_",
+"_Z11rsSetObjectP7rs_meshS_",
+"_Z11rsSetObjectP7rs_typeS_",
+"_Z11rsSetObjectP9rs_scriptS_",
+"_Z11rsgBindFont7rs_font",
+"_Z11rsgDrawMesh7rs_mesh",
+"_Z11rsgDrawMesh7rs_meshj",
+"_Z11rsgDrawMesh7rs_meshjjj",
+"_Z11rsgDrawQuadffffffffffff",
+"_Z11rsgDrawRectfffff",
+"_Z11rsgDrawText13rs_allocationii",
+"_Z11rsgDrawTextPKcii",
+"_Z11rsgGetWidthv",
+"_Z12convert_int2Dv2_Dh",
+"_Z12convert_int2Dv2_c",
+"_Z12convert_int2Dv2_d",
+"_Z12convert_int2Dv2_f",
+"_Z12convert_int2Dv2_h",
+"_Z12convert_int2Dv2_i",
+"_Z12convert_int2Dv2_j",
+"_Z12convert_int2Dv2_l",
+"_Z12convert_int2Dv2_m",
+"_Z12convert_int2Dv2_s",
+"_Z12convert_int2Dv2_t",
+"_Z12convert_int3Dv3_Dh",
+"_Z12convert_int3Dv3_c",
+"_Z12convert_int3Dv3_d",
+"_Z12convert_int3Dv3_f",
+"_Z12convert_int3Dv3_h",
+"_Z12convert_int3Dv3_i",
+"_Z12convert_int3Dv3_j",
+"_Z12convert_int3Dv3_l",
+"_Z12convert_int3Dv3_m",
+"_Z12convert_int3Dv3_s",
+"_Z12convert_int3Dv3_t",
+"_Z12convert_int4Dv4_Dh",
+"_Z12convert_int4Dv4_c",
+"_Z12convert_int4Dv4_d",
+"_Z12convert_int4Dv4_f",
+"_Z12convert_int4Dv4_h",
+"_Z12convert_int4Dv4_i",
+"_Z12convert_int4Dv4_j",
+"_Z12convert_int4Dv4_l",
+"_Z12convert_int4Dv4_m",
+"_Z12convert_int4Dv4_s",
+"_Z12convert_int4Dv4_t",
+"_Z12native_acoshDh",
+"_Z12native_acoshDv2_Dh",
+"_Z12native_acoshDv2_f",
+"_Z12native_acoshDv3_Dh",
+"_Z12native_acoshDv3_f",
+"_Z12native_acoshDv4_Dh",
+"_Z12native_acoshDv4_f",
+"_Z12native_acoshf",
+"_Z12native_asinhDh",
+"_Z12native_asinhDv2_Dh",
+"_Z12native_asinhDv2_f",
+"_Z12native_asinhDv3_Dh",
+"_Z12native_asinhDv3_f",
+"_Z12native_asinhDv4_Dh",
+"_Z12native_asinhDv4_f",
+"_Z12native_asinhf",
+"_Z12native_atan2DhDh",
+"_Z12native_atan2Dv2_DhS_",
+"_Z12native_atan2Dv2_fS_",
+"_Z12native_atan2Dv3_DhS_",
+"_Z12native_atan2Dv3_fS_",
+"_Z12native_atan2Dv4_DhS_",
+"_Z12native_atan2Dv4_fS_",
+"_Z12native_atan2ff",
+"_Z12native_atanhDh",
+"_Z12native_atanhDv2_Dh",
+"_Z12native_atanhDv2_f",
+"_Z12native_atanhDv3_Dh",
+"_Z12native_atanhDv3_f",
+"_Z12native_atanhDv4_Dh",
+"_Z12native_atanhDv4_f",
+"_Z12native_atanhf",
+"_Z12native_cospiDh",
+"_Z12native_cospiDv2_Dh",
+"_Z12native_cospiDv2_f",
+"_Z12native_cospiDv3_Dh",
+"_Z12native_cospiDv3_f",
+"_Z12native_cospiDv4_Dh",
+"_Z12native_cospiDv4_f",
+"_Z12native_cospif",
+"_Z12native_exp10Dh",
+"_Z12native_exp10Dv2_Dh",
+"_Z12native_exp10Dv2_f",
+"_Z12native_exp10Dv3_Dh",
+"_Z12native_exp10Dv3_f",
+"_Z12native_exp10Dv4_Dh",
+"_Z12native_exp10Dv4_f",
+"_Z12native_exp10f",
+"_Z12native_expm1Dh",
+"_Z12native_expm1Dv2_Dh",
+"_Z12native_expm1Dv2_f",
+"_Z12native_expm1Dv3_Dh",
+"_Z12native_expm1Dv3_f",
+"_Z12native_expm1Dv4_Dh",
+"_Z12native_expm1Dv4_f",
+"_Z12native_expm1f",
+"_Z12native_hypotDhDh",
+"_Z12native_hypotDv2_DhS_",
+"_Z12native_hypotDv2_fS_",
+"_Z12native_hypotDv3_DhS_",
+"_Z12native_hypotDv3_fS_",
+"_Z12native_hypotDv4_DhS_",
+"_Z12native_hypotDv4_fS_",
+"_Z12native_hypotff",
+"_Z12native_log10Dh",
+"_Z12native_log10Dv2_Dh",
+"_Z12native_log10Dv2_f",
+"_Z12native_log10Dv3_Dh",
+"_Z12native_log10Dv3_f",
+"_Z12native_log10Dv4_Dh",
+"_Z12native_log10Dv4_f",
+"_Z12native_log10f",
+"_Z12native_log1pDh",
+"_Z12native_log1pDv2_Dh",
+"_Z12native_log1pDv2_f",
+"_Z12native_log1pDv3_Dh",
+"_Z12native_log1pDv3_f",
+"_Z12native_log1pDv4_Dh",
+"_Z12native_log1pDv4_f",
+"_Z12native_log1pf",
+"_Z12native_recipDh",
+"_Z12native_recipDv2_Dh",
+"_Z12native_recipDv2_f",
+"_Z12native_recipDv3_Dh",
+"_Z12native_recipDv3_f",
+"_Z12native_recipDv4_Dh",
+"_Z12native_recipDv4_f",
+"_Z12native_recipf",
+"_Z12native_rootnDhi",
+"_Z12native_rootnDv2_DhDv2_i",
+"_Z12native_rootnDv2_fDv2_i",
+"_Z12native_rootnDv3_DhDv3_i",
+"_Z12native_rootnDv3_fDv3_i",
+"_Z12native_rootnDv4_DhDv4_i",
+"_Z12native_rootnDv4_fDv4_i",
+"_Z12native_rootnfi",
+"_Z12native_rsqrtDh",
+"_Z12native_rsqrtDv2_Dh",
+"_Z12native_rsqrtDv2_f",
+"_Z12native_rsqrtDv3_Dh",
+"_Z12native_rsqrtDv3_f",
+"_Z12native_rsqrtDv4_Dh",
+"_Z12native_rsqrtDv4_f",
+"_Z12native_rsqrtf",
+"_Z12native_sinpiDh",
+"_Z12native_sinpiDv2_Dh",
+"_Z12native_sinpiDv2_f",
+"_Z12native_sinpiDv3_Dh",
+"_Z12native_sinpiDv3_f",
+"_Z12native_sinpiDv4_Dh",
+"_Z12native_sinpiDv4_f",
+"_Z12native_sinpif",
+"_Z12native_tanpiDh",
+"_Z12native_tanpiDv2_Dh",
+"_Z12native_tanpiDv2_f",
+"_Z12native_tanpiDv3_Dh",
+"_Z12native_tanpiDv3_f",
+"_Z12native_tanpiDv4_Dh",
+"_Z12native_tanpiDv4_f",
+"_Z12native_tanpif",
+"_Z12rsCreateType10rs_elementj",
+"_Z12rsCreateType10rs_elementjj",
+"_Z12rsCreateType10rs_elementjjj",
+"_Z12rsCreateType10rs_elementjjjbb13rs_yuv_format",
+"_Z12rsMatrixLoadP12rs_matrix2x2PKS_",
+"_Z12rsMatrixLoadP12rs_matrix2x2PKf",
+"_Z12rsMatrixLoadP12rs_matrix3x3PKS_",
+"_Z12rsMatrixLoadP12rs_matrix3x3PKf",
+"_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix2x2",
+"_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix3x3",
+"_Z12rsMatrixLoadP12rs_matrix4x4PKS_",
+"_Z12rsMatrixLoadP12rs_matrix4x4PKf",
+"_Z12rsgFontColorffff",
+"_Z12rsgGetHeightv",
+"_Z13convert_char2Dv2_Dh",
+"_Z13convert_char2Dv2_c",
+"_Z13convert_char2Dv2_d",
+"_Z13convert_char2Dv2_f",
+"_Z13convert_char2Dv2_h",
+"_Z13convert_char2Dv2_i",
+"_Z13convert_char2Dv2_j",
+"_Z13convert_char2Dv2_l",
+"_Z13convert_char2Dv2_m",
+"_Z13convert_char2Dv2_s",
+"_Z13convert_char2Dv2_t",
+"_Z13convert_char3Dv3_Dh",
+"_Z13convert_char3Dv3_c",
+"_Z13convert_char3Dv3_d",
+"_Z13convert_char3Dv3_f",
+"_Z13convert_char3Dv3_h",
+"_Z13convert_char3Dv3_i",
+"_Z13convert_char3Dv3_j",
+"_Z13convert_char3Dv3_l",
+"_Z13convert_char3Dv3_m",
+"_Z13convert_char3Dv3_s",
+"_Z13convert_char3Dv3_t",
+"_Z13convert_char4Dv4_Dh",
+"_Z13convert_char4Dv4_c",
+"_Z13convert_char4Dv4_d",
+"_Z13convert_char4Dv4_f",
+"_Z13convert_char4Dv4_h",
+"_Z13convert_char4Dv4_i",
+"_Z13convert_char4Dv4_j",
+"_Z13convert_char4Dv4_l",
+"_Z13convert_char4Dv4_m",
+"_Z13convert_char4Dv4_s",
+"_Z13convert_char4Dv4_t",
+"_Z13convert_half2Dv2_Dh",
+"_Z13convert_half2Dv2_c",
+"_Z13convert_half2Dv2_d",
+"_Z13convert_half2Dv2_f",
+"_Z13convert_half2Dv2_h",
+"_Z13convert_half2Dv2_i",
+"_Z13convert_half2Dv2_j",
+"_Z13convert_half2Dv2_l",
+"_Z13convert_half2Dv2_m",
+"_Z13convert_half2Dv2_s",
+"_Z13convert_half2Dv2_t",
+"_Z13convert_half3Dv3_Dh",
+"_Z13convert_half3Dv3_c",
+"_Z13convert_half3Dv3_d",
+"_Z13convert_half3Dv3_f",
+"_Z13convert_half3Dv3_h",
+"_Z13convert_half3Dv3_i",
+"_Z13convert_half3Dv3_j",
+"_Z13convert_half3Dv3_l",
+"_Z13convert_half3Dv3_m",
+"_Z13convert_half3Dv3_s",
+"_Z13convert_half3Dv3_t",
+"_Z13convert_half4Dv4_Dh",
+"_Z13convert_half4Dv4_c",
+"_Z13convert_half4Dv4_d",
+"_Z13convert_half4Dv4_f",
+"_Z13convert_half4Dv4_h",
+"_Z13convert_half4Dv4_i",
+"_Z13convert_half4Dv4_j",
+"_Z13convert_half4Dv4_l",
+"_Z13convert_half4Dv4_m",
+"_Z13convert_half4Dv4_s",
+"_Z13convert_half4Dv4_t",
+"_Z13convert_long2Dv2_Dh",
+"_Z13convert_long2Dv2_c",
+"_Z13convert_long2Dv2_d",
+"_Z13convert_long2Dv2_f",
+"_Z13convert_long2Dv2_h",
+"_Z13convert_long2Dv2_i",
+"_Z13convert_long2Dv2_j",
+"_Z13convert_long2Dv2_l",
+"_Z13convert_long2Dv2_m",
+"_Z13convert_long2Dv2_s",
+"_Z13convert_long2Dv2_t",
+"_Z13convert_long3Dv3_Dh",
+"_Z13convert_long3Dv3_c",
+"_Z13convert_long3Dv3_d",
+"_Z13convert_long3Dv3_f",
+"_Z13convert_long3Dv3_h",
+"_Z13convert_long3Dv3_i",
+"_Z13convert_long3Dv3_j",
+"_Z13convert_long3Dv3_l",
+"_Z13convert_long3Dv3_m",
+"_Z13convert_long3Dv3_s",
+"_Z13convert_long3Dv3_t",
+"_Z13convert_long4Dv4_Dh",
+"_Z13convert_long4Dv4_c",
+"_Z13convert_long4Dv4_d",
+"_Z13convert_long4Dv4_f",
+"_Z13convert_long4Dv4_h",
+"_Z13convert_long4Dv4_i",
+"_Z13convert_long4Dv4_j",
+"_Z13convert_long4Dv4_l",
+"_Z13convert_long4Dv4_m",
+"_Z13convert_long4Dv4_s",
+"_Z13convert_long4Dv4_t",
+"_Z13convert_uint2Dv2_Dh",
+"_Z13convert_uint2Dv2_c",
+"_Z13convert_uint2Dv2_d",
+"_Z13convert_uint2Dv2_f",
+"_Z13convert_uint2Dv2_h",
+"_Z13convert_uint2Dv2_i",
+"_Z13convert_uint2Dv2_j",
+"_Z13convert_uint2Dv2_l",
+"_Z13convert_uint2Dv2_m",
+"_Z13convert_uint2Dv2_s",
+"_Z13convert_uint2Dv2_t",
+"_Z13convert_uint3Dv3_Dh",
+"_Z13convert_uint3Dv3_c",
+"_Z13convert_uint3Dv3_d",
+"_Z13convert_uint3Dv3_f",
+"_Z13convert_uint3Dv3_h",
+"_Z13convert_uint3Dv3_i",
+"_Z13convert_uint3Dv3_j",
+"_Z13convert_uint3Dv3_l",
+"_Z13convert_uint3Dv3_m",
+"_Z13convert_uint3Dv3_s",
+"_Z13convert_uint3Dv3_t",
+"_Z13convert_uint4Dv4_Dh",
+"_Z13convert_uint4Dv4_c",
+"_Z13convert_uint4Dv4_d",
+"_Z13convert_uint4Dv4_f",
+"_Z13convert_uint4Dv4_h",
+"_Z13convert_uint4Dv4_i",
+"_Z13convert_uint4Dv4_j",
+"_Z13convert_uint4Dv4_l",
+"_Z13convert_uint4Dv4_m",
+"_Z13convert_uint4Dv4_s",
+"_Z13convert_uint4Dv4_t",
+"_Z13fast_distanceDv2_fS_",
+"_Z13fast_distanceDv3_fS_",
+"_Z13fast_distanceDv4_fS_",
+"_Z13fast_distanceff",
+"_Z13native_acospiDh",
+"_Z13native_acospiDv2_Dh",
+"_Z13native_acospiDv2_f",
+"_Z13native_acospiDv3_Dh",
+"_Z13native_acospiDv3_f",
+"_Z13native_acospiDv4_Dh",
+"_Z13native_acospiDv4_f",
+"_Z13native_acospif",
+"_Z13native_asinpiDh",
+"_Z13native_asinpiDv2_Dh",
+"_Z13native_asinpiDv2_f",
+"_Z13native_asinpiDv3_Dh",
+"_Z13native_asinpiDv3_f",
+"_Z13native_asinpiDv4_Dh",
+"_Z13native_asinpiDv4_f",
+"_Z13native_asinpif",
+"_Z13native_atanpiDh",
+"_Z13native_atanpiDv2_Dh",
+"_Z13native_atanpiDv2_f",
+"_Z13native_atanpiDv3_Dh",
+"_Z13native_atanpiDv3_f",
+"_Z13native_atanpiDv4_Dh",
+"_Z13native_atanpiDv4_f",
+"_Z13native_atanpif",
+"_Z13native_divideDhDh",
+"_Z13native_divideDv2_DhS_",
+"_Z13native_divideDv2_fS_",
+"_Z13native_divideDv3_DhS_",
+"_Z13native_divideDv3_fS_",
+"_Z13native_divideDv4_DhS_",
+"_Z13native_divideDv4_fS_",
+"_Z13native_divideff",
+"_Z13native_lengthDh",
+"_Z13native_lengthDv2_Dh",
+"_Z13native_lengthDv2_f",
+"_Z13native_lengthDv3_Dh",
+"_Z13native_lengthDv3_f",
+"_Z13native_lengthDv4_Dh",
+"_Z13native_lengthDv4_f",
+"_Z13native_lengthf",
+"_Z13native_sincosDhPDh",
+"_Z13native_sincosDv2_DhPS_",
+"_Z13native_sincosDv2_fPS_",
+"_Z13native_sincosDv3_DhPS_",
+"_Z13native_sincosDv3_fPS_",
+"_Z13native_sincosDv4_DhPS_",
+"_Z13native_sincosDv4_fPS_",
+"_Z13native_sincosfPf",
+"_Z13rsClearObjectP10rs_element",
+"_Z13rsClearObjectP10rs_sampler",
+"_Z13rsClearObjectP13rs_allocation",
+"_Z13rsClearObjectP16rs_program_store",
+"_Z13rsClearObjectP17rs_program_raster",
+"_Z13rsClearObjectP17rs_program_vertex",
+"_Z13rsClearObjectP19rs_program_fragment",
+"_Z13rsClearObjectP7rs_font",
+"_Z13rsClearObjectP7rs_mesh",
+"_Z13rsClearObjectP7rs_type",
+"_Z13rsClearObjectP9rs_script",
+"_Z13rsMatrixScaleP12rs_matrix4x4fff",
+"_Z13rsUptimeNanosv",
+"_Z13rsgClearColorffff",
+"_Z13rsgClearDepthf",
+"_Z14convert_float2Dv2_Dh",
+"_Z14convert_float2Dv2_c",
+"_Z14convert_float2Dv2_d",
+"_Z14convert_float2Dv2_f",
+"_Z14convert_float2Dv2_h",
+"_Z14convert_float2Dv2_i",
+"_Z14convert_float2Dv2_j",
+"_Z14convert_float2Dv2_l",
+"_Z14convert_float2Dv2_m",
+"_Z14convert_float2Dv2_s",
+"_Z14convert_float2Dv2_t",
+"_Z14convert_float3Dv3_Dh",
+"_Z14convert_float3Dv3_c",
+"_Z14convert_float3Dv3_d",
+"_Z14convert_float3Dv3_f",
+"_Z14convert_float3Dv3_h",
+"_Z14convert_float3Dv3_i",
+"_Z14convert_float3Dv3_j",
+"_Z14convert_float3Dv3_l",
+"_Z14convert_float3Dv3_m",
+"_Z14convert_float3Dv3_s",
+"_Z14convert_float3Dv3_t",
+"_Z14convert_float4Dv4_Dh",
+"_Z14convert_float4Dv4_c",
+"_Z14convert_float4Dv4_d",
+"_Z14convert_float4Dv4_f",
+"_Z14convert_float4Dv4_h",
+"_Z14convert_float4Dv4_i",
+"_Z14convert_float4Dv4_j",
+"_Z14convert_float4Dv4_l",
+"_Z14convert_float4Dv4_m",
+"_Z14convert_float4Dv4_s",
+"_Z14convert_float4Dv4_t",
+"_Z14convert_short2Dv2_Dh",
+"_Z14convert_short2Dv2_c",
+"_Z14convert_short2Dv2_d",
+"_Z14convert_short2Dv2_f",
+"_Z14convert_short2Dv2_h",
+"_Z14convert_short2Dv2_i",
+"_Z14convert_short2Dv2_j",
+"_Z14convert_short2Dv2_l",
+"_Z14convert_short2Dv2_m",
+"_Z14convert_short2Dv2_s",
+"_Z14convert_short2Dv2_t",
+"_Z14convert_short3Dv3_Dh",
+"_Z14convert_short3Dv3_c",
+"_Z14convert_short3Dv3_d",
+"_Z14convert_short3Dv3_f",
+"_Z14convert_short3Dv3_h",
+"_Z14convert_short3Dv3_i",
+"_Z14convert_short3Dv3_j",
+"_Z14convert_short3Dv3_l",
+"_Z14convert_short3Dv3_m",
+"_Z14convert_short3Dv3_s",
+"_Z14convert_short3Dv3_t",
+"_Z14convert_short4Dv4_Dh",
+"_Z14convert_short4Dv4_c",
+"_Z14convert_short4Dv4_d",
+"_Z14convert_short4Dv4_f",
+"_Z14convert_short4Dv4_h",
+"_Z14convert_short4Dv4_i",
+"_Z14convert_short4Dv4_j",
+"_Z14convert_short4Dv4_l",
+"_Z14convert_short4Dv4_m",
+"_Z14convert_short4Dv4_s",
+"_Z14convert_short4Dv4_t",
+"_Z14convert_uchar2Dv2_Dh",
+"_Z14convert_uchar2Dv2_c",
+"_Z14convert_uchar2Dv2_d",
+"_Z14convert_uchar2Dv2_f",
+"_Z14convert_uchar2Dv2_h",
+"_Z14convert_uchar2Dv2_i",
+"_Z14convert_uchar2Dv2_j",
+"_Z14convert_uchar2Dv2_l",
+"_Z14convert_uchar2Dv2_m",
+"_Z14convert_uchar2Dv2_s",
+"_Z14convert_uchar2Dv2_t",
+"_Z14convert_uchar3Dv3_Dh",
+"_Z14convert_uchar3Dv3_c",
+"_Z14convert_uchar3Dv3_d",
+"_Z14convert_uchar3Dv3_f",
+"_Z14convert_uchar3Dv3_h",
+"_Z14convert_uchar3Dv3_i",
+"_Z14convert_uchar3Dv3_j",
+"_Z14convert_uchar3Dv3_l",
+"_Z14convert_uchar3Dv3_m",
+"_Z14convert_uchar3Dv3_s",
+"_Z14convert_uchar3Dv3_t",
+"_Z14convert_uchar4Dv4_Dh",
+"_Z14convert_uchar4Dv4_c",
+"_Z14convert_uchar4Dv4_d",
+"_Z14convert_uchar4Dv4_f",
+"_Z14convert_uchar4Dv4_h",
+"_Z14convert_uchar4Dv4_i",
+"_Z14convert_uchar4Dv4_j",
+"_Z14convert_uchar4Dv4_l",
+"_Z14convert_uchar4Dv4_m",
+"_Z14convert_uchar4Dv4_s",
+"_Z14convert_uchar4Dv4_t",
+"_Z14convert_ulong2Dv2_Dh",
+"_Z14convert_ulong2Dv2_c",
+"_Z14convert_ulong2Dv2_d",
+"_Z14convert_ulong2Dv2_f",
+"_Z14convert_ulong2Dv2_h",
+"_Z14convert_ulong2Dv2_i",
+"_Z14convert_ulong2Dv2_j",
+"_Z14convert_ulong2Dv2_l",
+"_Z14convert_ulong2Dv2_m",
+"_Z14convert_ulong2Dv2_s",
+"_Z14convert_ulong2Dv2_t",
+"_Z14convert_ulong3Dv3_Dh",
+"_Z14convert_ulong3Dv3_c",
+"_Z14convert_ulong3Dv3_d",
+"_Z14convert_ulong3Dv3_f",
+"_Z14convert_ulong3Dv3_h",
+"_Z14convert_ulong3Dv3_i",
+"_Z14convert_ulong3Dv3_j",
+"_Z14convert_ulong3Dv3_l",
+"_Z14convert_ulong3Dv3_m",
+"_Z14convert_ulong3Dv3_s",
+"_Z14convert_ulong3Dv3_t",
+"_Z14convert_ulong4Dv4_Dh",
+"_Z14convert_ulong4Dv4_c",
+"_Z14convert_ulong4Dv4_d",
+"_Z14convert_ulong4Dv4_f",
+"_Z14convert_ulong4Dv4_h",
+"_Z14convert_ulong4Dv4_i",
+"_Z14convert_ulong4Dv4_j",
+"_Z14convert_ulong4Dv4_l",
+"_Z14convert_ulong4Dv4_m",
+"_Z14convert_ulong4Dv4_s",
+"_Z14convert_ulong4Dv4_t",
+"_Z14fast_normalizeDv2_f",
+"_Z14fast_normalizeDv3_f",
+"_Z14fast_normalizeDv4_f",
+"_Z14fast_normalizef",
+"_Z14native_atan2piDhDh",
+"_Z14native_atan2piDv2_DhS_",
+"_Z14native_atan2piDv2_fS_",
+"_Z14native_atan2piDv3_DhS_",
+"_Z14native_atan2piDv3_fS_",
+"_Z14native_atan2piDv4_DhS_",
+"_Z14native_atan2piDv4_fS_",
+"_Z14native_atan2piff",
+"_Z14rsGetDimArray0PK19rs_kernel_context_t",
+"_Z14rsGetDimArray1PK19rs_kernel_context_t",
+"_Z14rsGetDimArray2PK19rs_kernel_context_t",
+"_Z14rsGetDimArray3PK19rs_kernel_context_t",
+"_Z14rsGetElementAt13rs_allocationj",
+"_Z14rsGetElementAt13rs_allocationjj",
+"_Z14rsGetElementAt13rs_allocationjjj",
+"_Z14rsMatrixRotateP12rs_matrix4x4ffff",
+"_Z14rsSendToClienti",
+"_Z14rsSendToClientiPKvj",
+"_Z14rsSetElementAt13rs_allocationPvj",
+"_Z14rsSetElementAt13rs_allocationPvjj",
+"_Z14rsUptimeMillisv",
+"_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler",
+"_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation",
+"_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_",
+"_Z14rsgMeasureTextPKcPiS1_S1_S1_",
+"_Z15convert_double2Dv2_Dh",
+"_Z15convert_double2Dv2_c",
+"_Z15convert_double2Dv2_d",
+"_Z15convert_double2Dv2_f",
+"_Z15convert_double2Dv2_h",
+"_Z15convert_double2Dv2_i",
+"_Z15convert_double2Dv2_j",
+"_Z15convert_double2Dv2_l",
+"_Z15convert_double2Dv2_m",
+"_Z15convert_double2Dv2_s",
+"_Z15convert_double2Dv2_t",
+"_Z15convert_double3Dv3_Dh",
+"_Z15convert_double3Dv3_c",
+"_Z15convert_double3Dv3_d",
+"_Z15convert_double3Dv3_f",
+"_Z15convert_double3Dv3_h",
+"_Z15convert_double3Dv3_i",
+"_Z15convert_double3Dv3_j",
+"_Z15convert_double3Dv3_l",
+"_Z15convert_double3Dv3_m",
+"_Z15convert_double3Dv3_s",
+"_Z15convert_double3Dv3_t",
+"_Z15convert_double4Dv4_Dh",
+"_Z15convert_double4Dv4_c",
+"_Z15convert_double4Dv4_d",
+"_Z15convert_double4Dv4_f",
+"_Z15convert_double4Dv4_h",
+"_Z15convert_double4Dv4_i",
+"_Z15convert_double4Dv4_j",
+"_Z15convert_double4Dv4_l",
+"_Z15convert_double4Dv4_m",
+"_Z15convert_double4Dv4_s",
+"_Z15convert_double4Dv4_t",
+"_Z15convert_ushort2Dv2_Dh",
+"_Z15convert_ushort2Dv2_c",
+"_Z15convert_ushort2Dv2_d",
+"_Z15convert_ushort2Dv2_f",
+"_Z15convert_ushort2Dv2_h",
+"_Z15convert_ushort2Dv2_i",
+"_Z15convert_ushort2Dv2_j",
+"_Z15convert_ushort2Dv2_l",
+"_Z15convert_ushort2Dv2_m",
+"_Z15convert_ushort2Dv2_s",
+"_Z15convert_ushort2Dv2_t",
+"_Z15convert_ushort3Dv3_Dh",
+"_Z15convert_ushort3Dv3_c",
+"_Z15convert_ushort3Dv3_d",
+"_Z15convert_ushort3Dv3_f",
+"_Z15convert_ushort3Dv3_h",
+"_Z15convert_ushort3Dv3_i",
+"_Z15convert_ushort3Dv3_j",
+"_Z15convert_ushort3Dv3_l",
+"_Z15convert_ushort3Dv3_m",
+"_Z15convert_ushort3Dv3_s",
+"_Z15convert_ushort3Dv3_t",
+"_Z15convert_ushort4Dv4_Dh",
+"_Z15convert_ushort4Dv4_c",
+"_Z15convert_ushort4Dv4_d",
+"_Z15convert_ushort4Dv4_f",
+"_Z15convert_ushort4Dv4_h",
+"_Z15convert_ushort4Dv4_i",
+"_Z15convert_ushort4Dv4_j",
+"_Z15convert_ushort4Dv4_l",
+"_Z15convert_ushort4Dv4_m",
+"_Z15convert_ushort4Dv4_s",
+"_Z15convert_ushort4Dv4_t",
+"_Z15native_distanceDhDh",
+"_Z15native_distanceDv2_DhS_",
+"_Z15native_distanceDv2_fS_",
+"_Z15native_distanceDv3_DhS_",
+"_Z15native_distanceDv3_fS_",
+"_Z15native_distanceDv4_DhS_",
+"_Z15native_distanceDv4_fS_",
+"_Z15native_distanceff",
+"_Z15rsCreateElement12rs_data_type",
+"_Z15rsCreateElementiibj",
+"_Z15rsGetAllocationPKv",
+"_Z15rsMatrixInverseP12rs_matrix4x4",
+"_Z15rsQuaternionAddPDv4_fPKS_",
+"_Z15rsQuaternionDotPKDv4_fS1_",
+"_Z15rsQuaternionSetPDv4_fPKS_",
+"_Z15rsQuaternionSetPDv4_fffff",
+"_Z15rsgBindConstant17rs_program_vertexj13rs_allocation",
+"_Z15rsgBindConstant19rs_program_fragmentj13rs_allocation",
+"_Z16native_normalizeDh",
+"_Z16native_normalizeDv2_Dh",
+"_Z16native_normalizeDv2_f",
+"_Z16native_normalizeDv3_Dh",
+"_Z16native_normalizeDv3_f",
+"_Z16native_normalizeDv4_Dh",
+"_Z16native_normalizeDv4_f",
+"_Z16native_normalizef",
+"_Z16rsGetDimHasFacesPK19rs_kernel_context_t",
+"_Z16rsMatrixMultiplyP12rs_matrix2x2Dv2_f",
+"_Z16rsMatrixMultiplyP12rs_matrix2x2PKS_",
+"_Z16rsMatrixMultiplyP12rs_matrix3x3Dv2_f",
+"_Z16rsMatrixMultiplyP12rs_matrix3x3Dv3_f",
+"_Z16rsMatrixMultiplyP12rs_matrix3x3PKS_",
+"_Z16rsMatrixMultiplyP12rs_matrix4x4Dv2_f",
+"_Z16rsMatrixMultiplyP12rs_matrix4x4Dv3_f",
+"_Z16rsMatrixMultiplyP12rs_matrix4x4Dv4_f",
+"_Z16rsMatrixMultiplyP12rs_matrix4x4PKS_",
+"_Z16rsMatrixMultiplyPK12rs_matrix2x2Dv2_f",
+"_Z16rsMatrixMultiplyPK12rs_matrix3x3Dv2_f",
+"_Z16rsMatrixMultiplyPK12rs_matrix3x3Dv3_f",
+"_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv2_f",
+"_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv3_f",
+"_Z16rsMatrixMultiplyPK12rs_matrix4x4Dv4_f",
+"_Z17rsForEachInternaliP14rs_script_calliiP13rs_allocation",
+"_Z17rsMatrixLoadOrthoP12rs_matrix4x4ffffff",
+"_Z17rsMatrixLoadScaleP12rs_matrix4x4fff",
+"_Z17rsMatrixTranslateP12rs_matrix4x4fff",
+"_Z17rsMatrixTransposeP12rs_matrix2x2",
+"_Z17rsMatrixTransposeP12rs_matrix3x3",
+"_Z17rsMatrixTransposeP12rs_matrix4x4",
+"_Z17rsPackColorTo8888Dv3_f",
+"_Z17rsPackColorTo8888Dv4_f",
+"_Z17rsPackColorTo8888fff",
+"_Z17rsPackColorTo8888ffff",
+"_Z17rsQuaternionSlerpPDv4_fPKS_S2_f",
+"_Z17rsSamplerGetWrapS10rs_sampler",
+"_Z17rsSamplerGetWrapT10rs_sampler",
+"_Z18rsAllocationIoSend13rs_allocation",
+"_Z18rsCreateAllocation7rs_type",
+"_Z18rsCreateAllocation7rs_type28rs_allocation_mipmap_controljPv",
+"_Z18rsCreateAllocation7rs_typej",
+"_Z18rsGetElementAt_int13rs_allocationj",
+"_Z18rsGetElementAt_int13rs_allocationjj",
+"_Z18rsGetElementAt_int13rs_allocationjjj",
+"_Z18rsMatrixLoadRotateP12rs_matrix4x4ffff",
+"_Z18rsSetElementAt_int13rs_allocationij",
+"_Z18rsSetElementAt_int13rs_allocationijj",
+"_Z18rsSetElementAt_int13rs_allocationijjj",
+"_Z18rsYuvToRGBA_float4hhh",
+"_Z18rsYuvToRGBA_uchar4hhh",
+"_Z18rsgBindColorTarget13rs_allocationj",
+"_Z18rsgBindDepthTarget13rs_allocation",
+"_Z19rsAllocationGetDimX13rs_allocation",
+"_Z19rsAllocationGetDimY13rs_allocation",
+"_Z19rsAllocationGetDimZ13rs_allocation",
+"_Z19rsGetElementAt_char13rs_allocationj",
+"_Z19rsGetElementAt_char13rs_allocationjj",
+"_Z19rsGetElementAt_char13rs_allocationjjj",
+"_Z19rsGetElementAt_half13rs_allocationj",
+"_Z19rsGetElementAt_half13rs_allocationjj",
+"_Z19rsGetElementAt_half13rs_allocationjjj",
+"_Z19rsGetElementAt_int213rs_allocationj",
+"_Z19rsGetElementAt_int213rs_allocationjj",
+"_Z19rsGetElementAt_int213rs_allocationjjj",
+"_Z19rsGetElementAt_int313rs_allocationj",
+"_Z19rsGetElementAt_int313rs_allocationjj",
+"_Z19rsGetElementAt_int313rs_allocationjjj",
+"_Z19rsGetElementAt_int413rs_allocationj",
+"_Z19rsGetElementAt_int413rs_allocationjj",
+"_Z19rsGetElementAt_int413rs_allocationjjj",
+"_Z19rsGetElementAt_long13rs_allocationj",
+"_Z19rsGetElementAt_long13rs_allocationjj",
+"_Z19rsGetElementAt_long13rs_allocationjjj",
+"_Z19rsGetElementAt_uint13rs_allocationj",
+"_Z19rsGetElementAt_uint13rs_allocationjj",
+"_Z19rsGetElementAt_uint13rs_allocationjjj",
+"_Z19rsIsSphereInFrustumPDv4_fS0_S0_S0_S0_S0_S0_",
+"_Z19rsMatrixLoadFrustumP12rs_matrix4x4ffffff",
+"_Z19rsSetElementAt_char13rs_allocationcj",
+"_Z19rsSetElementAt_char13rs_allocationcjj",
+"_Z19rsSetElementAt_char13rs_allocationcjjj",
+"_Z19rsSetElementAt_half13rs_allocationDhj",
+"_Z19rsSetElementAt_half13rs_allocationDhjj",
+"_Z19rsSetElementAt_half13rs_allocationDhjjj",
+"_Z19rsSetElementAt_int213rs_allocationDv2_ij",
+"_Z19rsSetElementAt_int213rs_allocationDv2_ijj",
+"_Z19rsSetElementAt_int213rs_allocationDv2_ijjj",
+"_Z19rsSetElementAt_int313rs_allocationDv3_ij",
+"_Z19rsSetElementAt_int313rs_allocationDv3_ijj",
+"_Z19rsSetElementAt_int313rs_allocationDv3_ijjj",
+"_Z19rsSetElementAt_int413rs_allocationDv4_ij",
+"_Z19rsSetElementAt_int413rs_allocationDv4_ijj",
+"_Z19rsSetElementAt_int413rs_allocationDv4_ijjj",
+"_Z19rsSetElementAt_long13rs_allocationlj",
+"_Z19rsSetElementAt_long13rs_allocationljj",
+"_Z19rsSetElementAt_long13rs_allocationljjj",
+"_Z19rsSetElementAt_uint13rs_allocationjj",
+"_Z19rsSetElementAt_uint13rs_allocationjjj",
+"_Z19rsSetElementAt_uint13rs_allocationjjjj",
+"_Z19rsgBindProgramStore16rs_program_store",
+"_Z19rsgClearColorTargetj",
+"_Z19rsgClearDepthTargetv",
+"_Z19rsgMeshGetPrimitive7rs_meshj",
+"_Z20rsCreatePixelElement12rs_data_type12rs_data_kind",
+"_Z20rsElementGetDataKind10rs_element",
+"_Z20rsElementGetDataType10rs_element",
+"_Z20rsGetElementAt_char213rs_allocationj",
+"_Z20rsGetElementAt_char213rs_allocationjj",
+"_Z20rsGetElementAt_char213rs_allocationjjj",
+"_Z20rsGetElementAt_char313rs_allocationj",
+"_Z20rsGetElementAt_char313rs_allocationjj",
+"_Z20rsGetElementAt_char313rs_allocationjjj",
+"_Z20rsGetElementAt_char413rs_allocationj",
+"_Z20rsGetElementAt_char413rs_allocationjj",
+"_Z20rsGetElementAt_char413rs_allocationjjj",
+"_Z20rsGetElementAt_float13rs_allocationj",
+"_Z20rsGetElementAt_float13rs_allocationjj",
+"_Z20rsGetElementAt_float13rs_allocationjjj",
+"_Z20rsGetElementAt_half213rs_allocationj",
+"_Z20rsGetElementAt_half213rs_allocationjj",
+"_Z20rsGetElementAt_half213rs_allocationjjj",
+"_Z20rsGetElementAt_half313rs_allocationj",
+"_Z20rsGetElementAt_half313rs_allocationjj",
+"_Z20rsGetElementAt_half313rs_allocationjjj",
+"_Z20rsGetElementAt_half413rs_allocationj",
+"_Z20rsGetElementAt_half413rs_allocationjj",
+"_Z20rsGetElementAt_half413rs_allocationjjj",
+"_Z20rsGetElementAt_long213rs_allocationj",
+"_Z20rsGetElementAt_long213rs_allocationjj",
+"_Z20rsGetElementAt_long213rs_allocationjjj",
+"_Z20rsGetElementAt_long313rs_allocationj",
+"_Z20rsGetElementAt_long313rs_allocationjj",
+"_Z20rsGetElementAt_long313rs_allocationjjj",
+"_Z20rsGetElementAt_long413rs_allocationj",
+"_Z20rsGetElementAt_long413rs_allocationjj",
+"_Z20rsGetElementAt_long413rs_allocationjjj",
+"_Z20rsGetElementAt_short13rs_allocationj",
+"_Z20rsGetElementAt_short13rs_allocationjj",
+"_Z20rsGetElementAt_short13rs_allocationjjj",
+"_Z20rsGetElementAt_uchar13rs_allocationj",
+"_Z20rsGetElementAt_uchar13rs_allocationjj",
+"_Z20rsGetElementAt_uchar13rs_allocationjjj",
+"_Z20rsGetElementAt_uint213rs_allocationj",
+"_Z20rsGetElementAt_uint213rs_allocationjj",
+"_Z20rsGetElementAt_uint213rs_allocationjjj",
+"_Z20rsGetElementAt_uint313rs_allocationj",
+"_Z20rsGetElementAt_uint313rs_allocationjj",
+"_Z20rsGetElementAt_uint313rs_allocationjjj",
+"_Z20rsGetElementAt_uint413rs_allocationj",
+"_Z20rsGetElementAt_uint413rs_allocationjj",
+"_Z20rsGetElementAt_uint413rs_allocationjjj",
+"_Z20rsGetElementAt_ulong13rs_allocationj",
+"_Z20rsGetElementAt_ulong13rs_allocationjj",
+"_Z20rsGetElementAt_ulong13rs_allocationjjj",
+"_Z20rsMatrixLoadIdentityP12rs_matrix2x2",
+"_Z20rsMatrixLoadIdentityP12rs_matrix3x3",
+"_Z20rsMatrixLoadIdentityP12rs_matrix4x4",
+"_Z20rsMatrixLoadMultiplyP12rs_matrix2x2PKS_S2_",
+"_Z20rsMatrixLoadMultiplyP12rs_matrix3x3PKS_S2_",
+"_Z20rsMatrixLoadMultiplyP12rs_matrix4x4PKS_S2_",
+"_Z20rsQuaternionMultiplyPDv4_fPKS_",
+"_Z20rsQuaternionMultiplyPDv4_ff",
+"_Z20rsSetElementAt_char213rs_allocationDv2_cj",
+"_Z20rsSetElementAt_char213rs_allocationDv2_cjj",
+"_Z20rsSetElementAt_char213rs_allocationDv2_cjjj",
+"_Z20rsSetElementAt_char313rs_allocationDv3_cj",
+"_Z20rsSetElementAt_char313rs_allocationDv3_cjj",
+"_Z20rsSetElementAt_char313rs_allocationDv3_cjjj",
+"_Z20rsSetElementAt_char413rs_allocationDv4_cj",
+"_Z20rsSetElementAt_char413rs_allocationDv4_cjj",
+"_Z20rsSetElementAt_char413rs_allocationDv4_cjjj",
+"_Z20rsSetElementAt_float13rs_allocationfj",
+"_Z20rsSetElementAt_float13rs_allocationfjj",
+"_Z20rsSetElementAt_float13rs_allocationfjjj",
+"_Z20rsSetElementAt_half213rs_allocationDv2_Dhj",
+"_Z20rsSetElementAt_half213rs_allocationDv2_Dhjj",
+"_Z20rsSetElementAt_half213rs_allocationDv2_Dhjjj",
+"_Z20rsSetElementAt_half313rs_allocationDv3_Dhj",
+"_Z20rsSetElementAt_half313rs_allocationDv3_Dhjj",
+"_Z20rsSetElementAt_half313rs_allocationDv3_Dhjjj",
+"_Z20rsSetElementAt_half413rs_allocationDv4_Dhj",
+"_Z20rsSetElementAt_half413rs_allocationDv4_Dhjj",
+"_Z20rsSetElementAt_half413rs_allocationDv4_Dhjjj",
+"_Z20rsSetElementAt_long213rs_allocationDv2_lj",
+"_Z20rsSetElementAt_long213rs_allocationDv2_ljj",
+"_Z20rsSetElementAt_long213rs_allocationDv2_ljjj",
+"_Z20rsSetElementAt_long313rs_allocationDv3_lj",
+"_Z20rsSetElementAt_long313rs_allocationDv3_ljj",
+"_Z20rsSetElementAt_long313rs_allocationDv3_ljjj",
+"_Z20rsSetElementAt_long413rs_allocationDv4_lj",
+"_Z20rsSetElementAt_long413rs_allocationDv4_ljj",
+"_Z20rsSetElementAt_long413rs_allocationDv4_ljjj",
+"_Z20rsSetElementAt_short13rs_allocationsj",
+"_Z20rsSetElementAt_short13rs_allocationsjj",
+"_Z20rsSetElementAt_short13rs_allocationsjjj",
+"_Z20rsSetElementAt_uchar13rs_allocationhj",
+"_Z20rsSetElementAt_uchar13rs_allocationhjj",
+"_Z20rsSetElementAt_uchar13rs_allocationhjjj",
+"_Z20rsSetElementAt_uint213rs_allocationDv2_jj",
+"_Z20rsSetElementAt_uint213rs_allocationDv2_jjj",
+"_Z20rsSetElementAt_uint213rs_allocationDv2_jjjj",
+"_Z20rsSetElementAt_uint313rs_allocationDv3_jj",
+"_Z20rsSetElementAt_uint313rs_allocationDv3_jjj",
+"_Z20rsSetElementAt_uint313rs_allocationDv3_jjjj",
+"_Z20rsSetElementAt_uint413rs_allocationDv4_jj",
+"_Z20rsSetElementAt_uint413rs_allocationDv4_jjj",
+"_Z20rsSetElementAt_uint413rs_allocationDv4_jjjj",
+"_Z20rsSetElementAt_ulong13rs_allocationmj",
+"_Z20rsSetElementAt_ulong13rs_allocationmjj",
+"_Z20rsSetElementAt_ulong13rs_allocationmjjj",
+"_Z20rsSetElementAt_ulong13rs_allocationyj",
+"_Z20rsSetElementAt_ulong13rs_allocationyjj",
+"_Z20rsSetElementAt_ulong13rs_allocationyjjj",
+"_Z20rsgAllocationSyncAll13rs_allocation",
+"_Z20rsgAllocationSyncAll13rs_allocation24rs_allocation_usage_type",
+"_Z20rsgBindProgramRaster17rs_program_raster",
+"_Z20rsgBindProgramVertex17rs_program_vertex",
+"_Z20rsgDrawQuadTexCoordsffffffffffffffffffff",
+"_Z21rsAllocationGetDimLOD13rs_allocation",
+"_Z21rsAllocationIoReceive13rs_allocation",
+"_Z21rsCreateVectorElement12rs_data_typej",
+"_Z21rsElementGetBytesSize10rs_element",
+"_Z21rsGetElementAt_double13rs_allocationj",
+"_Z21rsGetElementAt_double13rs_allocationjj",
+"_Z21rsGetElementAt_double13rs_allocationjjj",
+"_Z21rsGetElementAt_float213rs_allocationj",
+"_Z21rsGetElementAt_float213rs_allocationjj",
+"_Z21rsGetElementAt_float213rs_allocationjjj",
+"_Z21rsGetElementAt_float313rs_allocationj",
+"_Z21rsGetElementAt_float313rs_allocationjj",
+"_Z21rsGetElementAt_float313rs_allocationjjj",
+"_Z21rsGetElementAt_float413rs_allocationj",
+"_Z21rsGetElementAt_float413rs_allocationjj",
+"_Z21rsGetElementAt_float413rs_allocationjjj",
+"_Z21rsGetElementAt_short213rs_allocationj",
+"_Z21rsGetElementAt_short213rs_allocationjj",
+"_Z21rsGetElementAt_short213rs_allocationjjj",
+"_Z21rsGetElementAt_short313rs_allocationj",
+"_Z21rsGetElementAt_short313rs_allocationjj",
+"_Z21rsGetElementAt_short313rs_allocationjjj",
+"_Z21rsGetElementAt_short413rs_allocationj",
+"_Z21rsGetElementAt_short413rs_allocationjj",
+"_Z21rsGetElementAt_short413rs_allocationjjj",
+"_Z21rsGetElementAt_uchar213rs_allocationj",
+"_Z21rsGetElementAt_uchar213rs_allocationjj",
+"_Z21rsGetElementAt_uchar213rs_allocationjjj",
+"_Z21rsGetElementAt_uchar313rs_allocationj",
+"_Z21rsGetElementAt_uchar313rs_allocationjj",
+"_Z21rsGetElementAt_uchar313rs_allocationjjj",
+"_Z21rsGetElementAt_uchar413rs_allocationj",
+"_Z21rsGetElementAt_uchar413rs_allocationjj",
+"_Z21rsGetElementAt_uchar413rs_allocationjjj",
+"_Z21rsGetElementAt_ulong213rs_allocationj",
+"_Z21rsGetElementAt_ulong213rs_allocationjj",
+"_Z21rsGetElementAt_ulong213rs_allocationjjj",
+"_Z21rsGetElementAt_ulong313rs_allocationj",
+"_Z21rsGetElementAt_ulong313rs_allocationjj",
+"_Z21rsGetElementAt_ulong313rs_allocationjjj",
+"_Z21rsGetElementAt_ulong413rs_allocationj",
+"_Z21rsGetElementAt_ulong413rs_allocationjj",
+"_Z21rsGetElementAt_ulong413rs_allocationjjj",
+"_Z21rsGetElementAt_ushort13rs_allocationj",
+"_Z21rsGetElementAt_ushort13rs_allocationjj",
+"_Z21rsGetElementAt_ushort13rs_allocationjjj",
+"_Z21rsMatrixLoadTranslateP12rs_matrix4x4fff",
+"_Z21rsQuaternionConjugatePDv4_f",
+"_Z21rsQuaternionNormalizePDv4_f",
+"_Z21rsSetElementAt_double13rs_allocationdj",
+"_Z21rsSetElementAt_double13rs_allocationdjj",
+"_Z21rsSetElementAt_double13rs_allocationdjjj",
+"_Z21rsSetElementAt_float213rs_allocationDv2_fj",
+"_Z21rsSetElementAt_float213rs_allocationDv2_fjj",
+"_Z21rsSetElementAt_float213rs_allocationDv2_fjjj",
+"_Z21rsSetElementAt_float313rs_allocationDv3_fj",
+"_Z21rsSetElementAt_float313rs_allocationDv3_fjj",
+"_Z21rsSetElementAt_float313rs_allocationDv3_fjjj",
+"_Z21rsSetElementAt_float413rs_allocationDv4_fj",
+"_Z21rsSetElementAt_float413rs_allocationDv4_fjj",
+"_Z21rsSetElementAt_float413rs_allocationDv4_fjjj",
+"_Z21rsSetElementAt_short213rs_allocationDv2_sj",
+"_Z21rsSetElementAt_short213rs_allocationDv2_sjj",
+"_Z21rsSetElementAt_short213rs_allocationDv2_sjjj",
+"_Z21rsSetElementAt_short313rs_allocationDv3_sj",
+"_Z21rsSetElementAt_short313rs_allocationDv3_sjj",
+"_Z21rsSetElementAt_short313rs_allocationDv3_sjjj",
+"_Z21rsSetElementAt_short413rs_allocationDv4_sj",
+"_Z21rsSetElementAt_short413rs_allocationDv4_sjj",
+"_Z21rsSetElementAt_short413rs_allocationDv4_sjjj",
+"_Z21rsSetElementAt_uchar213rs_allocationDv2_hj",
+"_Z21rsSetElementAt_uchar213rs_allocationDv2_hjj",
+"_Z21rsSetElementAt_uchar213rs_allocationDv2_hjjj",
+"_Z21rsSetElementAt_uchar313rs_allocationDv3_hj",
+"_Z21rsSetElementAt_uchar313rs_allocationDv3_hjj",
+"_Z21rsSetElementAt_uchar313rs_allocationDv3_hjjj",
+"_Z21rsSetElementAt_uchar413rs_allocationDv4_hj",
+"_Z21rsSetElementAt_uchar413rs_allocationDv4_hjj",
+"_Z21rsSetElementAt_uchar413rs_allocationDv4_hjjj",
+"_Z21rsSetElementAt_ulong213rs_allocationDv2_mj",
+"_Z21rsSetElementAt_ulong213rs_allocationDv2_mjj",
+"_Z21rsSetElementAt_ulong213rs_allocationDv2_mjjj",
+"_Z21rsSetElementAt_ulong213rs_allocationDv2_yj",
+"_Z21rsSetElementAt_ulong213rs_allocationDv2_yjj",
+"_Z21rsSetElementAt_ulong213rs_allocationDv2_yjjj",
+"_Z21rsSetElementAt_ulong313rs_allocationDv3_mj",
+"_Z21rsSetElementAt_ulong313rs_allocationDv3_mjj",
+"_Z21rsSetElementAt_ulong313rs_allocationDv3_mjjj",
+"_Z21rsSetElementAt_ulong313rs_allocationDv3_yj",
+"_Z21rsSetElementAt_ulong313rs_allocationDv3_yjj",
+"_Z21rsSetElementAt_ulong313rs_allocationDv3_yjjj",
+"_Z21rsSetElementAt_ulong413rs_allocationDv4_mj",
+"_Z21rsSetElementAt_ulong413rs_allocationDv4_mjj",
+"_Z21rsSetElementAt_ulong413rs_allocationDv4_mjjj",
+"_Z21rsSetElementAt_ulong413rs_allocationDv4_yj",
+"_Z21rsSetElementAt_ulong413rs_allocationDv4_yjj",
+"_Z21rsSetElementAt_ulong413rs_allocationDv4_yjjj",
+"_Z21rsSetElementAt_ushort13rs_allocationtj",
+"_Z21rsSetElementAt_ushort13rs_allocationtjj",
+"_Z21rsSetElementAt_ushort13rs_allocationtjjj",
+"_Z22rsAllocationGetElement13rs_allocation",
+"_Z22rsElementGetSubElement10rs_elementj",
+"_Z22rsElementGetVectorSize10rs_element",
+"_Z22rsExtractFrustumPlanesPK12rs_matrix4x4PDv4_fS3_S3_S3_S3_S3_",
+"_Z22rsGetElementAt_double213rs_allocationj",
+"_Z22rsGetElementAt_double213rs_allocationjj",
+"_Z22rsGetElementAt_double213rs_allocationjjj",
+"_Z22rsGetElementAt_double313rs_allocationj",
+"_Z22rsGetElementAt_double313rs_allocationjj",
+"_Z22rsGetElementAt_double313rs_allocationjjj",
+"_Z22rsGetElementAt_double413rs_allocationj",
+"_Z22rsGetElementAt_double413rs_allocationjj",
+"_Z22rsGetElementAt_double413rs_allocationjjj",
+"_Z22rsGetElementAt_ushort213rs_allocationj",
+"_Z22rsGetElementAt_ushort213rs_allocationjj",
+"_Z22rsGetElementAt_ushort213rs_allocationjjj",
+"_Z22rsGetElementAt_ushort313rs_allocationj",
+"_Z22rsGetElementAt_ushort313rs_allocationjj",
+"_Z22rsGetElementAt_ushort313rs_allocationjjj",
+"_Z22rsGetElementAt_ushort413rs_allocationj",
+"_Z22rsGetElementAt_ushort413rs_allocationjj",
+"_Z22rsGetElementAt_ushort413rs_allocationjjj",
+"_Z22rsQuaternionLoadRotatePDv4_fffff",
+"_Z22rsSamplerGetAnisotropy10rs_sampler",
+"_Z22rsSendToClientBlockingi",
+"_Z22rsSendToClientBlockingiPKvj",
+"_Z22rsSetElementAt_double213rs_allocationDv2_dj",
+"_Z22rsSetElementAt_double213rs_allocationDv2_djj",
+"_Z22rsSetElementAt_double213rs_allocationDv2_djjj",
+"_Z22rsSetElementAt_double313rs_allocationDv3_dj",
+"_Z22rsSetElementAt_double313rs_allocationDv3_djj",
+"_Z22rsSetElementAt_double313rs_allocationDv3_djjj",
+"_Z22rsSetElementAt_double413rs_allocationDv4_dj",
+"_Z22rsSetElementAt_double413rs_allocationDv4_djj",
+"_Z22rsSetElementAt_double413rs_allocationDv4_djjj",
+"_Z22rsSetElementAt_ushort213rs_allocationDv2_tj",
+"_Z22rsSetElementAt_ushort213rs_allocationDv2_tjj",
+"_Z22rsSetElementAt_ushort213rs_allocationDv2_tjjj",
+"_Z22rsSetElementAt_ushort313rs_allocationDv3_tj",
+"_Z22rsSetElementAt_ushort313rs_allocationDv3_tjj",
+"_Z22rsSetElementAt_ushort313rs_allocationDv3_tjjj",
+"_Z22rsSetElementAt_ushort413rs_allocationDv4_tj",
+"_Z22rsSetElementAt_ushort413rs_allocationDv4_tjj",
+"_Z22rsSetElementAt_ushort413rs_allocationDv4_tjjj",
+"_Z22rsgBindProgramFragment19rs_program_fragment",
+"_Z23rsAllocationCopy1DRange13rs_allocationjjjS_jj",
+"_Z23rsAllocationCopy2DRange13rs_allocationjjj26rs_allocation_cubemap_facejjS_jjjS0_",
+"_Z23rsAllocationGetDimFaces13rs_allocation",
+"_Z23rsAllocationVLoadX_int213rs_allocationj",
+"_Z23rsAllocationVLoadX_int213rs_allocationjj",
+"_Z23rsAllocationVLoadX_int213rs_allocationjjj",
+"_Z23rsAllocationVLoadX_int313rs_allocationj",
+"_Z23rsAllocationVLoadX_int313rs_allocationjj",
+"_Z23rsAllocationVLoadX_int313rs_allocationjjj",
+"_Z23rsAllocationVLoadX_int413rs_allocationj",
+"_Z23rsAllocationVLoadX_int413rs_allocationjj",
+"_Z23rsAllocationVLoadX_int413rs_allocationjjj",
+"_Z23rsMatrixLoadPerspectiveP12rs_matrix4x4ffff",
+"_Z24rsAllocationVLoadX_char213rs_allocationj",
+"_Z24rsAllocationVLoadX_char213rs_allocationjj",
+"_Z24rsAllocationVLoadX_char213rs_allocationjjj",
+"_Z24rsAllocationVLoadX_char313rs_allocationj",
+"_Z24rsAllocationVLoadX_char313rs_allocationjj",
+"_Z24rsAllocationVLoadX_char313rs_allocationjjj",
+"_Z24rsAllocationVLoadX_char413rs_allocationj",
+"_Z24rsAllocationVLoadX_char413rs_allocationjj",
+"_Z24rsAllocationVLoadX_char413rs_allocationjjj",
+"_Z24rsAllocationVLoadX_long213rs_allocationj",
+"_Z24rsAllocationVLoadX_long213rs_allocationjj",
+"_Z24rsAllocationVLoadX_long213rs_allocationjjj",
+"_Z24rsAllocationVLoadX_long313rs_allocationj",
+"_Z24rsAllocationVLoadX_long313rs_allocationjj",
+"_Z24rsAllocationVLoadX_long313rs_allocationjjj",
+"_Z24rsAllocationVLoadX_long413rs_allocationj",
+"_Z24rsAllocationVLoadX_long413rs_allocationjj",
+"_Z24rsAllocationVLoadX_long413rs_allocationjjj",
+"_Z24rsAllocationVLoadX_uint213rs_allocationj",
+"_Z24rsAllocationVLoadX_uint213rs_allocationjj",
+"_Z24rsAllocationVLoadX_uint213rs_allocationjjj",
+"_Z24rsAllocationVLoadX_uint313rs_allocationj",
+"_Z24rsAllocationVLoadX_uint313rs_allocationjj",
+"_Z24rsAllocationVLoadX_uint313rs_allocationjjj",
+"_Z24rsAllocationVLoadX_uint413rs_allocationj",
+"_Z24rsAllocationVLoadX_uint413rs_allocationjj",
+"_Z24rsAllocationVLoadX_uint413rs_allocationjjj",
+"_Z24rsAllocationVStoreX_int213rs_allocationDv2_ij",
+"_Z24rsAllocationVStoreX_int213rs_allocationDv2_ijj",
+"_Z24rsAllocationVStoreX_int213rs_allocationDv2_ijjj",
+"_Z24rsAllocationVStoreX_int313rs_allocationDv3_ij",
+"_Z24rsAllocationVStoreX_int313rs_allocationDv3_ijj",
+"_Z24rsAllocationVStoreX_int313rs_allocationDv3_ijjj",
+"_Z24rsAllocationVStoreX_int413rs_allocationDv4_ij",
+"_Z24rsAllocationVStoreX_int413rs_allocationDv4_ijj",
+"_Z24rsAllocationVStoreX_int413rs_allocationDv4_ijjj",
+"_Z24rsMatrixInverseTransposeP12rs_matrix4x4",
+"_Z24rsSamplerGetMinification10rs_sampler",
+"_Z24rsgClearAllRenderTargetsv",
+"_Z24rsgDrawSpriteScreenspacefffff",
+"_Z24rsgMeshGetPrimitiveCount7rs_mesh",
+"_Z25rsAllocationVLoadX_float213rs_allocationj",
+"_Z25rsAllocationVLoadX_float213rs_allocationjj",
+"_Z25rsAllocationVLoadX_float213rs_allocationjjj",
+"_Z25rsAllocationVLoadX_float313rs_allocationj",
+"_Z25rsAllocationVLoadX_float313rs_allocationjj",
+"_Z25rsAllocationVLoadX_float313rs_allocationjjj",
+"_Z25rsAllocationVLoadX_float413rs_allocationj",
+"_Z25rsAllocationVLoadX_float413rs_allocationjj",
+"_Z25rsAllocationVLoadX_float413rs_allocationjjj",
+"_Z25rsAllocationVLoadX_short213rs_allocationj",
+"_Z25rsAllocationVLoadX_short213rs_allocationjj",
+"_Z25rsAllocationVLoadX_short213rs_allocationjjj",
+"_Z25rsAllocationVLoadX_short313rs_allocationj",
+"_Z25rsAllocationVLoadX_short313rs_allocationjj",
+"_Z25rsAllocationVLoadX_short313rs_allocationjjj",
+"_Z25rsAllocationVLoadX_short413rs_allocationj",
+"_Z25rsAllocationVLoadX_short413rs_allocationjj",
+"_Z25rsAllocationVLoadX_short413rs_allocationjjj",
+"_Z25rsAllocationVLoadX_uchar213rs_allocationj",
+"_Z25rsAllocationVLoadX_uchar213rs_allocationjj",
+"_Z25rsAllocationVLoadX_uchar213rs_allocationjjj",
+"_Z25rsAllocationVLoadX_uchar313rs_allocationj",
+"_Z25rsAllocationVLoadX_uchar313rs_allocationjj",
+"_Z25rsAllocationVLoadX_uchar313rs_allocationjjj",
+"_Z25rsAllocationVLoadX_uchar413rs_allocationj",
+"_Z25rsAllocationVLoadX_uchar413rs_allocationjj",
+"_Z25rsAllocationVLoadX_uchar413rs_allocationjjj",
+"_Z25rsAllocationVLoadX_ulong213rs_allocationj",
+"_Z25rsAllocationVLoadX_ulong213rs_allocationjj",
+"_Z25rsAllocationVLoadX_ulong213rs_allocationjjj",
+"_Z25rsAllocationVLoadX_ulong313rs_allocationj",
+"_Z25rsAllocationVLoadX_ulong313rs_allocationjj",
+"_Z25rsAllocationVLoadX_ulong313rs_allocationjjj",
+"_Z25rsAllocationVLoadX_ulong413rs_allocationj",
+"_Z25rsAllocationVLoadX_ulong413rs_allocationjj",
+"_Z25rsAllocationVLoadX_ulong413rs_allocationjjj",
+"_Z25rsAllocationVStoreX_char213rs_allocationDv2_cj",
+"_Z25rsAllocationVStoreX_char213rs_allocationDv2_cjj",
+"_Z25rsAllocationVStoreX_char213rs_allocationDv2_cjjj",
+"_Z25rsAllocationVStoreX_char313rs_allocationDv3_cj",
+"_Z25rsAllocationVStoreX_char313rs_allocationDv3_cjj",
+"_Z25rsAllocationVStoreX_char313rs_allocationDv3_cjjj",
+"_Z25rsAllocationVStoreX_char413rs_allocationDv4_cj",
+"_Z25rsAllocationVStoreX_char413rs_allocationDv4_cjj",
+"_Z25rsAllocationVStoreX_char413rs_allocationDv4_cjjj",
+"_Z25rsAllocationVStoreX_long213rs_allocationDv2_lj",
+"_Z25rsAllocationVStoreX_long213rs_allocationDv2_ljj",
+"_Z25rsAllocationVStoreX_long213rs_allocationDv2_ljjj",
+"_Z25rsAllocationVStoreX_long313rs_allocationDv3_lj",
+"_Z25rsAllocationVStoreX_long313rs_allocationDv3_ljj",
+"_Z25rsAllocationVStoreX_long313rs_allocationDv3_ljjj",
+"_Z25rsAllocationVStoreX_long413rs_allocationDv4_lj",
+"_Z25rsAllocationVStoreX_long413rs_allocationDv4_ljj",
+"_Z25rsAllocationVStoreX_long413rs_allocationDv4_ljjj",
+"_Z25rsAllocationVStoreX_uint213rs_allocationDv2_jj",
+"_Z25rsAllocationVStoreX_uint213rs_allocationDv2_jjj",
+"_Z25rsAllocationVStoreX_uint213rs_allocationDv2_jjjj",
+"_Z25rsAllocationVStoreX_uint313rs_allocationDv3_jj",
+"_Z25rsAllocationVStoreX_uint313rs_allocationDv3_jjj",
+"_Z25rsAllocationVStoreX_uint313rs_allocationDv3_jjjj",
+"_Z25rsAllocationVStoreX_uint413rs_allocationDv4_jj",
+"_Z25rsAllocationVStoreX_uint413rs_allocationDv4_jjj",
+"_Z25rsAllocationVStoreX_uint413rs_allocationDv4_jjjj",
+"_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj",
+"_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj",
+"_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj",
+"_Z25rsQuaternionGetMatrixUnitP12rs_matrix4x4PKDv4_f",
+"_Z25rsSamplerGetMagnification10rs_sampler",
+"_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_",
+"_Z25rsgMeshGetIndexAllocation7rs_meshj",
+"_Z26rsAllocationVLoadX_double213rs_allocationj",
+"_Z26rsAllocationVLoadX_double213rs_allocationjj",
+"_Z26rsAllocationVLoadX_double213rs_allocationjjj",
+"_Z26rsAllocationVLoadX_double313rs_allocationj",
+"_Z26rsAllocationVLoadX_double313rs_allocationjj",
+"_Z26rsAllocationVLoadX_double313rs_allocationjjj",
+"_Z26rsAllocationVLoadX_double413rs_allocationj",
+"_Z26rsAllocationVLoadX_double413rs_allocationjj",
+"_Z26rsAllocationVLoadX_double413rs_allocationjjj",
+"_Z26rsAllocationVLoadX_ushort213rs_allocationj",
+"_Z26rsAllocationVLoadX_ushort213rs_allocationjj",
+"_Z26rsAllocationVLoadX_ushort213rs_allocationjjj",
+"_Z26rsAllocationVLoadX_ushort313rs_allocationj",
+"_Z26rsAllocationVLoadX_ushort313rs_allocationjj",
+"_Z26rsAllocationVLoadX_ushort313rs_allocationjjj",
+"_Z26rsAllocationVLoadX_ushort413rs_allocationj",
+"_Z26rsAllocationVLoadX_ushort413rs_allocationjj",
+"_Z26rsAllocationVLoadX_ushort413rs_allocationjjj",
+"_Z26rsAllocationVStoreX_float213rs_allocationDv2_fj",
+"_Z26rsAllocationVStoreX_float213rs_allocationDv2_fjj",
+"_Z26rsAllocationVStoreX_float213rs_allocationDv2_fjjj",
+"_Z26rsAllocationVStoreX_float313rs_allocationDv3_fj",
+"_Z26rsAllocationVStoreX_float313rs_allocationDv3_fjj",
+"_Z26rsAllocationVStoreX_float313rs_allocationDv3_fjjj",
+"_Z26rsAllocationVStoreX_float413rs_allocationDv4_fj",
+"_Z26rsAllocationVStoreX_float413rs_allocationDv4_fjj",
+"_Z26rsAllocationVStoreX_float413rs_allocationDv4_fjjj",
+"_Z26rsAllocationVStoreX_short213rs_allocationDv2_sj",
+"_Z26rsAllocationVStoreX_short213rs_allocationDv2_sjj",
+"_Z26rsAllocationVStoreX_short213rs_allocationDv2_sjjj",
+"_Z26rsAllocationVStoreX_short313rs_allocationDv3_sj",
+"_Z26rsAllocationVStoreX_short313rs_allocationDv3_sjj",
+"_Z26rsAllocationVStoreX_short313rs_allocationDv3_sjjj",
+"_Z26rsAllocationVStoreX_short413rs_allocationDv4_sj",
+"_Z26rsAllocationVStoreX_short413rs_allocationDv4_sjj",
+"_Z26rsAllocationVStoreX_short413rs_allocationDv4_sjjj",
+"_Z26rsAllocationVStoreX_uchar213rs_allocationDv2_hj",
+"_Z26rsAllocationVStoreX_uchar213rs_allocationDv2_hjj",
+"_Z26rsAllocationVStoreX_uchar213rs_allocationDv2_hjjj",
+"_Z26rsAllocationVStoreX_uchar313rs_allocationDv3_hj",
+"_Z26rsAllocationVStoreX_uchar313rs_allocationDv3_hjj",
+"_Z26rsAllocationVStoreX_uchar313rs_allocationDv3_hjjj",
+"_Z26rsAllocationVStoreX_uchar413rs_allocationDv4_hj",
+"_Z26rsAllocationVStoreX_uchar413rs_allocationDv4_hjj",
+"_Z26rsAllocationVStoreX_uchar413rs_allocationDv4_hjjj",
+"_Z26rsAllocationVStoreX_ulong213rs_allocationDv2_mj",
+"_Z26rsAllocationVStoreX_ulong213rs_allocationDv2_mjj",
+"_Z26rsAllocationVStoreX_ulong213rs_allocationDv2_mjjj",
+"_Z26rsAllocationVStoreX_ulong313rs_allocationDv3_mj",
+"_Z26rsAllocationVStoreX_ulong313rs_allocationDv3_mjj",
+"_Z26rsAllocationVStoreX_ulong313rs_allocationDv3_mjjj",
+"_Z26rsAllocationVStoreX_ulong413rs_allocationDv4_mj",
+"_Z26rsAllocationVStoreX_ulong413rs_allocationDv4_mjj",
+"_Z26rsAllocationVStoreX_ulong413rs_allocationDv4_mjjj",
+"_Z26rsElementGetSubElementName10rs_elementjPcj",
+"_Z26rsQuaternionLoadRotateUnitPDv4_fffff",
+"_Z26rsgMeshGetVertexAllocation7rs_meshj",
+"_Z27rsAllocationVStoreX_double213rs_allocationDv2_dj",
+"_Z27rsAllocationVStoreX_double213rs_allocationDv2_djj",
+"_Z27rsAllocationVStoreX_double213rs_allocationDv2_djjj",
+"_Z27rsAllocationVStoreX_double313rs_allocationDv3_dj",
+"_Z27rsAllocationVStoreX_double313rs_allocationDv3_djj",
+"_Z27rsAllocationVStoreX_double313rs_allocationDv3_djjj",
+"_Z27rsAllocationVStoreX_double413rs_allocationDv4_dj",
+"_Z27rsAllocationVStoreX_double413rs_allocationDv4_djj",
+"_Z27rsAllocationVStoreX_double413rs_allocationDv4_djjj",
+"_Z27rsAllocationVStoreX_ushort213rs_allocationDv2_tj",
+"_Z27rsAllocationVStoreX_ushort213rs_allocationDv2_tjj",
+"_Z27rsAllocationVStoreX_ushort213rs_allocationDv2_tjjj",
+"_Z27rsAllocationVStoreX_ushort313rs_allocationDv3_tj",
+"_Z27rsAllocationVStoreX_ushort313rs_allocationDv3_tjj",
+"_Z27rsAllocationVStoreX_ushort313rs_allocationDv3_tjjj",
+"_Z27rsAllocationVStoreX_ushort413rs_allocationDv4_tj",
+"_Z27rsAllocationVStoreX_ushort413rs_allocationDv4_tjj",
+"_Z27rsAllocationVStoreX_ushort413rs_allocationDv4_tjjj",
+"_Z27rsElementGetSubElementCount10rs_element",
+"_Z27rsgProgramRasterGetCullMode17rs_program_raster",
+"_Z27rsgProgramStoreGetDepthFunc16rs_program_store",
+"_Z30rsgProgramStoreGetBlendDstFunc16rs_program_store",
+"_Z30rsgProgramStoreGetBlendSrcFunc16rs_program_store",
+"_Z30rsgProgramStoreIsDitherEnabled16rs_program_store",
+"_Z31rsElementGetSubElementArraySize10rs_elementj",
+"_Z31rsgMeshGetVertexAllocationCount7rs_mesh",
+"_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff",
+"_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4",
+"_Z32rsElementGetSubElementNameLength10rs_elementj",
+"_Z33rsElementGetSubElementOffsetBytes10rs_elementj",
+"_Z33rsgProgramStoreIsDepthMaskEnabled16rs_program_store",
+"_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4",
+"_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4",
+"_Z36rsgProgramRasterIsPointSpriteEnabled17rs_program_raster",
+"_Z36rsgProgramStoreIsColorMaskRedEnabled16rs_program_store",
+"_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4",
+"_Z37rsgProgramStoreIsColorMaskBlueEnabled16rs_program_store",
+"_Z38rsgProgramStoreIsColorMaskAlphaEnabled16rs_program_store",
+"_Z38rsgProgramStoreIsColorMaskGreenEnabled16rs_program_store",
+"_Z3absDv2_c",
+"_Z3absDv2_i",
+"_Z3absDv2_s",
+"_Z3absDv3_c",
+"_Z3absDv3_i",
+"_Z3absDv3_s",
+"_Z3absDv4_c",
+"_Z3absDv4_i",
+"_Z3absDv4_s",
+"_Z3absc",
+"_Z3absi",
+"_Z3abss",
+"_Z3clzDv2_c",
+"_Z3clzDv2_h",
+"_Z3clzDv2_i",
+"_Z3clzDv2_j",
+"_Z3clzDv2_s",
+"_Z3clzDv2_t",
+"_Z3clzDv3_c",
+"_Z3clzDv3_h",
+"_Z3clzDv3_i",
+"_Z3clzDv3_j",
+"_Z3clzDv3_s",
+"_Z3clzDv3_t",
+"_Z3clzDv4_c",
+"_Z3clzDv4_h",
+"_Z3clzDv4_i",
+"_Z3clzDv4_j",
+"_Z3clzDv4_s",
+"_Z3clzDv4_t",
+"_Z3clzc",
+"_Z3clzh",
+"_Z3clzi",
+"_Z3clzj",
+"_Z3clzs",
+"_Z3clzt",
+"_Z3cosDh",
+"_Z3cosDv2_Dh",
+"_Z3cosDv2_f",
+"_Z3cosDv3_Dh",
+"_Z3cosDv3_f",
+"_Z3cosDv4_Dh",
+"_Z3cosDv4_f",
+"_Z3cosf",
+"_Z3dotDhDh",
+"_Z3dotDv2_DhS_",
+"_Z3dotDv2_fS_",
+"_Z3dotDv3_DhS_",
+"_Z3dotDv3_fS_",
+"_Z3dotDv4_DhS_",
+"_Z3dotDv4_fS_",
+"_Z3dotff",
+"_Z3erfDh",
+"_Z3erfDv2_Dh",
+"_Z3erfDv2_f",
+"_Z3erfDv3_Dh",
+"_Z3erfDv3_f",
+"_Z3erfDv4_Dh",
+"_Z3erfDv4_f",
+"_Z3erff",
+"_Z3expDh",
+"_Z3expDv2_Dh",
+"_Z3expDv2_f",
+"_Z3expDv3_Dh",
+"_Z3expDv3_f",
+"_Z3expDv4_Dh",
+"_Z3expDv4_f",
+"_Z3expf",
+"_Z3fmaDhDhDh",
+"_Z3fmaDv2_DhS_S_",
+"_Z3fmaDv2_fS_S_",
+"_Z3fmaDv3_DhS_S_",
+"_Z3fmaDv3_fS_S_",
+"_Z3fmaDv4_DhS_S_",
+"_Z3fmaDv4_fS_S_",
+"_Z3fmafff",
+"_Z3logDh",
+"_Z3logDv2_Dh",
+"_Z3logDv2_f",
+"_Z3logDv3_Dh",
+"_Z3logDv3_f",
+"_Z3logDv4_Dh",
+"_Z3logDv4_f",
+"_Z3logf",
+"_Z3madDhDhDh",
+"_Z3madDv2_DhS_S_",
+"_Z3madDv2_fS_S_",
+"_Z3madDv3_DhS_S_",
+"_Z3madDv3_fS_S_",
+"_Z3madDv4_DhS_S_",
+"_Z3madDv4_fS_S_",
+"_Z3madfff",
+"_Z3maxDhDh",
+"_Z3maxDv2_DhDh",
+"_Z3maxDv2_DhS_",
+"_Z3maxDv2_cS_",
+"_Z3maxDv2_fS_",
+"_Z3maxDv2_ff",
+"_Z3maxDv2_hS_",
+"_Z3maxDv2_iS_",
+"_Z3maxDv2_jS_",
+"_Z3maxDv2_lS_",
+"_Z3maxDv2_mS_",
+"_Z3maxDv2_sS_",
+"_Z3maxDv2_tS_",
+"_Z3maxDv3_DhDh",
+"_Z3maxDv3_DhS_",
+"_Z3maxDv3_cS_",
+"_Z3maxDv3_fS_",
+"_Z3maxDv3_ff",
+"_Z3maxDv3_hS_",
+"_Z3maxDv3_iS_",
+"_Z3maxDv3_jS_",
+"_Z3maxDv3_lS_",
+"_Z3maxDv3_mS_",
+"_Z3maxDv3_sS_",
+"_Z3maxDv3_tS_",
+"_Z3maxDv4_DhDh",
+"_Z3maxDv4_DhS_",
+"_Z3maxDv4_cS_",
+"_Z3maxDv4_fS_",
+"_Z3maxDv4_ff",
+"_Z3maxDv4_hS_",
+"_Z3maxDv4_iS_",
+"_Z3maxDv4_jS_",
+"_Z3maxDv4_lS_",
+"_Z3maxDv4_mS_",
+"_Z3maxDv4_sS_",
+"_Z3maxDv4_tS_",
+"_Z3maxcc",
+"_Z3maxff",
+"_Z3maxhh",
+"_Z3maxii",
+"_Z3maxjj",
+"_Z3maxll",
+"_Z3maxmm",
+"_Z3maxss",
+"_Z3maxtt",
+"_Z3minDhDh",
+"_Z3minDv2_DhDh",
+"_Z3minDv2_DhS_",
+"_Z3minDv2_cS_",
+"_Z3minDv2_fS_",
+"_Z3minDv2_ff",
+"_Z3minDv2_hS_",
+"_Z3minDv2_iS_",
+"_Z3minDv2_jS_",
+"_Z3minDv2_lS_",
+"_Z3minDv2_mS_",
+"_Z3minDv2_sS_",
+"_Z3minDv2_tS_",
+"_Z3minDv3_DhDh",
+"_Z3minDv3_DhS_",
+"_Z3minDv3_cS_",
+"_Z3minDv3_fS_",
+"_Z3minDv3_ff",
+"_Z3minDv3_hS_",
+"_Z3minDv3_iS_",
+"_Z3minDv3_jS_",
+"_Z3minDv3_lS_",
+"_Z3minDv3_mS_",
+"_Z3minDv3_sS_",
+"_Z3minDv3_tS_",
+"_Z3minDv4_DhDh",
+"_Z3minDv4_DhS_",
+"_Z3minDv4_cS_",
+"_Z3minDv4_fS_",
+"_Z3minDv4_ff",
+"_Z3minDv4_hS_",
+"_Z3minDv4_iS_",
+"_Z3minDv4_jS_",
+"_Z3minDv4_lS_",
+"_Z3minDv4_mS_",
+"_Z3minDv4_sS_",
+"_Z3minDv4_tS_",
+"_Z3mincc",
+"_Z3minff",
+"_Z3minhh",
+"_Z3minii",
+"_Z3minjj",
+"_Z3minll",
+"_Z3minmm",
+"_Z3minss",
+"_Z3mintt",
+"_Z3mixDhDhDh",
+"_Z3mixDv2_DhS_Dh",
+"_Z3mixDv2_DhS_S_",
+"_Z3mixDv2_fS_S_",
+"_Z3mixDv2_fS_f",
+"_Z3mixDv3_DhS_Dh",
+"_Z3mixDv3_DhS_S_",
+"_Z3mixDv3_fS_S_",
+"_Z3mixDv3_fS_f",
+"_Z3mixDv4_DhS_Dh",
+"_Z3mixDv4_DhS_S_",
+"_Z3mixDv4_fS_S_",
+"_Z3mixDv4_fS_f",
+"_Z3mixfff",
+"_Z3nanj",
+"_Z3powDhDh",
+"_Z3powDv2_DhS_",
+"_Z3powDv2_fS_",
+"_Z3powDv3_DhS_",
+"_Z3powDv3_fS_",
+"_Z3powDv4_DhS_",
+"_Z3powDv4_fS_",
+"_Z3powff",
+"_Z3sinDh",
+"_Z3sinDv2_Dh",
+"_Z3sinDv2_f",
+"_Z3sinDv3_Dh",
+"_Z3sinDv3_f",
+"_Z3sinDv4_Dh",
+"_Z3sinDv4_f",
+"_Z3sinf",
+"_Z3tanDh",
+"_Z3tanDv2_Dh",
+"_Z3tanDv2_f",
+"_Z3tanDv3_Dh",
+"_Z3tanDv3_f",
+"_Z3tanDv4_Dh",
+"_Z3tanDv4_f",
+"_Z3tanf",
+"_Z4acosDh",
+"_Z4acosDv2_Dh",
+"_Z4acosDv2_f",
+"_Z4acosDv3_Dh",
+"_Z4acosDv3_f",
+"_Z4acosDv4_Dh",
+"_Z4acosDv4_f",
+"_Z4acosf",
+"_Z4asinDh",
+"_Z4asinDv2_Dh",
+"_Z4asinDv2_f",
+"_Z4asinDv3_Dh",
+"_Z4asinDv3_f",
+"_Z4asinDv4_Dh",
+"_Z4asinDv4_f",
+"_Z4asinf",
+"_Z4atanDh",
+"_Z4atanDv2_Dh",
+"_Z4atanDv2_f",
+"_Z4atanDv3_Dh",
+"_Z4atanDv3_f",
+"_Z4atanDv4_Dh",
+"_Z4atanDv4_f",
+"_Z4atanf",
+"_Z4cbrtDh",
+"_Z4cbrtDv2_Dh",
+"_Z4cbrtDv2_f",
+"_Z4cbrtDv3_Dh",
+"_Z4cbrtDv3_f",
+"_Z4cbrtDv4_Dh",
+"_Z4cbrtDv4_f",
+"_Z4cbrtf",
+"_Z4ceilDh",
+"_Z4ceilDv2_Dh",
+"_Z4ceilDv2_f",
+"_Z4ceilDv3_Dh",
+"_Z4ceilDv3_f",
+"_Z4ceilDv4_Dh",
+"_Z4ceilDv4_f",
+"_Z4ceilf",
+"_Z4coshDh",
+"_Z4coshDv2_Dh",
+"_Z4coshDv2_f",
+"_Z4coshDv3_Dh",
+"_Z4coshDv3_f",
+"_Z4coshDv4_Dh",
+"_Z4coshDv4_f",
+"_Z4coshf",
+"_Z4erfcDh",
+"_Z4erfcDv2_Dh",
+"_Z4erfcDv2_f",
+"_Z4erfcDv3_Dh",
+"_Z4erfcDv3_f",
+"_Z4erfcDv4_Dh",
+"_Z4erfcDv4_f",
+"_Z4erfcf",
+"_Z4exp2Dh",
+"_Z4exp2Dv2_Dh",
+"_Z4exp2Dv2_f",
+"_Z4exp2Dv3_Dh",
+"_Z4exp2Dv3_f",
+"_Z4exp2Dv4_Dh",
+"_Z4exp2Dv4_f",
+"_Z4exp2f",
+"_Z4fabsDh",
+"_Z4fabsDv2_Dh",
+"_Z4fabsDv2_f",
+"_Z4fabsDv3_Dh",
+"_Z4fabsDv3_f",
+"_Z4fabsDv4_Dh",
+"_Z4fabsDv4_f",
+"_Z4fabsf",
+"_Z4fdimDhDh",
+"_Z4fdimDv2_DhS_",
+"_Z4fdimDv2_fS_",
+"_Z4fdimDv3_DhS_",
+"_Z4fdimDv3_fS_",
+"_Z4fdimDv4_DhS_",
+"_Z4fdimDv4_fS_",
+"_Z4fdimff",
+"_Z4fmaxDhDh",
+"_Z4fmaxDv2_DhDh",
+"_Z4fmaxDv2_DhS_",
+"_Z4fmaxDv2_fS_",
+"_Z4fmaxDv2_ff",
+"_Z4fmaxDv3_DhDh",
+"_Z4fmaxDv3_DhS_",
+"_Z4fmaxDv3_fS_",
+"_Z4fmaxDv3_ff",
+"_Z4fmaxDv4_DhDh",
+"_Z4fmaxDv4_DhS_",
+"_Z4fmaxDv4_fS_",
+"_Z4fmaxDv4_ff",
+"_Z4fmaxff",
+"_Z4fminDhDh",
+"_Z4fminDv2_DhDh",
+"_Z4fminDv2_DhS_",
+"_Z4fminDv2_fS_",
+"_Z4fminDv2_ff",
+"_Z4fminDv3_DhDh",
+"_Z4fminDv3_DhS_",
+"_Z4fminDv3_fS_",
+"_Z4fminDv3_ff",
+"_Z4fminDv4_DhDh",
+"_Z4fminDv4_DhS_",
+"_Z4fminDv4_fS_",
+"_Z4fminDv4_ff",
+"_Z4fminff",
+"_Z4fmodDhDh",
+"_Z4fmodDv2_DhS_",
+"_Z4fmodDv2_fS_",
+"_Z4fmodDv3_DhS_",
+"_Z4fmodDv3_fS_",
+"_Z4fmodDv4_DhS_",
+"_Z4fmodDv4_fS_",
+"_Z4fmodff",
+"_Z4log2Dh",
+"_Z4log2Dv2_Dh",
+"_Z4log2Dv2_f",
+"_Z4log2Dv3_Dh",
+"_Z4log2Dv3_f",
+"_Z4log2Dv4_Dh",
+"_Z4log2Dv4_f",
+"_Z4log2f",
+"_Z4logbDh",
+"_Z4logbDv2_Dh",
+"_Z4logbDv2_f",
+"_Z4logbDv3_Dh",
+"_Z4logbDv3_f",
+"_Z4logbDv4_Dh",
+"_Z4logbDv4_f",
+"_Z4logbf",
+"_Z4modfDhPDh",
+"_Z4modfDv2_DhPS_",
+"_Z4modfDv2_fPS_",
+"_Z4modfDv3_DhPS_",
+"_Z4modfDv3_fPS_",
+"_Z4modfDv4_DhPS_",
+"_Z4modfDv4_fPS_",
+"_Z4modffPf",
+"_Z4pownDhi",
+"_Z4pownDv2_DhDv2_i",
+"_Z4pownDv2_fDv2_i",
+"_Z4pownDv3_DhDv3_i",
+"_Z4pownDv3_fDv3_i",
+"_Z4pownDv4_DhDv4_i",
+"_Z4pownDv4_fDv4_i",
+"_Z4pownfi",
+"_Z4powrDhDh",
+"_Z4powrDv2_DhS_",
+"_Z4powrDv2_fS_",
+"_Z4powrDv3_DhS_",
+"_Z4powrDv3_fS_",
+"_Z4powrDv4_DhS_",
+"_Z4powrDv4_fS_",
+"_Z4powrff",
+"_Z4rintDh",
+"_Z4rintDv2_Dh",
+"_Z4rintDv2_f",
+"_Z4rintDv3_Dh",
+"_Z4rintDv3_f",
+"_Z4rintDv4_Dh",
+"_Z4rintDv4_f",
+"_Z4rintf",
+"_Z4signDh",
+"_Z4signDv2_Dh",
+"_Z4signDv2_f",
+"_Z4signDv3_Dh",
+"_Z4signDv3_f",
+"_Z4signDv4_Dh",
+"_Z4signDv4_f",
+"_Z4signf",
+"_Z4sinhDh",
+"_Z4sinhDv2_Dh",
+"_Z4sinhDv2_f",
+"_Z4sinhDv3_Dh",
+"_Z4sinhDv3_f",
+"_Z4sinhDv4_Dh",
+"_Z4sinhDv4_f",
+"_Z4sinhf",
+"_Z4sqrtDh",
+"_Z4sqrtDv2_Dh",
+"_Z4sqrtDv2_f",
+"_Z4sqrtDv3_Dh",
+"_Z4sqrtDv3_f",
+"_Z4sqrtDv4_Dh",
+"_Z4sqrtDv4_f",
+"_Z4sqrtf",
+"_Z4stepDhDh",
+"_Z4stepDhDv2_Dh",
+"_Z4stepDhDv3_Dh",
+"_Z4stepDhDv4_Dh",
+"_Z4stepDv2_DhDh",
+"_Z4stepDv2_DhS_",
+"_Z4stepDv2_fS_",
+"_Z4stepDv2_ff",
+"_Z4stepDv3_DhDh",
+"_Z4stepDv3_DhS_",
+"_Z4stepDv3_fS_",
+"_Z4stepDv3_ff",
+"_Z4stepDv4_DhDh",
+"_Z4stepDv4_DhS_",
+"_Z4stepDv4_fS_",
+"_Z4stepDv4_ff",
+"_Z4stepfDv2_f",
+"_Z4stepfDv3_f",
+"_Z4stepfDv4_f",
+"_Z4stepff",
+"_Z4tanhDh",
+"_Z4tanhDv2_Dh",
+"_Z4tanhDv2_f",
+"_Z4tanhDv3_Dh",
+"_Z4tanhDv3_f",
+"_Z4tanhDv4_Dh",
+"_Z4tanhDv4_f",
+"_Z4tanhf",
+"_Z5acoshDh",
+"_Z5acoshDv2_Dh",
+"_Z5acoshDv2_f",
+"_Z5acoshDv3_Dh",
+"_Z5acoshDv3_f",
+"_Z5acoshDv4_Dh",
+"_Z5acoshDv4_f",
+"_Z5acoshf",
+"_Z5asinhDh",
+"_Z5asinhDv2_Dh",
+"_Z5asinhDv2_f",
+"_Z5asinhDv3_Dh",
+"_Z5asinhDv3_f",
+"_Z5asinhDv4_Dh",
+"_Z5asinhDv4_f",
+"_Z5asinhf",
+"_Z5atan2DhDh",
+"_Z5atan2Dv2_DhS_",
+"_Z5atan2Dv2_fS_",
+"_Z5atan2Dv3_DhS_",
+"_Z5atan2Dv3_fS_",
+"_Z5atan2Dv4_DhS_",
+"_Z5atan2Dv4_fS_",
+"_Z5atan2ff",
+"_Z5atanhDh",
+"_Z5atanhDv2_Dh",
+"_Z5atanhDv2_f",
+"_Z5atanhDv3_Dh",
+"_Z5atanhDv3_f",
+"_Z5atanhDv4_Dh",
+"_Z5atanhDv4_f",
+"_Z5atanhf",
+"_Z5clampDhDhDh",
+"_Z5clampDv2_DhDhDh",
+"_Z5clampDv2_DhS_S_",
+"_Z5clampDv2_cS_S_",
+"_Z5clampDv2_ccc",
+"_Z5clampDv2_fS_S_",
+"_Z5clampDv2_fff",
+"_Z5clampDv2_hS_S_",
+"_Z5clampDv2_hhh",
+"_Z5clampDv2_iS_S_",
+"_Z5clampDv2_iii",
+"_Z5clampDv2_jS_S_",
+"_Z5clampDv2_jjj",
+"_Z5clampDv2_lS_S_",
+"_Z5clampDv2_lll",
+"_Z5clampDv2_mS_S_",
+"_Z5clampDv2_mmm",
+"_Z5clampDv2_sS_S_",
+"_Z5clampDv2_sss",
+"_Z5clampDv2_tS_S_",
+"_Z5clampDv2_ttt",
+"_Z5clampDv2_yS_S_",
+"_Z5clampDv2_yyy",
+"_Z5clampDv3_DhDhDh",
+"_Z5clampDv3_DhS_S_",
+"_Z5clampDv3_cS_S_",
+"_Z5clampDv3_ccc",
+"_Z5clampDv3_fS_S_",
+"_Z5clampDv3_fff",
+"_Z5clampDv3_hS_S_",
+"_Z5clampDv3_hhh",
+"_Z5clampDv3_iS_S_",
+"_Z5clampDv3_iii",
+"_Z5clampDv3_jS_S_",
+"_Z5clampDv3_jjj",
+"_Z5clampDv3_lS_S_",
+"_Z5clampDv3_lll",
+"_Z5clampDv3_mS_S_",
+"_Z5clampDv3_mmm",
+"_Z5clampDv3_sS_S_",
+"_Z5clampDv3_sss",
+"_Z5clampDv3_tS_S_",
+"_Z5clampDv3_ttt",
+"_Z5clampDv3_yS_S_",
+"_Z5clampDv3_yyy",
+"_Z5clampDv4_DhDhDh",
+"_Z5clampDv4_DhS_S_",
+"_Z5clampDv4_cS_S_",
+"_Z5clampDv4_ccc",
+"_Z5clampDv4_fS_S_",
+"_Z5clampDv4_fff",
+"_Z5clampDv4_hS_S_",
+"_Z5clampDv4_hhh",
+"_Z5clampDv4_iS_S_",
+"_Z5clampDv4_iii",
+"_Z5clampDv4_jS_S_",
+"_Z5clampDv4_jjj",
+"_Z5clampDv4_lS_S_",
+"_Z5clampDv4_lll",
+"_Z5clampDv4_mS_S_",
+"_Z5clampDv4_mmm",
+"_Z5clampDv4_sS_S_",
+"_Z5clampDv4_sss",
+"_Z5clampDv4_tS_S_",
+"_Z5clampDv4_ttt",
+"_Z5clampDv4_yS_S_",
+"_Z5clampDv4_yyy",
+"_Z5clampccc",
+"_Z5clampfff",
+"_Z5clamphhh",
+"_Z5clampiii",
+"_Z5clampjjj",
+"_Z5clamplll",
+"_Z5clampmmm",
+"_Z5clampsss",
+"_Z5clampttt",
+"_Z5clampyyy",
+"_Z5cospiDh",
+"_Z5cospiDv2_Dh",
+"_Z5cospiDv2_f",
+"_Z5cospiDv3_Dh",
+"_Z5cospiDv3_f",
+"_Z5cospiDv4_Dh",
+"_Z5cospiDv4_f",
+"_Z5cospif",
+"_Z5crossDv3_DhS_",
+"_Z5crossDv3_fS_",
+"_Z5crossDv4_DhS_",
+"_Z5crossDv4_fS_",
+"_Z5exp10Dh",
+"_Z5exp10Dv2_Dh",
+"_Z5exp10Dv2_f",
+"_Z5exp10Dv3_Dh",
+"_Z5exp10Dv3_f",
+"_Z5exp10Dv4_Dh",
+"_Z5exp10Dv4_f",
+"_Z5exp10f",
+"_Z5expm1Dh",
+"_Z5expm1Dv2_Dh",
+"_Z5expm1Dv2_f",
+"_Z5expm1Dv3_Dh",
+"_Z5expm1Dv3_f",
+"_Z5expm1Dv4_Dh",
+"_Z5expm1Dv4_f",
+"_Z5expm1f",
+"_Z5floorDh",
+"_Z5floorDv2_Dh",
+"_Z5floorDv2_f",
+"_Z5floorDv3_Dh",
+"_Z5floorDv3_f",
+"_Z5floorDv4_Dh",
+"_Z5floorDv4_f",
+"_Z5floorf",
+"_Z5fractDh",
+"_Z5fractDhPDh",
+"_Z5fractDv2_Dh",
+"_Z5fractDv2_DhPS_",
+"_Z5fractDv2_f",
+"_Z5fractDv2_fPS_",
+"_Z5fractDv3_Dh",
+"_Z5fractDv3_DhPS_",
+"_Z5fractDv3_f",
+"_Z5fractDv3_fPS_",
+"_Z5fractDv4_Dh",
+"_Z5fractDv4_DhPS_",
+"_Z5fractDv4_f",
+"_Z5fractDv4_fPS_",
+"_Z5fractf",
+"_Z5fractfPf",
+"_Z5frexpDhPi",
+"_Z5frexpDv2_DhPDv2_i",
+"_Z5frexpDv2_fPDv2_i",
+"_Z5frexpDv3_DhPDv3_i",
+"_Z5frexpDv3_fPDv3_i",
+"_Z5frexpDv4_DhPDv4_i",
+"_Z5frexpDv4_fPDv4_i",
+"_Z5frexpfPi",
+"_Z5hypotDhDh",
+"_Z5hypotDv2_DhS_",
+"_Z5hypotDv2_fS_",
+"_Z5hypotDv3_DhS_",
+"_Z5hypotDv3_fS_",
+"_Z5hypotDv4_DhS_",
+"_Z5hypotDv4_fS_",
+"_Z5hypotff",
+"_Z5ilogbDh",
+"_Z5ilogbDv2_Dh",
+"_Z5ilogbDv2_f",
+"_Z5ilogbDv3_Dh",
+"_Z5ilogbDv3_f",
+"_Z5ilogbDv4_Dh",
+"_Z5ilogbDv4_f",
+"_Z5ilogbf",
+"_Z5ldexpDhi",
+"_Z5ldexpDv2_DhDv2_i",
+"_Z5ldexpDv2_Dhi",
+"_Z5ldexpDv2_fDv2_i",
+"_Z5ldexpDv2_fi",
+"_Z5ldexpDv3_DhDv3_i",
+"_Z5ldexpDv3_Dhi",
+"_Z5ldexpDv3_fDv3_i",
+"_Z5ldexpDv3_fi",
+"_Z5ldexpDv4_DhDv4_i",
+"_Z5ldexpDv4_Dhi",
+"_Z5ldexpDv4_fDv4_i",
+"_Z5ldexpDv4_fi",
+"_Z5ldexpfi",
+"_Z5log10Dh",
+"_Z5log10Dv2_Dh",
+"_Z5log10Dv2_f",
+"_Z5log10Dv3_Dh",
+"_Z5log10Dv3_f",
+"_Z5log10Dv4_Dh",
+"_Z5log10Dv4_f",
+"_Z5log10f",
+"_Z5log1pDh",
+"_Z5log1pDv2_Dh",
+"_Z5log1pDv2_f",
+"_Z5log1pDv3_Dh",
+"_Z5log1pDv3_f",
+"_Z5log1pDv4_Dh",
+"_Z5log1pDv4_f",
+"_Z5log1pf",
+"_Z5rootnDhi",
+"_Z5rootnDv2_DhDv2_i",
+"_Z5rootnDv2_fDv2_i",
+"_Z5rootnDv3_DhDv3_i",
+"_Z5rootnDv3_fDv3_i",
+"_Z5rootnDv4_DhDv4_i",
+"_Z5rootnDv4_fDv4_i",
+"_Z5rootnfi",
+"_Z5roundDh",
+"_Z5roundDv2_Dh",
+"_Z5roundDv2_f",
+"_Z5roundDv3_Dh",
+"_Z5roundDv3_f",
+"_Z5roundDv4_Dh",
+"_Z5roundDv4_f",
+"_Z5roundf",
+"_Z5rsqrtDh",
+"_Z5rsqrtDv2_Dh",
+"_Z5rsqrtDv2_f",
+"_Z5rsqrtDv3_Dh",
+"_Z5rsqrtDv3_f",
+"_Z5rsqrtDv4_Dh",
+"_Z5rsqrtDv4_f",
+"_Z5rsqrtf",
+"_Z5sinpiDh",
+"_Z5sinpiDv2_Dh",
+"_Z5sinpiDv2_f",
+"_Z5sinpiDv3_Dh",
+"_Z5sinpiDv3_f",
+"_Z5sinpiDv4_Dh",
+"_Z5sinpiDv4_f",
+"_Z5sinpif",
+"_Z5tanpiDh",
+"_Z5tanpiDv2_Dh",
+"_Z5tanpiDv2_f",
+"_Z5tanpiDv3_Dh",
+"_Z5tanpiDv3_f",
+"_Z5tanpiDv4_Dh",
+"_Z5tanpiDv4_f",
+"_Z5tanpif",
+"_Z5truncDh",
+"_Z5truncDv2_Dh",
+"_Z5truncDv2_f",
+"_Z5truncDv3_Dh",
+"_Z5truncDv3_f",
+"_Z5truncDv4_Dh",
+"_Z5truncDv4_f",
+"_Z5truncf",
+"_Z6acospiDh",
+"_Z6acospiDv2_Dh",
+"_Z6acospiDv2_f",
+"_Z6acospiDv3_Dh",
+"_Z6acospiDv3_f",
+"_Z6acospiDv4_Dh",
+"_Z6acospiDv4_f",
+"_Z6acospif",
+"_Z6asinpiDh",
+"_Z6asinpiDv2_Dh",
+"_Z6asinpiDv2_f",
+"_Z6asinpiDv3_Dh",
+"_Z6asinpiDv3_f",
+"_Z6asinpiDv4_Dh",
+"_Z6asinpiDv4_f",
+"_Z6asinpif",
+"_Z6atanpiDh",
+"_Z6atanpiDv2_Dh",
+"_Z6atanpiDv2_f",
+"_Z6atanpiDv3_Dh",
+"_Z6atanpiDv3_f",
+"_Z6atanpiDv4_Dh",
+"_Z6atanpiDv4_f",
+"_Z6atanpif",
+"_Z6lengthDh",
+"_Z6lengthDv2_Dh",
+"_Z6lengthDv2_f",
+"_Z6lengthDv3_Dh",
+"_Z6lengthDv3_f",
+"_Z6lengthDv4_Dh",
+"_Z6lengthDv4_f",
+"_Z6lengthf",
+"_Z6lgammaDh",
+"_Z6lgammaDhPi",
+"_Z6lgammaDv2_Dh",
+"_Z6lgammaDv2_DhPDv2_i",
+"_Z6lgammaDv2_f",
+"_Z6lgammaDv2_fPDv2_i",
+"_Z6lgammaDv3_Dh",
+"_Z6lgammaDv3_DhPDv3_i",
+"_Z6lgammaDv3_f",
+"_Z6lgammaDv3_fPDv3_i",
+"_Z6lgammaDv4_Dh",
+"_Z6lgammaDv4_DhPDv4_i",
+"_Z6lgammaDv4_f",
+"_Z6lgammaDv4_fPDv4_i",
+"_Z6lgammaf",
+"_Z6lgammafPi",
+"_Z6remquoDhDhPi",
+"_Z6remquoDv2_DhS_PDv2_i",
+"_Z6remquoDv2_fS_PDv2_i",
+"_Z6remquoDv3_DhS_PDv3_i",
+"_Z6remquoDv3_fS_PDv3_i",
+"_Z6remquoDv4_DhS_PDv4_i",
+"_Z6remquoDv4_fS_PDv4_i",
+"_Z6remquoffPi",
+"_Z6rsFracf",
+"_Z6rsRandf",
+"_Z6rsRandff",
+"_Z6rsRandi",
+"_Z6rsRandii",
+"_Z6rsTimePi",
+"_Z6rsTimePl",
+"_Z6sincosDhPDh",
+"_Z6sincosDv2_DhPS_",
+"_Z6sincosDv2_fPS_",
+"_Z6sincosDv3_DhPS_",
+"_Z6sincosDv3_fPS_",
+"_Z6sincosDv4_DhPS_",
+"_Z6sincosDv4_fPS_",
+"_Z6sincosfPf",
+"_Z6tgammaDh",
+"_Z6tgammaDv2_Dh",
+"_Z6tgammaDv2_f",
+"_Z6tgammaDv3_Dh",
+"_Z6tgammaDv3_f",
+"_Z6tgammaDv4_Dh",
+"_Z6tgammaDv4_f",
+"_Z6tgammaf",
+"_Z7atan2piDhDh",
+"_Z7atan2piDv2_DhS_",
+"_Z7atan2piDv2_fS_",
+"_Z7atan2piDv3_DhS_",
+"_Z7atan2piDv3_fS_",
+"_Z7atan2piDv4_DhS_",
+"_Z7atan2piDv4_fS_",
+"_Z7atan2piff",
+"_Z7degreesDh",
+"_Z7degreesDv2_Dh",
+"_Z7degreesDv2_f",
+"_Z7degreesDv3_Dh",
+"_Z7degreesDv3_f",
+"_Z7degreesDv4_Dh",
+"_Z7degreesDv4_f",
+"_Z7degreesf",
+"_Z7radiansDh",
+"_Z7radiansDv2_Dh",
+"_Z7radiansDv2_f",
+"_Z7radiansDv3_Dh",
+"_Z7radiansDv3_f",
+"_Z7radiansDv4_Dh",
+"_Z7radiansDv4_f",
+"_Z7radiansf",
+"_Z7rsClampccc",
+"_Z7rsClamphhh",
+"_Z7rsClampiii",
+"_Z7rsClampjjj",
+"_Z7rsClampsss",
+"_Z7rsClampttt",
+"_Z7rsDebugPKcDh",
+"_Z7rsDebugPKcDv2_Dh",
+"_Z7rsDebugPKcDv2_c",
+"_Z7rsDebugPKcDv2_d",
+"_Z7rsDebugPKcDv2_f",
+"_Z7rsDebugPKcDv2_h",
+"_Z7rsDebugPKcDv2_i",
+"_Z7rsDebugPKcDv2_j",
+"_Z7rsDebugPKcDv2_l",
+"_Z7rsDebugPKcDv2_m",
+"_Z7rsDebugPKcDv2_s",
+"_Z7rsDebugPKcDv2_t",
+"_Z7rsDebugPKcDv2_y",
+"_Z7rsDebugPKcDv3_Dh",
+"_Z7rsDebugPKcDv3_c",
+"_Z7rsDebugPKcDv3_d",
+"_Z7rsDebugPKcDv3_f",
+"_Z7rsDebugPKcDv3_h",
+"_Z7rsDebugPKcDv3_i",
+"_Z7rsDebugPKcDv3_j",
+"_Z7rsDebugPKcDv3_l",
+"_Z7rsDebugPKcDv3_m",
+"_Z7rsDebugPKcDv3_s",
+"_Z7rsDebugPKcDv3_t",
+"_Z7rsDebugPKcDv3_y",
+"_Z7rsDebugPKcDv4_Dh",
+"_Z7rsDebugPKcDv4_c",
+"_Z7rsDebugPKcDv4_d",
+"_Z7rsDebugPKcDv4_f",
+"_Z7rsDebugPKcDv4_h",
+"_Z7rsDebugPKcDv4_i",
+"_Z7rsDebugPKcDv4_j",
+"_Z7rsDebugPKcDv4_l",
+"_Z7rsDebugPKcDv4_m",
+"_Z7rsDebugPKcDv4_s",
+"_Z7rsDebugPKcDv4_t",
+"_Z7rsDebugPKcDv4_y",
+"_Z7rsDebugPKcPK12rs_matrix2x2",
+"_Z7rsDebugPKcPK12rs_matrix3x3",
+"_Z7rsDebugPKcPK12rs_matrix4x4",
+"_Z7rsDebugPKcPKv",
+"_Z7rsDebugPKcc",
+"_Z7rsDebugPKcd",
+"_Z7rsDebugPKcf",
+"_Z7rsDebugPKcff",
+"_Z7rsDebugPKcfff",
+"_Z7rsDebugPKcffff",
+"_Z7rsDebugPKch",
+"_Z7rsDebugPKci",
+"_Z7rsDebugPKcj",
+"_Z7rsDebugPKcl",
+"_Z7rsDebugPKcm",
+"_Z7rsDebugPKcs",
+"_Z7rsDebugPKct",
+"_Z7rsDebugPKcx",
+"_Z7rsDebugPKcy",
+"_Z7rsGetDtv",
+"_Z8copysignDhDh",
+"_Z8copysignDv2_DhS_",
+"_Z8copysignDv2_fS_",
+"_Z8copysignDv3_DhS_",
+"_Z8copysignDv3_fS_",
+"_Z8copysignDv4_DhS_",
+"_Z8copysignDv4_fS_",
+"_Z8copysignff",
+"_Z8distanceDhDh",
+"_Z8distanceDv2_DhS_",
+"_Z8distanceDv2_fS_",
+"_Z8distanceDv3_DhS_",
+"_Z8distanceDv3_fS_",
+"_Z8distanceDv4_DhS_",
+"_Z8distanceDv4_fS_",
+"_Z8distanceff",
+"_Z8nan_halfv",
+"_Z8rsGetLodPK19rs_kernel_context_t",
+"_Z8rsSample13rs_allocation10rs_samplerDv2_f",
+"_Z8rsSample13rs_allocation10rs_samplerDv2_ff",
+"_Z8rsSample13rs_allocation10rs_samplerf",
+"_Z8rsSample13rs_allocation10rs_samplerff",
+"_Z9half_sqrtDv2_f",
+"_Z9half_sqrtDv3_f",
+"_Z9half_sqrtDv4_f",
+"_Z9half_sqrtf",
+"_Z9nextafterDhDh",
+"_Z9nextafterDv2_DhS_",
+"_Z9nextafterDv2_fS_",
+"_Z9nextafterDv3_DhS_",
+"_Z9nextafterDv3_fS_",
+"_Z9nextafterDv4_DhS_",
+"_Z9nextafterDv4_fS_",
+"_Z9nextafterff",
+"_Z9normalizeDh",
+"_Z9normalizeDv2_Dh",
+"_Z9normalizeDv2_f",
+"_Z9normalizeDv3_Dh",
+"_Z9normalizeDv3_f",
+"_Z9normalizeDv4_Dh",
+"_Z9normalizeDv4_f",
+"_Z9normalizef",
+"_Z9remainderDhDh",
+"_Z9remainderDv2_DhS_",
+"_Z9remainderDv2_fS_",
+"_Z9remainderDv3_DhS_",
+"_Z9remainderDv3_fS_",
+"_Z9remainderDv4_DhS_",
+"_Z9remainderDv4_fS_",
+"_Z9remainderff",
+"_Z9rsForEach9rs_script13rs_allocationS0_",
+"_Z9rsForEach9rs_script13rs_allocationS0_PKv",
+"_Z9rsForEach9rs_script13rs_allocationS0_PKvPK14rs_script_call",
+"_Z9rsForEach9rs_script13rs_allocationS0_PKvj",
+"_Z9rsForEach9rs_script13rs_allocationS0_PKvjPK14rs_script_call",
+"_Z9rsGetDimXPK19rs_kernel_context_t",
+"_Z9rsGetDimYPK19rs_kernel_context_t",
+"_Z9rsGetDimZPK19rs_kernel_context_t",
+"_Z9rsGetFacePK19rs_kernel_context_t",
+"_Z9rsgFinishv",
+"rsUnpackColor8888",
+};
diff --git a/libbcc/lib/Renderscript/RSStubsWhiteList.h b/libbcc/lib/Renderscript/RSStubsWhiteList.h
new file mode 100644
index 0000000..d5a9986
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSStubsWhiteList.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014, 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 RSStubsWhiteList_H
+#define RSStubsWhiteList_H
+
+#include <cstdlib>
+#include <vector>
+#include <string>
+
+extern std::vector<std::string> stubList;
+
+#endif // RSStubsWhiteList_H
diff --git a/libbcc/lib/Renderscript/RSX86CallConvPass.cpp b/libbcc/lib/Renderscript/RSX86CallConvPass.cpp
new file mode 100644
index 0000000..5642d7b
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSX86CallConvPass.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSUtils.h"
+#include "bcc/Support/Log.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <llvm/IR/CallSite.h>
+#include <llvm/IR/Type.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Function.h>
+#include <llvm/Pass.h>
+
+namespace { // anonymous namespace
+
+static const bool kDebug = false;
+
+/* RSX86_64CallConvPass: This pass scans for calls to Renderscript functions in
+ * the CPU reference driver.  For such calls, it  identifies the
+ * pass-by-reference large-object pointer arguments introduced by the frontend
+ * to conform to the AArch64 calling convention (AAPCS).  These pointer
+ * arguments are converted to pass-by-value to match the calling convention of
+ * the CPU reference driver.
+ */
+class RSX86_64CallConvPass: public llvm::ModulePass {
+private:
+  bool IsRSFunctionOfInterest(llvm::Function &F) {
+  // Only Renderscript functions that are not defined locally be considered
+    if (!F.empty()) // defined locally
+      return false;
+
+    // llvm intrinsic or internal function
+    llvm::StringRef FName = F.getName();
+    if (FName.startswith("llvm."))
+      return false;
+
+    // All other functions need to be checked for large-object parameters.
+    // Disallowed (non-Renderscript) functions are detected by a different pass.
+    return true;
+  }
+
+  // Test if this argument needs to be converted to pass-by-value.
+  bool IsDerefNeeded(llvm::Function *F, llvm::Argument &Arg) {
+    unsigned ArgNo = Arg.getArgNo();
+    llvm::Type *ArgTy = Arg.getType();
+
+    // Do not consider arguments with 'sret' attribute.  Parameters with this
+    // attribute are actually pointers to structure return values.
+    if (Arg.hasStructRetAttr())
+      return false;
+
+    // Dereference needed only if type is a pointer to a struct
+    if (!ArgTy->isPointerTy() || !ArgTy->getPointerElementType()->isStructTy())
+      return false;
+
+    // Dereference needed only for certain RS struct objects.
+    llvm::Type *StructTy = ArgTy->getPointerElementType();
+    if (!isRsObjectType(StructTy))
+      return false;
+
+    // TODO Find a better way to encode exceptions
+    llvm::StringRef FName = F->getName();
+    // rsSetObject's first parameter is a pointer
+    if (FName.find("rsSetObject") != std::string::npos && ArgNo == 0)
+      return false;
+    // rsClearObject's first parameter is a pointer
+    if (FName.find("rsClearObject") != std::string::npos && ArgNo == 0)
+      return false;
+    // rsForEachInternal's fifth parameter is a pointer
+    if (FName.find("rsForEachInternal") != std::string::npos && ArgNo == 4)
+      return false;
+
+    return true;
+  }
+
+  // Compute which arguments to this function need be converted to pass-by-value
+  bool FillArgsToDeref(llvm::Function *F, std::vector<unsigned> &ArgNums) {
+    bccAssert(ArgNums.size() == 0);
+
+    for (auto &Arg: F->getArgumentList()) {
+      if (IsDerefNeeded(F, Arg)) {
+        ArgNums.push_back(Arg.getArgNo());
+
+        if (kDebug) {
+          ALOGV("Lowering argument %u for function %s\n", Arg.getArgNo(),
+                F->getName().str().c_str());
+        }
+      }
+    }
+    return ArgNums.size() > 0;
+  }
+
+  llvm::Function *RedefineFn(llvm::Function *OrigFn,
+                             std::vector<unsigned> &ArgsToDeref) {
+
+    llvm::FunctionType *FTy = OrigFn->getFunctionType();
+    std::vector<llvm::Type *> Params(FTy->param_begin(), FTy->param_end());
+
+    llvm::FunctionType *NewTy = llvm::FunctionType::get(FTy->getReturnType(),
+                                                        Params,
+                                                        FTy->isVarArg());
+    llvm::Function *NewFn = llvm::Function::Create(NewTy,
+                                                   OrigFn->getLinkage(),
+                                                   OrigFn->getName(),
+                                                   OrigFn->getParent());
+
+    // Add the ByVal attribute to the attribute list corresponding to this
+    // argument.  The list at index (i+1) corresponds to the i-th argument.  The
+    // list at index 0 corresponds to the return value's attribute.
+    for (auto i: ArgsToDeref) {
+      NewFn->addAttribute(i+1, llvm::Attribute::ByVal);
+    }
+
+    NewFn->copyAttributesFrom(OrigFn);
+    NewFn->takeName(OrigFn);
+
+    for (auto AI=OrigFn->arg_begin(), AE=OrigFn->arg_end(),
+              NAI=NewFn->arg_begin();
+         AI != AE; ++ AI, ++NAI) {
+      NAI->takeName(&*AI);
+    }
+
+    return NewFn;
+  }
+
+  void ReplaceCallInsn(llvm::CallSite &CS,
+                       llvm::Function *NewFn,
+                       std::vector<unsigned> &ArgsToDeref) {
+
+    llvm::CallInst *CI = llvm::cast<llvm::CallInst>(CS.getInstruction());
+    std::vector<llvm::Value *> Args(CS.arg_begin(), CS.arg_end());
+    auto NewCI = llvm::CallInst::Create(NewFn, Args, "", CI);
+
+    // Add the ByVal attribute to the attribute list corresponding to this
+    // argument.  The list at index (i+1) corresponds to the i-th argument.  The
+    // list at index 0 corresponds to the return value's attribute.
+    for (auto i: ArgsToDeref) {
+      NewCI->addAttribute(i+1, llvm::Attribute::ByVal);
+    }
+    if (CI->isTailCall())
+      NewCI->setTailCall();
+
+    if (!CI->getType()->isVoidTy())
+      CI->replaceAllUsesWith(NewCI);
+
+    CI->eraseFromParent();
+  }
+
+public:
+  static char ID;
+
+  RSX86_64CallConvPass()
+    : ModulePass (ID) {
+  }
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    // This pass does not use any other analysis passes, but it does
+    // modify the existing functions in the module (thus altering the CFG).
+  }
+
+  bool runOnModule(llvm::Module &M) override {
+    // Avoid adding Functions and altering FunctionList while iterating over it
+    // by collecting functions and processing them later.
+    std::vector<llvm::Function *> FunctionsToHandle;
+
+    auto &FunctionList = M.getFunctionList();
+    for (auto &OrigFn: FunctionList) {
+      if (!IsRSFunctionOfInterest(OrigFn))
+        continue;
+      FunctionsToHandle.push_back(&OrigFn);
+    }
+
+    for (auto OrigFn: FunctionsToHandle) {
+      std::vector<unsigned> ArgsToDeref;
+      if (!FillArgsToDeref(OrigFn, ArgsToDeref))
+        continue;
+
+      // Replace all calls to OrigFn and erase it from parent.
+      llvm::Function *NewFn = RedefineFn(OrigFn, ArgsToDeref);
+      while (!OrigFn->use_empty()) {
+        llvm::CallSite CS(OrigFn->user_back());
+        ReplaceCallInsn(CS, NewFn, ArgsToDeref);
+      }
+      OrigFn->eraseFromParent();
+    }
+
+    return FunctionsToHandle.size() > 0;
+  }
+
+};
+
+}
+
+char RSX86_64CallConvPass::ID = 0;
+
+static llvm::RegisterPass<RSX86_64CallConvPass> X("X86-64-calling-conv",
+  "remove AArch64 assumptions from calls in X86-64");
+
+namespace bcc {
+
+llvm::ModulePass *
+createRSX86_64CallConvPass() {
+  return new RSX86_64CallConvPass();
+}
+
+}
diff --git a/libbcc/lib/Renderscript/RSX86TranslateGEPPass.cpp b/libbcc/lib/Renderscript/RSX86TranslateGEPPass.cpp
new file mode 100644
index 0000000..75fc2ed
--- /dev/null
+++ b/libbcc/lib/Renderscript/RSX86TranslateGEPPass.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Assert.h"
+#include "bcc/Config/Config.h"
+#include "bcc/Support/Log.h"
+#include "bcc/Renderscript/RSTransforms.h"
+
+#include <cstdlib>
+
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Pass.h>
+#include <llvm/IR/GetElementPtrTypeIterator.h>
+
+namespace { // anonymous namespace
+
+/* This pass translates GEPs that index into structs or arrays of structs to
+ * GEPs with an int8* operand and a byte offset.  This translation is done to
+ * enforce on x86 the ARM alignment rule that 64-bit scalars be 8-byte aligned
+ * for structs with such scalars.
+ */
+class RSX86TranslateGEPPass : public llvm::FunctionPass {
+private:
+  static char ID;
+  llvm::LLVMContext *Context;
+  const llvm::DataLayout DL;
+
+  // Walk a GEP instruction and return true if any type indexed is a struct.
+  bool GEPIndexesStructType(const llvm::GetElementPtrInst *GEP) {
+    for (llvm::gep_type_iterator GTI = gep_type_begin(GEP),
+                                 GTE = gep_type_end(GEP);
+         GTI != GTE; ++GTI) {
+      if (llvm::dyn_cast<llvm::StructType>(*GTI)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Helper method to add two llvm::Value parameters
+  llvm::Value *incrementOffset(llvm::Value *accum, llvm::Value *incr,
+                               llvm::Instruction *InsertBefore) {
+    if (accum == nullptr)
+      return incr;
+    return llvm::BinaryOperator::CreateAdd(accum, incr, "", InsertBefore);
+  }
+
+  // Compute the byte offset for a GEP from the GEP's base pointer operand.
+  // Based on visitGetElementPtrInst in llvm/lib/Transforms/Scalar/SROA.cpp.
+  // The difference is that this function handles non-constant array indices and
+  // constructs a sequence of instructions to calculate the offset.  These
+  // instructions might not be the most efficient way to calculate this offset,
+  // but we rely on subsequent optimizations to do necessary fold/combine.
+  llvm::Value *computeGEPOffset(llvm::GetElementPtrInst *GEP) {
+    llvm::Value *Offset = nullptr;
+
+    for (llvm::gep_type_iterator GTI = gep_type_begin(GEP),
+                                 GTE = gep_type_end(GEP);
+         GTI != GTE; ++GTI) {
+      if (llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(*GTI)) {
+        llvm::ConstantInt *OpC = llvm::dyn_cast<llvm::ConstantInt>(GTI.getOperand());
+        if (!OpC) {
+          ALOGE("Operand for struct type is not constant!");
+          bccAssert(false);
+        }
+
+        // Offset = Offset + EltOffset for index into a struct
+        const llvm::StructLayout *SL = DL.getStructLayout(STy);
+        unsigned EltOffset = SL->getElementOffset(OpC->getZExtValue());
+        llvm::Value *Incr = llvm::ConstantInt::get(
+                                llvm::Type::getInt32Ty(*Context), EltOffset);
+        Offset = incrementOffset(Offset, Incr, GEP);
+      } else {
+        // Offset = Offset + Index * EltSize for index into an array or a vector
+        llvm::Value *EltSize = llvm::ConstantInt::get(
+                                 llvm::Type::getInt32Ty(*Context),
+                                 DL.getTypeAllocSize(GTI.getIndexedType()));
+        llvm::Value *Incr = llvm::BinaryOperator::CreateMul(
+                                GTI.getOperand() /* Index */,
+                                EltSize, "", GEP);
+        Offset = incrementOffset(Offset, Incr, GEP);
+      }
+    }
+
+    return Offset;
+  }
+
+  void translateGEP(llvm::GetElementPtrInst *GEP) {
+    // cast GEP pointer operand to int8*
+    llvm::CastInst *Int8Ptr = llvm::CastInst::CreatePointerCast(
+                                  GEP->getPointerOperand(),
+                                  llvm::Type::getInt8PtrTy(*Context),
+                                  "to.int8ptr",
+                                  GEP);
+    llvm::Value *Indices[1] = {computeGEPOffset(GEP)};
+
+    // index into the int8* based on the byte offset
+    llvm::GetElementPtrInst *Int8PtrGEP = llvm::GetElementPtrInst::Create(
+        llvm::Type::getInt8Ty(*Context), Int8Ptr, llvm::makeArrayRef(Indices),
+        "int8ptr.indexed", GEP);
+    Int8PtrGEP->setIsInBounds(GEP->isInBounds());
+
+    // cast the indexed int8* back to the type of the original GEP
+    llvm::CastInst *OutCast = llvm::CastInst::CreatePointerCast(
+        Int8PtrGEP, GEP->getType(), "to.orig.geptype", GEP);
+
+    GEP->replaceAllUsesWith(OutCast);
+  }
+
+public:
+  RSX86TranslateGEPPass()
+    : FunctionPass (ID), DL(X86_CUSTOM_DL_STRING) {
+  }
+
+  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+    // This pass is run in isolation in a separate pass manager.  So setting
+    // AnalysisUsage is unnecessary.  Set just for completeness.
+    AU.setPreservesCFG();
+  }
+
+  virtual bool runOnFunction(llvm::Function &F) override {
+    bool changed = false;
+    Context = &F.getParent()->getContext();
+
+    // To avoid updating/deleting instructions while walking a BasicBlock's instructions,
+    // collect the GEPs that need to be translated and process them
+    // subsequently.
+    std::vector<llvm::GetElementPtrInst *> GEPsToHandle;
+
+    for (auto &BB: F) {
+      for (auto &I: BB) {
+        if (auto *GEP = llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
+          if (GEPIndexesStructType(GEP)) {
+            GEPsToHandle.push_back(GEP);
+          }
+        }
+      }
+    }
+
+    for (auto *GEP: GEPsToHandle) {
+      // Translate GEPs and erase them
+      translateGEP(GEP);
+      changed = true;
+      GEP->eraseFromParent();
+    }
+
+    return changed;
+  }
+
+  virtual const char *getPassName() const override {
+    return "Translate GEPs on structs, intended for x86 target";
+  }
+};
+
+}
+
+char RSX86TranslateGEPPass::ID = 0;
+
+namespace bcc {
+
+llvm::FunctionPass *
+createRSX86TranslateGEPPass() {
+  return new RSX86TranslateGEPPass();
+}
+
+}
diff --git a/libbcc/lib/Support/Android.mk b/libbcc/lib/Support/Android.mk
new file mode 100644
index 0000000..5efbabd
--- /dev/null
+++ b/libbcc/lib/Support/Android.mk
@@ -0,0 +1,64 @@
+#
+# 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.
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+
+#=====================================================================
+# Common: libbccSupport
+#=====================================================================
+
+libbcc_support_SRC_FILES := \
+  CompilerConfig.cpp \
+  Disassembler.cpp \
+  FileBase.cpp \
+  Initialization.cpp \
+  InputFile.cpp \
+  OutputFile.cpp \
+
+#=====================================================================
+# Device Static Library: libbccSupport
+#=====================================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccSupport
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+LOCAL_SRC_FILES := \
+  $(libbcc_support_SRC_FILES)
+
+include $(LIBBCC_DEVICE_BUILD_MK)
+include $(LLVM_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
+endif
+
+#=====================================================================
+# Host Static Library: libbccSupport
+#=====================================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbccSupport
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+LOCAL_SRC_FILES := \
+  $(libbcc_support_SRC_FILES)
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libbcc/lib/Support/CompilerConfig.cpp b/libbcc/lib/Support/CompilerConfig.cpp
new file mode 100644
index 0000000..05d811f
--- /dev/null
+++ b/libbcc/lib/Support/CompilerConfig.cpp
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Support/CompilerConfig.h"
+#include "bcc/Config/Config.h"
+#include "bcc/Support/Properties.h"
+
+#include <llvm/CodeGen/SchedulerRegistry.h>
+#include <llvm/MC/SubtargetFeature.h>
+#include <llvm/Support/Host.h>
+#include <llvm/Support/TargetRegistry.h>
+
+#include "bcc/Support/Log.h"
+
+using namespace bcc;
+
+#if defined (PROVIDE_X86_CODEGEN) && !defined(__HOST__)
+
+namespace {
+
+// Utility function to test for f16c feature.  This function is only needed for
+// on-device bcc for x86
+bool HasF16C() {
+  llvm::StringMap<bool> features;
+  if (!llvm::sys::getHostCPUFeatures(features))
+    return false;
+
+  if (features.count("f16c") && features["f16c"])
+    return true;
+  else
+    return false;
+}
+
+}
+#endif // (PROVIDE_X86_CODEGEN) && !defined(__HOST__)
+
+CompilerConfig::CompilerConfig(const std::string &pTriple)
+  : mTriple(pTriple), mFullPrecision(true), mTarget(nullptr) {
+  //===--------------------------------------------------------------------===//
+  // Default setting of target options
+  //===--------------------------------------------------------------------===//
+
+  // Use soft-float ABI.  This only selects the ABI (and is applicable only to
+  // ARM targets).  Codegen still uses hardware FPU by default.  To use software
+  // floating point, add 'soft-float' feature to mFeatureString below.
+  mTargetOpts.FloatABIType = llvm::FloatABI::Soft;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for code model
+  //===--------------------------------------------------------------------===//
+  mCodeModel = llvm::CodeModel::Small;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for relocation model
+  //===--------------------------------------------------------------------===//
+  mRelocModel = llvm::Reloc::Default;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for optimization level (-O2)
+  //===--------------------------------------------------------------------===//
+  mOptLevel = llvm::CodeGenOpt::Default;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for architecture type
+  //===--------------------------------------------------------------------===//
+  mArchType = llvm::Triple::UnknownArch;
+
+  initializeTarget();
+  initializeArch();
+
+  return;
+}
+
+bool CompilerConfig::initializeTarget() {
+  std::string error;
+  mTarget = llvm::TargetRegistry::lookupTarget(mTriple, error);
+  if (mTarget != nullptr) {
+    return true;
+  } else {
+    ALOGE("Cannot initialize llvm::Target for given triple '%s'! (%s)",
+          mTriple.c_str(), error.c_str());
+    return false;
+  }
+}
+
+bool CompilerConfig::initializeArch() {
+  if (mTarget != nullptr) {
+    mArchType = llvm::Triple::getArchTypeForLLVMName(mTarget->getName());
+  } else {
+    mArchType = llvm::Triple::UnknownArch;
+    return false;
+  }
+
+  // Configure each architecture for any necessary additional flags.
+  std::vector<std::string> attributes;
+  switch (mArchType) {
+#if defined(PROVIDE_ARM_CODEGEN)
+  case llvm::Triple::arm: {
+    llvm::StringMap<bool> features;
+    llvm::sys::getHostCPUFeatures(features);
+
+#if defined(__HOST__) || defined(ARCH_ARM_HAVE_VFP)
+    attributes.push_back("+vfp3");
+#if !defined(__HOST__) && !defined(ARCH_ARM_HAVE_VFP_D32)
+    attributes.push_back("+d16");
+#endif  // !__HOST__ && !ARCH_ARM_HAVE_VFP_D32
+#endif  // __HOST__ || ARCH_ARM_HAVE_VFP
+
+#if defined(__HOST__) || defined(ARCH_ARM_HAVE_NEON)
+    // Only enable NEON on ARM if we have relaxed precision floats.
+    if (!mFullPrecision) {
+      attributes.push_back("+neon");
+    } else {
+#endif  // __HOST__ || ARCH_ARM_HAVE_NEON
+      attributes.push_back("-neon");
+      attributes.push_back("-neonfp");
+#if defined(__HOST__) || defined(ARCH_ARM_HAVE_NEON)
+    }
+#endif  // __HOST__ || ARCH_ARM_HAVE_NEON
+
+    if (!getProperty("debug.rs.arm-no-hwdiv")) {
+      if (features.count("hwdiv-arm") && features["hwdiv-arm"])
+        attributes.push_back("+hwdiv-arm");
+
+      if (features.count("hwdiv") && features["hwdiv"])
+        attributes.push_back("+hwdiv");
+    }
+
+    // Enable fp16 attribute if available in the feature list.  This feature
+    // will not be added in the host version of bcc or bcc_compat since
+    // 'features' would correspond to features in an x86 host.
+    if (features.count("fp16") && features["fp16"])
+      attributes.push_back("+fp16");
+
+
+#if defined(TARGET_BUILD)
+    if (!getProperty("debug.rs.arm-no-tune-for-cpu")) {
+#ifndef FORCE_CPU_VARIANT_32
+#ifdef DEFAULT_ARM_CODEGEN
+      setCPU(llvm::sys::getHostCPUName());
+#endif
+#else
+#define XSTR(S) #S
+#define STR(S) XSTR(S)
+      setCPU(STR(FORCE_CPU_VARIANT_32));
+#undef STR
+#undef XSTR
+#endif
+    }
+#endif  // TARGET_BUILD
+
+    break;
+  }
+#endif  // PROVIDE_ARM_CODEGEN
+
+#if defined(PROVIDE_ARM64_CODEGEN)
+  case llvm::Triple::aarch64:
+#if defined(TARGET_BUILD)
+    if (!getProperty("debug.rs.arm-no-tune-for-cpu")) {
+#ifndef FORCE_CPU_VARIANT_64
+#ifdef DEFAULT_ARM64_CODEGEN
+      setCPU(llvm::sys::getHostCPUName());
+#endif
+#else
+#define XSTR(S) #S
+#define STR(S) XSTR(S)
+      setCPU(STR(FORCE_CPU_VARIANT_64));
+#undef STR
+#undef XSTR
+#endif
+
+    }
+#endif  // TARGET_BUILD
+    break;
+#endif  // PROVIDE_ARM64_CODEGEN
+
+#if defined (PROVIDE_MIPS_CODEGEN)
+  case llvm::Triple::mips:
+  case llvm::Triple::mipsel:
+    if (getRelocationModel() == llvm::Reloc::Default) {
+      setRelocationModel(llvm::Reloc::Static);
+    }
+    break;
+#endif  // PROVIDE_MIPS_CODEGEN
+
+#if defined (PROVIDE_MIPS64_CODEGEN)
+  case llvm::Triple::mips64:
+  case llvm::Triple::mips64el:
+    // Default revision for MIPS64 Android is R6.
+    setCPU("mips64r6");
+    break;
+#endif // PROVIDE_MIPS64_CODEGEN
+
+#if defined (PROVIDE_X86_CODEGEN)
+  case llvm::Triple::x86:
+    getTargetOptions().UseInitArray = true;
+#if defined (DEFAULT_X86_CODEGEN) && !defined (DEFAULT_X86_64_CODEGEN)
+    setCPU(llvm::sys::getHostCPUName());
+#else
+    // generic fallback for 32bit x86 targets
+    setCPU("atom");
+#endif // DEFAULT_X86_CODEGEN && !DEFAULT_X86_64_CODEGEN
+
+#ifndef __HOST__
+    // If not running on the host, and f16c is available, set it in the feature
+    // string
+    if (HasF16C())
+      attributes.push_back("+f16c");
+#if defined(__SSE3__)
+    attributes.push_back("+sse3");
+    attributes.push_back("+ssse3");
+#endif
+#if defined(__SSE4_1__)
+    attributes.push_back("+sse4.1");
+#endif
+#if defined(__SSE4_2__)
+    attributes.push_back("+sse4.2");
+#endif
+#endif // __HOST__
+
+    // LLVM generates AVX code that treats a long3 as 256 bits, while
+    // RenderScript considers a long3 192 bits (http://b/28879581)
+    attributes.push_back("-avx");
+
+    break;
+#endif  // PROVIDE_X86_CODEGEN
+
+#if defined (PROVIDE_X86_CODEGEN)
+// PROVIDE_X86_CODEGEN is defined for both x86 and x86_64
+  case llvm::Triple::x86_64:
+#if defined(DEFAULT_X86_64_CODEGEN) && !defined(__HOST__)
+    setCPU(llvm::sys::getHostCPUName());
+#else
+    // generic fallback for 64bit x86 targets
+    setCPU("core2");
+#endif
+    // x86_64 needs small CodeModel if use PIC_ reloc, or else dlopen failed with TEXTREL.
+    if (getRelocationModel() == llvm::Reloc::PIC_) {
+      setCodeModel(llvm::CodeModel::Small);
+    } else {
+      setCodeModel(llvm::CodeModel::Medium);
+    }
+    getTargetOptions().UseInitArray = true;
+
+#ifndef __HOST__
+    // If not running on the host, and f16c is available, set it in the feature
+    // string
+    if (HasF16C())
+      attributes.push_back("+f16c");
+#endif // __HOST__
+
+    // LLVM generates AVX code that treats a long3 as 256 bits, while
+    // RenderScript considers a long3 192 bits (http://b/28879581)
+    attributes.push_back("-avx");
+
+    break;
+#endif  // PROVIDE_X86_CODEGEN
+
+  default:
+    ALOGE("Unsupported architecture type: %s", mTarget->getName());
+    return false;
+  }
+
+  setFeatureString(attributes);
+  return true;
+}
+
+void CompilerConfig::setFeatureString(const std::vector<std::string> &pAttrs) {
+  llvm::SubtargetFeatures f;
+
+  for (std::vector<std::string>::const_iterator attr_iter = pAttrs.begin(),
+           attr_end = pAttrs.end();
+       attr_iter != attr_end; attr_iter++) {
+    f.AddFeature(*attr_iter);
+  }
+
+  mFeatureString = f.getString();
+  return;
+}
diff --git a/libbcc/lib/Support/Disassembler.cpp b/libbcc/lib/Support/Disassembler.cpp
new file mode 100644
index 0000000..f1265aa
--- /dev/null
+++ b/libbcc/lib/Support/Disassembler.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright 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.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Support/Disassembler.h"
+
+#include "bcc/Config/Config.h"
+#if USE_DISASSEMBLER
+
+#include <string>
+
+#include <llvm/IR/LLVMContext.h>
+
+#include <llvm/MC/MCAsmInfo.h>
+#include <llvm/MC/MCDisassembler.h>
+#include <llvm/MC/MCInst.h>
+#include <llvm/MC/MCInstPrinter.h>
+#include <llvm/MC/MCInstrInfo.h>
+#include <llvm/MC/MCRegisterInfo.h>
+#include <llvm/MC/MCSubtargetInfo.h>
+
+#include <llvm/Support/MemoryObject.h>
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Support/raw_ostream.h>
+
+#include "bcc/Support/OutputFile.h"
+#include "bcc/Support/Log.h"
+
+namespace {
+
+class BufferMemoryObject : public llvm::MemoryObject {
+private:
+  const uint8_t *mBytes;
+  uint64_t mLength;
+
+public:
+  BufferMemoryObject(const uint8_t *pBytes, uint64_t pLength)
+    : mBytes(pBytes), mLength(pLength) {
+  }
+
+  virtual uint64_t getBase() const { return 0; }
+  virtual uint64_t getExtent() const { return mLength; }
+
+  virtual int readByte(uint64_t pAddr, uint8_t *pByte) const {
+    if (pAddr > getExtent())
+      return -1;
+    *pByte = mBytes[pAddr];
+    return 0;
+  }
+};
+
+} // namespace anonymous
+
+namespace bcc {
+
+DisassembleResult Disassemble(llvm::raw_ostream &pOutput, const char *pTriple,
+                              const char *pFuncName, const uint8_t *pFunc,
+                              size_t pFuncSize) {
+  DisassembleResult result = kDisassembleSuccess;
+  uint64_t i = 0;
+
+  const llvm::MCSubtargetInfo *subtarget_info = nullptr;
+  const llvm::MCDisassembler *disassembler = nullptr;
+  const llvm::MCInstrInfo *mc_inst_info = nullptr;
+  const llvm::MCRegisterInfo *mc_reg_info = nullptr;
+  const llvm::MCAsmInfo *asm_info = nullptr;
+  llvm::MCInstPrinter *inst_printer = nullptr;
+
+  BufferMemoryObject *input_function = nullptr;
+
+  std::string error;
+  const llvm::Target* target =
+      llvm::TargetRegistry::lookupTarget(pTriple, error);
+
+  if (target == nullptr) {
+    ALOGE("Invalid target triple for disassembler: %s (%s)!",
+          pTriple, error.c_str());
+    return kDisassembleUnknownTarget;
+  }
+
+  subtarget_info =
+      target->createMCSubtargetInfo(pTriple, /* CPU */"", /* Features */"");;
+
+  if (subtarget_info == nullptr) {
+    result = kDisassembleFailedSetup;
+    goto bail;
+  }
+
+  disassembler = target->createMCDisassembler(*subtarget_info);
+
+  mc_inst_info = target->createMCInstrInfo();
+
+  mc_reg_info = target->createMCRegInfo(pTriple);
+
+  asm_info = target->createMCAsmInfo(pTriple);
+
+  if ((disassembler == nullptr) || (mc_inst_info == nullptr) ||
+      (mc_reg_info == nullptr) || (asm_info == nullptr)) {
+    result = kDisassembleFailedSetup;
+    goto bail;
+  }
+
+  inst_printer = target->createMCInstPrinter(asm_info->getAssemblerDialect(),
+                                             *asm_info, *mc_inst_info,
+                                             *mc_reg_info, *subtarget_info);
+
+  if (inst_printer == nullptr) {
+    result = kDisassembleFailedSetup;
+    goto bail;
+  }
+
+  input_function = new (std::nothrow) BufferMemoryObject(pFunc, pFuncSize);
+
+  if (input_function == nullptr) {
+    result = kDisassembleOutOfMemory;
+    goto bail;
+  }
+
+  // Disassemble the given function
+  pOutput << "Disassembled code: " << pFuncName << "\n";
+
+  while (i < pFuncSize) {
+    llvm::MCInst inst;
+    uint64_t inst_size;
+
+    llvm::MCDisassembler::DecodeStatus decode_result =
+        disassembler->getInstruction(inst, inst_size, *input_function, i,
+                                     llvm::nulls(), llvm::nulls());
+
+    switch (decode_result) {
+      case llvm::MCDisassembler::Fail: {
+        ALOGW("Invalid instruction encoding encountered at %llu of function %s "
+              "under %s.", i, pFuncName, pTriple);
+        i++;
+        break;
+      }
+      case llvm::MCDisassembler::SoftFail: {
+        ALOGW("Potentially undefined instruction encoding encountered at %llu "
+              "of function %s under %s.", i, pFuncName, pTriple);
+        // fall-through
+      }
+      case llvm::MCDisassembler::Success : {
+        const uint8_t *inst_addr = pFunc + i;
+
+        pOutput.indent(4);
+        pOutput << "0x";
+        pOutput.write_hex(reinterpret_cast<uintptr_t>(inst_addr));
+        pOutput << ": 0x";
+        pOutput.write_hex(*reinterpret_cast<const uint32_t *>(inst_addr));
+        inst_printer->printInst(&inst, pOutput, /* Annot */"");
+        pOutput << "\n";
+
+        i += inst_size;
+        break;
+      }
+    }
+  }
+
+  pOutput << "\n";
+
+bail:
+  // Clean up
+  delete input_function;
+  delete inst_printer;
+  delete asm_info;
+  delete mc_reg_info;
+  delete mc_inst_info;
+  delete disassembler;
+  delete subtarget_info;
+
+  return result;
+}
+
+DisassembleResult Disassemble(OutputFile &pOutput, const char *pTriple,
+                              const char *pFuncName, const uint8_t *pFunc,
+                              size_t FuncSize) {
+  // Check the state of the specified output file.
+  if (pOutput.hasError()) {
+    return kDisassembleInvalidOutput;
+  }
+
+  // Open the output file decorated in llvm::raw_ostream.
+  llvm::raw_ostream *output = pOutput.dup();
+  if (output == nullptr) {
+    return kDisassembleFailedPrepareOutput;
+  }
+
+  // Delegate the request.
+  DisassembleResult result =
+      Disassemble(*output, pTriple, pFuncName, pFunc, FuncSize);
+
+  // Close the output before return.
+  delete output;
+
+  return result;
+}
+
+} // namespace bcc
+
+#else
+
+bcc::DisassembleResult Disassemble(llvm::raw_ostream &pOutput,
+                                   const char *pTriple, const char *pFuncName,
+                                   const uint8_t *pFunc, size_t pFuncSize) {
+  return bcc::kDisassemblerNotAvailable;
+}
+
+bcc::DisassembleResult bcc::Disassemble(OutputFile &pOutput,
+                                        const char *pTriple,
+                                        const char *pFuncName,
+                                        const uint8_t *pFunc,
+                                        size_t pFuncSize) {
+  return bcc::kDisassemblerNotAvailable;
+}
+
+#endif // USE_DISASSEMBLER
diff --git a/libbcc/lib/Support/FileBase.cpp b/libbcc/lib/Support/FileBase.cpp
new file mode 100644
index 0000000..90a5fc0
--- /dev/null
+++ b/libbcc/lib/Support/FileBase.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Support/FileBase.h"
+
+#include "bcc/Support/Log.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <cerrno>
+#include <cstring>
+#include <new>
+
+#include <utils/FileMap.h>
+
+using namespace bcc;
+
+#ifdef _WIN32
+// TODO: Fix flock usage under windows
+#define LOCK_SH 0
+#define LOCK_EX 0
+#define LOCK_NB 0
+#define LOCK_UN 0
+
+int flock(int fd, int operation) {
+  return 0;
+}
+#endif  // _WIN32
+
+FileBase::FileBase(const std::string &pFilename,
+                   unsigned pOpenFlags,
+                   unsigned pFlags)
+  : mFD(-1),
+    mError(),
+    mName(pFilename), mOpenFlags(pOpenFlags),
+    mShouldUnlock(false),
+    mShouldDelete(false) {
+  // Process pFlags
+#ifdef O_BINARY
+  if (pFlags & kBinary) {
+    mOpenFlags |= O_BINARY;
+  }
+#endif
+  if (pFlags & kTruncate) {
+    mOpenFlags |= O_TRUNC;
+  }
+
+  if (pFlags & kAppend) {
+    mOpenFlags |= O_APPEND;
+  }
+
+  if (pFlags & kDeleteOnClose) {
+    mShouldDelete = true;
+  }
+
+  // Open the file.
+  open();
+
+  return;
+}
+
+FileBase::~FileBase() {
+  close();
+}
+
+bool FileBase::open() {
+  do {
+    // FIXME: Hard-coded permissions (0644) for newly created file should be
+    //        removed and provide a way to let the user configure the value.
+    mFD = ::open(mName.c_str(), mOpenFlags, 0644);
+    if (mFD > 0) {
+      return true;
+    }
+
+    // Some errors occurred ...
+    if (errno != EINTR) {
+      detectError();
+      return false;
+    }
+  } while (true);
+  // unreachable
+}
+
+
+bool FileBase::checkFileIntegrity() {
+  // Check the file integrity by examining whether the inode referring to the mFD
+  // and to the file mName are the same.
+  struct stat fd_stat, file_stat;
+
+  // Get the file status of file descriptor mFD.
+  do {
+    if (::fstat(mFD, &fd_stat) == 0) {
+      break;
+    } else if (errno != EINTR) {
+      detectError();
+      return false;
+    }
+  } while (true);
+
+  // Get the file status of file mName.
+  do {
+    if (::stat(mName.c_str(), &file_stat) == 0) {
+      break;
+    } else if (errno != EINTR) {
+      detectError();
+      return false;
+    }
+  } while (true);
+
+  return ((fd_stat.st_dev == file_stat.st_dev) &&
+          (fd_stat.st_ino == file_stat.st_ino));
+}
+
+void FileBase::detectError() {
+  // Read error from errno.
+  mError.assign(errno, std::generic_category());
+}
+
+bool FileBase::lock(enum LockModeEnum pMode,
+                    bool pNonblocking,
+                    unsigned pMaxRetry,
+                    useconds_t pRetryInterval) {
+  int lock_operation;
+  unsigned retry = 0;
+
+  // Check the state.
+  if ((mFD < 0) || hasError()) {
+    return false;
+  }
+
+  // Return immediately if it's already locked.
+  if (mShouldUnlock) {
+    return true;
+  }
+
+  // Determine the lock operation (2nd argument) to the flock().
+  if (pMode == kReadLock) {
+    lock_operation = LOCK_SH;
+  } else if (pMode == kWriteLock) {
+    lock_operation = LOCK_EX;
+  } else {
+    mError = std::make_error_code(std::errc::invalid_argument);
+    return false;
+  }
+
+  if (pNonblocking) {
+    lock_operation |= LOCK_NB;
+  }
+
+  do {
+    if (::flock(mFD, lock_operation) == 0) {
+      mShouldUnlock = true;
+      // Here we got a lock but we need to check whether the mFD still
+      // "represents" the filename (mName) we opened in the contructor. This
+      // check may failed when another process deleted the original file mFD
+      // mapped when we were trying to obtain the lock on the file.
+      if (!checkFileIntegrity()) {
+        if (hasError() || !reopen()) {
+          // Error occurred when check the file integrity or re-open the file.
+          return false;
+        } else {
+          // Wait a while before the next try.
+          ::usleep(pRetryInterval);
+          retry++;
+          continue;
+        }
+      }
+
+      return true;
+    }
+
+    // flock() was not performed successfully. Check the errno to see whether
+    // it's retry-able.
+    if (errno == EINTR) {
+      // flock() was interrupted by delivery of a signal. Restart without
+      // decrement the retry counter.
+      continue;
+    } else if (errno == EWOULDBLOCK) {
+      // The file descriptor was locked by others, wait for a while before next
+      // retry.
+      retry++;
+      ::usleep(pRetryInterval);
+    } else {
+      // There's a fatal error occurs when perform flock(). Return immediately
+      // without further retry.
+      detectError();
+      return false;
+    }
+  } while (retry <= pMaxRetry);
+
+  return false;
+}
+
+void FileBase::unlock() {
+  if (mFD < 0) {
+    return;
+  }
+
+  do {
+    if (::flock(mFD, LOCK_UN) == 0) {
+      mShouldUnlock = false;
+      return;
+    }
+  } while (errno == EINTR);
+
+  detectError();
+  return;
+}
+
+android::FileMap *FileBase::createMap(off_t pOffset, size_t pLength,
+                                      bool pIsReadOnly) {
+  if (mFD < 0 || hasError()) {
+    return nullptr;
+  }
+
+  android::FileMap *map = new (std::nothrow) android::FileMap();
+  if (map == nullptr) {
+    mError = make_error_code(std::errc::not_enough_memory);
+    return nullptr;
+  }
+
+  if (!map->create(nullptr, mFD, pOffset, pLength, pIsReadOnly)) {
+    detectError();
+    delete map;
+    return nullptr;
+  }
+
+  return map;
+}
+
+size_t FileBase::getSize() {
+  if (mFD < 0 || hasError()) {
+    return static_cast<size_t>(-1);
+  }
+
+  struct stat file_stat;
+  do {
+    if (::fstat(mFD, &file_stat) == 0) {
+      break;
+    } else if (errno != EINTR) {
+      detectError();
+      return static_cast<size_t>(-1);
+    }
+  } while (true);
+
+  return file_stat.st_size;
+}
+
+off_t FileBase::seek(off_t pOffset) {
+  if ((mFD < 0) || hasError()) {
+    return static_cast<off_t>(-1);
+  }
+
+  do {
+    off_t result = ::lseek(mFD, pOffset, SEEK_SET);
+    if (result == pOffset) {
+      return result;
+    }
+  } while (errno == EINTR);
+
+  detectError();
+  return static_cast<off_t>(-1);
+}
+
+off_t FileBase::tell() {
+  if ((mFD < 0) || hasError()) {
+    return static_cast<off_t>(-1);
+  }
+
+  do {
+    off_t result = ::lseek(mFD, 0, SEEK_CUR);
+    if (result != static_cast<off_t>(-1)) {
+      return result;
+    }
+  } while (errno == EINTR);
+
+  detectError();
+  return static_cast<off_t>(-1);
+}
+
+void FileBase::close() {
+  if (mShouldUnlock) {
+    unlock();
+    mShouldUnlock = false;
+  }
+  if (mFD > 0) {
+    ::close(mFD);
+    mFD = -1;
+  }
+  if (mShouldDelete) {
+    int res = ::remove(mName.c_str());
+    if (res != 0) {
+      ALOGE("Failed to remove file: %s - %s", mName.c_str(), ::strerror(res));
+    }
+  }
+  return;
+}
diff --git a/libbcc/lib/Support/Initialization.cpp b/libbcc/lib/Support/Initialization.cpp
new file mode 100644
index 0000000..0149435
--- /dev/null
+++ b/libbcc/lib/Support/Initialization.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Support/Initialization.h"
+
+#include <cstdlib>
+
+#include <llvm/InitializePasses.h>
+#include <llvm/PassRegistry.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Support/TargetSelect.h>
+
+#include "bcc/Config/Config.h"
+#include "bcc/Support/Log.h"
+
+namespace {
+
+void llvm_error_handler(void *pUserData, const std::string &pMessage,
+                        bool pGenCrashDiag) {
+  ALOGE("bcc: Internal Error - %s", pMessage.c_str());
+  ::exit(1);
+}
+
+} // end anonymous namespace
+
+void bcc::init::Initialize() {
+  static bool is_initialized = false;
+
+  if (is_initialized) {
+    return;
+  }
+
+  // Setup error handler for LLVM.
+  llvm::remove_fatal_error_handler();
+  llvm::install_fatal_error_handler(llvm_error_handler, nullptr);
+
+
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllAsmPrinters();
+
+  llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
+  llvm::initializeCore(Registry);
+  llvm::initializeScalarOpts(Registry);
+  llvm::initializeVectorization(Registry);
+  llvm::initializeIPO(Registry);
+  llvm::initializeAnalysis(Registry);
+  llvm::initializeTransformUtils(Registry);
+  llvm::initializeInstCombine(Registry);
+  llvm::initializeInstrumentation(Registry);
+  llvm::initializeTarget(Registry);
+  llvm::initializeCodeGenPreparePass(Registry);
+  llvm::initializeAtomicExpandPass(Registry);
+  llvm::initializeRewriteSymbolsPass(Registry);
+
+  is_initialized = true;
+
+  return;
+}
diff --git a/libbcc/lib/Support/InputFile.cpp b/libbcc/lib/Support/InputFile.cpp
new file mode 100644
index 0000000..5701d20
--- /dev/null
+++ b/libbcc/lib/Support/InputFile.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Support/InputFile.h"
+
+#include "bcc/Support/Log.h"
+
+using namespace bcc;
+
+InputFile::InputFile(const std::string &pFilename, unsigned pFlags)
+  : super(pFilename, pFlags) { }
+
+ssize_t InputFile::read(void *pBuf, size_t count) {
+  if ((mFD < 0) || hasError()) {
+    return -1;
+  }
+
+  if ((count <= 0) || (pBuf == nullptr)) {
+    // Keep safe and issue a warning.
+    ALOGW("InputFile::read: count = %zu, buffer = %p", count, pBuf);
+    return 0;
+  }
+
+  while (count > 0) {
+    ssize_t read_size = ::read(mFD, pBuf, count);
+
+    if (read_size >= 0) {
+      return read_size;
+    } else if ((errno == EAGAIN) || (errno == EINTR)) {
+      // If the errno is EAGAIN or EINTR, then we try to read again.
+      //
+      // Fall-through
+    } else {
+      detectError();
+      return -1;
+    }
+  }
+  // unreachable
+  return 0;
+}
diff --git a/libbcc/lib/Support/OutputFile.cpp b/libbcc/lib/Support/OutputFile.cpp
new file mode 100644
index 0000000..dab02b9
--- /dev/null
+++ b/libbcc/lib/Support/OutputFile.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bcc/Support/OutputFile.h"
+
+#include <cstdlib>
+
+#include <llvm/Support/raw_ostream.h>
+
+#include "bcc/Support/Log.h"
+
+using namespace bcc;
+
+OutputFile::OutputFile(const std::string &pFilename, unsigned pFlags)
+  : super(pFilename, pFlags) { }
+
+ssize_t OutputFile::write(const void *pBuf, size_t count) {
+  if ((mFD < 0) || hasError()) {
+    return -1;
+  }
+
+  if ((count <= 0) || (pBuf == nullptr)) {
+    // Keep safe and issue a warning.
+    ALOGW("OutputFile::write: count = %zu, buffer = %p", count, pBuf);
+    return 0;
+  }
+
+  while (count > 0) {
+    ssize_t write_size = ::write(mFD, pBuf, count);
+
+    if (write_size > 0) {
+      return write_size;
+    } else if ((errno == EAGAIN) || (errno == EINTR)) {
+      // If the errno is EAGAIN or EINTR, then we try to write again.
+      //
+      // Fall-through
+    } else {
+      detectError();
+      return -1;
+    }
+  }
+  // unreachable
+  return 0;
+}
+
+void OutputFile::truncate() {
+  if (mFD < 0) {
+    return;
+  }
+
+  do {
+    if (::ftruncate(mFD, 0) == 0) {
+      return;
+    }
+  } while (errno == EINTR);
+  detectError();
+
+  return;
+}
+
+llvm::raw_fd_ostream *OutputFile::dup() {
+  int newfd;
+
+  do {
+    newfd = ::dup(mFD);
+    if (newfd < 0) {
+      if (errno != EINTR) {
+        detectError();
+        return nullptr;
+      }
+      // EINTR
+      continue;
+    }
+    // dup() returns ok.
+    break;
+  } while (true);
+
+  llvm::raw_fd_ostream *result =
+      new (std::nothrow) llvm::raw_fd_ostream(newfd, /* shouldClose */true);
+
+  if (result == nullptr) {
+    mError = std::make_error_code(std::errc::not_enough_memory);
+  }
+
+  return result;
+}
diff --git a/libbcc/libbcc-device-build.mk b/libbcc/libbcc-device-build.mk
new file mode 100644
index 0000000..b103da2
--- /dev/null
+++ b/libbcc/libbcc-device-build.mk
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+
+LOCAL_CLANG := true
+
+LOCAL_CFLAGS := \
+  -Wall \
+  -Wno-unused-parameter \
+  -Werror \
+  -DTARGET_BUILD \
+  $(RS_VERSION_DEFINE) \
+  $(LOCAL_CFLAGS)
+
+
+ifneq ($(BOARD_OVERRIDE_RS_CPU_VARIANT_32),)
+LOCAL_CFLAGS += -DFORCE_CPU_VARIANT_32=$(BOARD_OVERRIDE_RS_CPU_VARIANT_32)
+endif
+
+ifneq ($(BOARD_OVERRIDE_RS_CPU_VARIANT_64),)
+LOCAL_CFLAGS += -DFORCE_CPU_VARIANT_64=$(BOARD_OVERRIDE_RS_CPU_VARIANT_64)
+endif
+
+ifeq ($(TARGET_BUILD_VARIANT),eng)
+LOCAL_CFLAGS += -DANDROID_ENGINEERING_BUILD
+else
+LOCAL_CFLAGS += -D__DISABLE_ASSERTS
+endif
+
+ifeq ($(FORCE_BUILD_LLVM_DISABLE_NDEBUG),true)
+LOCAL_CFLAGS += -DFORCE_BUILD_LLVM_DISABLE_NDEBUG
+endif
+
+#=====================================================================
+# Architecture Selection
+#=====================================================================
+# Note: We should only use -DFORCE_ARCH_CODEGEN on target build.
+# For the host build, we will include as many architecture as possible,
+# so that we can test the execution engine easily.
+
+LOCAL_MODULE_TARGET_ARCH := $(LLVM_SUPPORTED_ARCH)
+
+include frameworks/compile/libbcc/libbcc-targets.mk
+
+LOCAL_C_INCLUDES := \
+  $(LIBBCC_ROOT_PATH)/include \
+  $(RS_ROOT_PATH) \
+  $(LLVM_ROOT_PATH)/include \
+  $(LLVM_ROOT_PATH)/device/include \
+  $(LOCAL_C_INCLUDES)
diff --git a/libbcc/libbcc-host-build.mk b/libbcc/libbcc-host-build.mk
new file mode 100644
index 0000000..9fe5278
--- /dev/null
+++ b/libbcc/libbcc-host-build.mk
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+LOCAL_CFLAGS := \
+  -Wall \
+  -Wno-unused-parameter \
+  -Werror \
+  -D__HOST__ \
+  $(RS_VERSION_DEFINE) \
+  $(LOCAL_CFLAGS)
+
+ifeq ($(TARGET_BUILD_VARIANT),eng)
+libbcc_CFLAGS += -DANDROID_ENGINEERING_BUILD
+else
+LOCAL_CFLAGS += -D__DISABLE_ASSERTS
+endif
+
+ifeq ($(FORCE_BUILD_LLVM_DISABLE_NDEBUG),true)
+LOCAL_CFLAGS += -DFORCE_BUILD_LLVM_DISABLE_NDEBUG
+endif
+
+LOCAL_C_INCLUDES := \
+  $(LIBBCC_ROOT_PATH)/include \
+  $(RS_ROOT_PATH) \
+  $(LLVM_ROOT_PATH)/include \
+  $(LLVM_ROOT_PATH)/host/include \
+  $(LOCAL_C_INCLUDES)
+
+LOCAL_IS_HOST_MODULE := true
diff --git a/libbcc/libbcc-targets.mk b/libbcc/libbcc-targets.mk
new file mode 100644
index 0000000..7bb2384
--- /dev/null
+++ b/libbcc/libbcc-targets.mk
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file contains target-specific defines for projects including LLVM
+# and/or libbcc directly.
+
+LOCAL_CFLAGS_arm += -DFORCE_ARM_CODEGEN
+ifeq ($(ARCH_ARM_HAVE_VFP),true)
+  LOCAL_CFLAGS_arm += -DARCH_ARM_HAVE_VFP
+  ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+    LOCAL_CFLAGS_arm += -DARCH_ARM_HAVE_VFP_D32
+  endif
+endif
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+  LOCAL_CFLAGS_arm += -DARCH_ARM_HAVE_NEON
+endif
+
+LOCAL_CFLAGS_arm64 += -DFORCE_ARM64_CODEGEN -DARCH_ARM_HAVE_NEON -DARCH_ARM_HAVE_VFP -DARCH_ARM_HAVE_VFP_D32 -DDISABLE_CLCORE_NEON
+LOCAL_CFLAGS_mips += -DFORCE_MIPS_CODEGEN
+LOCAL_CFLAGS_mips64 += -DFORCE_MIPS64_CODEGEN
+
+LOCAL_CFLAGS_x86 += -DFORCE_X86_CODEGEN
+LOCAL_CFLAGS_x86_64 += -DFORCE_X86_64_CODEGEN
+
+ifeq ($(BUILD_ARM_FOR_X86),true)
+LOCAL_CFLAGS_x86 += -DPROVIDE_ARM_CODEGEN -DFORCE_BUILD_ARM
+LOCAL_CFLAGS_x86_64 += -DPROVIDE_ARM_CODEGEN -DFORCE_BUILD_ARM -DPROVIDE_ARM64_CODEGEN
+endif
+
+
+ifeq (,$(filter $(TARGET_ARCH),arm64 arm mips mips64 x86 x86_64))
+  $(error Unsupported architecture $(TARGET_ARCH))
+endif
+
diff --git a/libbcc/libbcc.mk b/libbcc/libbcc.mk
new file mode 100644
index 0000000..c3775b2
--- /dev/null
+++ b/libbcc/libbcc.mk
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+ifeq ($(LIBBCC_ROOT_PATH),)
+$(error Must set variable LIBBCC_ROOT_PATH before including this! $(LOCAL_PATH))
+endif
+
+#=====================================================================
+# Root Path for Other Projects
+#=====================================================================
+
+LLVM_ROOT_PATH          := external/llvm
+RS_ROOT_PATH            := frameworks/rs
+
+#=====================================================================
+# Related Makefile Paths of libbcc
+#=====================================================================
+
+LIBBCC_HOST_BUILD_MK    := $(LIBBCC_ROOT_PATH)/libbcc-host-build.mk
+LIBBCC_DEVICE_BUILD_MK  := $(LIBBCC_ROOT_PATH)/libbcc-device-build.mk
+
+#=====================================================================
+# Related Makefile Paths of LLVM
+#=====================================================================
+include $(LLVM_ROOT_PATH)/llvm.mk
diff --git a/libbcc/libbcc.sha1.mk b/libbcc/libbcc.sha1.mk
new file mode 100644
index 0000000..60c05d7
--- /dev/null
+++ b/libbcc/libbcc.sha1.mk
@@ -0,0 +1,44 @@
+#=====================================================================
+# Calculate SHA1 checksum for libbcc.so, libRS.so and libclcore.bc
+#=====================================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libbcc.sha1
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+libbcc_SHA1_SRCS := \
+  $($(my_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libbcc.so \
+  $($(my_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libcompiler_rt.so \
+  $($(my_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libRS.so \
+  $(call intermediates-dir-for,SHARED_LIBRARIES,libclcore.bc,,,$(my_2nd_arch_prefix))/libclcore.bc \
+  $(call intermediates-dir-for,SHARED_LIBRARIES,libclcore_debug.bc,,,$(my_2nd_arch_prefix))/libclcore_debug.bc
+
+ifeq ($(TARGET_$(my_2nd_arch_prefix)ARCH),arm)
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+  libbcc_SHA1_SRCS += \
+    $(call intermediates-dir-for,SHARED_LIBRARIES,libclcore_neon.bc,,,$(my_2nd_arch_prefix))/libclcore_neon.bc
+endif
+endif
+
+libbcc_GEN_SHA1_STAMP := $(LOCAL_PATH)/tools/build/gen-sha1-stamp.py
+intermediates := $(call local-intermediates-dir,,$(my_2nd_arch_prefix))
+
+libbcc_SHA1_ASM := $(intermediates)/libbcc.sha1.S
+LOCAL_GENERATED_SOURCES += $(libbcc_SHA1_ASM)
+$(libbcc_SHA1_ASM): PRIVATE_SHA1_SRCS := $(libbcc_SHA1_SRCS)
+$(libbcc_SHA1_ASM): $(libbcc_SHA1_SRCS) $(libbcc_GEN_SHA1_STAMP)
+	@echo libbcc.sha1: $@
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(libbcc_GEN_SHA1_STAMP) $(PRIVATE_SHA1_SRCS) > $@
+
+LOCAL_CFLAGS += -D_REENTRANT -DPIC -fPIC
+LOCAL_CFLAGS += -O3 -nodefaultlibs -nostdlib
+
+LOCAL_MODULE_TARGET_ARCH := $(filter $(TARGET_$(my_2nd_arch_prefix)ARCH),$(LLVM_SUPPORTED_ARCH))
+
+ifdef LOCAL_MODULE_TARGET_ARCH
+include $(BUILD_SHARED_LIBRARY)
+endif
+endif
diff --git a/libbcc/llvm-loadable-libbcc.mk b/libbcc/llvm-loadable-libbcc.mk
new file mode 100644
index 0000000..5e47ced
--- /dev/null
+++ b/libbcc/llvm-loadable-libbcc.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Checks whether libbcc can be built as an LLVM loadable module on the
+# host.
+CAN_BUILD_HOST_LLVM_LOADABLE_MODULE := true
+
+ifneq ($(FORCE_BUILD_LLVM_COMPONENTS),true)
+CAN_BUILD_HOST_LLVM_LOADABLE_MODULE := false
+endif
diff --git a/libbcc/tests/README.lit b/libbcc/tests/README.lit
new file mode 100644
index 0000000..16fa305
--- /dev/null
+++ b/libbcc/tests/README.lit
@@ -0,0 +1,7 @@
+To run the libbcc lit tests:
+ * Ensure `llvm-rs-as` is built, either by doing a top-level `make
+   checkbuild` or by doing `mm` from frameworks/compile/slang.
+ * Ensure that LLVM and libbcc are built with
+   `FORCE_BUILD_LLVM_COMPONENTS=true`.
+ * Ensure `opt` is built from external/llvm, either by top-level `make
+   checkbuild` or by doing `mm` from external/llvm.
diff --git a/libbcc/tests/debuginfo/README b/libbcc/tests/debuginfo/README
new file mode 100644
index 0000000..80e2cc9
--- /dev/null
+++ b/libbcc/tests/debuginfo/README
@@ -0,0 +1,63 @@
+
+Summary
+=======
+This directory contains integration tests for debug information in libbcc.
+
+The tests come in two flavours: host and target. Host tests are run on the
+build machine (currently, only Linux has been tested extensively) and target
+tests run on a live Android system (emulator or device.)
+
+Host tests use clang to build bytecode (bc) files, which are then executed
+by the libbcc driver utility (bcc) on the host through GDB. The debugger
+output is verified against expected output by the llvm tool FileCheck.
+Both the debugger commands and the expected output are embedded in the
+original sources as comments of the form "DEBUGGER: " and "CHECK: ".
+
+Target tests are similar, but instead of using clang, they use ant and
+llvm-rs-cc from the Android SDK to build a test binary package (apk)
+that is uploaded to the device (or emulator) and run with GDB attached.
+The output is verified in the same way as host side tests, and the format
+of the tests is the same.
+
+*** If you are running target-side tests, you must disable parallel
+*** execution with the "-j1" flag to llvm-lit
+
+
+Prerequisites
+=============
+To run the tests, you must have built the android source tree and have
+the build environment variables set (i.e. ANDROID_BUILD_TOP)
+
+You need the following tools (not built by the android build system) on
+your PATH:
+- gdb     (Tested with gdb 7.3 from Ubuntu 11.10)
+
+In addition, you need a build of gdbserver available in the prebuilt directory.
+
+Customizing
+===========
+By default, llvm-lit will use the clang and bcc driver built in the android
+output directory. If you wish to use different versions of these tools,
+set the following environment variables:
+CLANG      - path to clang
+BCC_DRIVER - path to bcc
+FILECHECK  - path to FileCheck
+GDB        - path to GDB
+
+Further customization is possible by modifying the lit.cfg file.
+
+
+Running
+=======
+To execute all the tests from this directory, use the llvm-lit tool:
+$ ./llvm-lit host-tests
+$ ./llvm-lit target-tests -j 1
+
+The tool can be run from any directory.
+-j controls the number of tests to run in parallel
+-v enables additional verbosity (useful when examining unexpected failures)
+
+Adding new tests
+================
+To add new tests, just add a .c, .cpp, or .rs file to a test directory with
+similar RUN/DEBUGGER/CHECK directives in comments as the existing tests.
diff --git a/libbcc/tests/debuginfo/build_test_apk.sh b/libbcc/tests/debuginfo/build_test_apk.sh
new file mode 100755
index 0000000..0f0d541
--- /dev/null
+++ b/libbcc/tests/debuginfo/build_test_apk.sh
@@ -0,0 +1,245 @@
+#!/bin/bash -e
+
+# 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.
+
+# Creates and builds projects from a RenderScript testcase and a set of Java templates
+
+HELP=no
+VERBOSE=no
+MINSDK=1
+TARGET=1
+NAME=""
+OUT_DIR=
+ACTIVITY=""
+PACKAGE=""
+SDK=""
+TESTCASE_PATH=""
+DRIVER=""
+
+check_param ()
+{
+    if [ -z "$2" ]; then
+        echo "ERROR: Missing parameter after option '$1'"
+        exit 1
+    fi
+}
+
+check_required_param()
+{
+    if [ -z "$1" ]; then
+        echo "ERROR: Missing required parameter $2"
+        exit 1
+    fi
+}
+
+run ()
+{
+    if [ "$VERBOSE" = "yes" ] ; then
+        echo "## COMMAND: $@"
+    fi
+    $@ 2>&1
+}
+
+process_template()
+{
+  src=$1
+  dest=$2
+  sed -e "s/%ACTIVITY%/$3/g" -e "s/%PACKAGE%/$4/g" -e "s/%TESTCASE%/$5/g" -e "s/%MINSDK%/$6/g" < $src > $dest;
+  echo "processed $src ==> $dest"
+}
+
+while [ -n "$1" ]; do
+    opt="$1"
+    case "$opt" in
+        --help|-h|-\?)
+            HELP=yes
+            ;;
+        --verbose|-v)
+            VERBOSE=yes
+            ;;
+        --sdk)
+            check_param $1 $2
+            SDK="$2"
+            ;;
+        --name)
+            check_param $1 $2
+            NAME="$2"
+            ;;
+        --out)
+            check_param $1 $2
+            OUT_DIR="$2"
+            ;;
+        --activity)
+            check_param $1 $2
+            ACTIVITY="$2"
+            ;;
+        --package)
+            check_param $1 $2
+            PACKAGE="$2"
+            ;;
+        --minsdk)
+            check_param $1 $2
+            MINSDK="$2"
+            ;;
+        --target)
+            check_param $1 $2
+            TARGET="$2"
+            ;;
+        --testcase)
+            check_param $1 $2
+            TESTCASE_PATH="$2"
+            ;;
+        --driver)
+            check_param $1 $2
+            DRIVER="${2%/}"
+            ;;
+        -*) # unknown options
+            echo "ERROR: Unknown option '$opt', use --help for list of valid ones."
+            exit 1
+        ;;
+        *)  # Simply record parameter
+            if [ -z "$PARAMETERS" ] ; then
+                PARAMETERS="$opt"
+            else
+                PARAMETERS="$PARAMETERS $opt"
+            fi
+            ;;
+    esac
+    shift
+done
+
+if [ "$HELP" = "yes" ] ; then
+    echo "Usage: $PROGNAME [options]"
+    echo ""
+    echo "Build a test project from a RS testcase and a java driver template."
+    echo ""
+    echo "Required Parameters:"
+    echo "    --sdk                Location of Android SDK installation"
+    echo "    --out <path>         Location of your project directory"
+    echo "    --testcase <name>    The .rs testcase file with which to build the project"
+    echo "    --driver <name>      The java template directory with which to build the project"
+    echo ""
+    echo "Optional Parameters (reasonable defaults are used if not specified)"
+    echo "    --activity <name>    Name for your default Activity class"
+    echo "    --package <name>     Package namespace for your project"
+    echo "    --target <name>      Android build target. Execute 'android list targets' to list available targets and their ID's."
+    echo "    --minsdk <name>      minSdkVersion attribute to embed in AndroidManifest.xml of test project."
+    echo "    --help|-h|-?         Print this help"
+    echo "    --verbose|-v         Enable verbose mode"
+    echo ""
+    exit 0
+fi
+
+# Verify required parameters are non-empty
+check_required_param "$SDK" "--sdk"
+check_required_param "$OUT_DIR" "--out"
+check_required_param "$TESTCASE_PATH" "--testcase"
+check_required_param "$DRIVER" "--driver"
+
+# Compute name of testcase
+TESTCASE=`basename $TESTCASE_PATH .rs`
+
+# Compute activity, appname, and java package, if not specified via parameters
+if [ -z "$ACTIVITY" ]; then
+  ACTIVITY="$TESTCASE";
+fi
+
+if [ -z "$NAME" ]; then
+  NAME="$ACTIVITY"
+fi
+
+if [ -z "$PACKAGE" ]; then
+  PACKAGE=com.android.test.rsdebug.$TESTCASE
+fi
+
+# Create the project
+run $SDK/tools/android create project --target $TARGET --name $NAME --path $OUT_DIR --activity $ACTIVITY --package $PACKAGE
+
+if [ $? != 0 ] ; then
+    echo "ERROR: Could not create Android project."
+    echo "       Check parameters and try again."
+    exit 1
+fi
+
+# Compute name of destination source directory
+DEST_SRC_DIR=$OUT_DIR/src/`echo $PACKAGE | sed 's/\./\//g'`
+
+if [ ! -d "$DRIVER" ]; then
+  # If driver directory does not exist, try to fix it up by searching the
+  # testcase directory as well
+  DRIVER=`dirname $TESTCASE_PATH`/"$DRIVER"
+  if [ ! -d $DRIVER ]; then
+    echo "unable to find driver in $DRIVER, please check --driver"
+    exit 1;
+  fi
+fi
+
+echo "Copying driver template from $DRIVER -> $DEST_SRC_DIR"
+if [ ! -d "$DEST_SRC_DIR" ]; then
+  echo "Error, destination directory does not exist: $DEST_SRC_DIR";
+  exit 1;
+fi
+echo "Performing template substitutions:"
+echo "    %ACTIVITY% ==> $ACTIVITY"
+echo "    %PACKAGE% ==> $PACKAGE"
+echo "    %TESTCASE% ==> $TESTCASE"
+echo "    %MINSDK% ==> $MINSDK"
+SUBST_PARAMS="$ACTIVITY $PACKAGE $TESTCASE $MINSDK"
+
+# If it exists, use contents of driver-common directory to seed
+# the testcase project
+DRIVER_COMMON="`dirname $TESTCASE_PATH`/driver-common"
+if [ -d $DRIVER_COMMON ]; then
+  echo "Found common driver directory: $DRIVER_COMMON"
+  ls $DRIVER_COMMON/SRC/*.java.template | while read src; do
+    SRC_BASENAME=`basename $src .java.template`;
+    dest=$DEST_SRC_DIR/`echo $SRC_BASENAME | sed "s/ACTIVITY/$ACTIVITY/g"`.java
+    process_template $src $dest $SUBST_PARAMS
+  done;
+
+  # Copy AndroidManifest.xml
+  COMMON_MANIFEST="$DRIVER_COMMON/AndroidManifest.xml"
+  if [ -e $COMMON_MANIFEST ]; then
+    process_template $COMMON_MANIFEST $OUT_DIR/AndroidManifest.xml $SUBST_PARAMS
+  fi
+fi
+
+# Copy Java source to project directory.
+ls $DRIVER/*.java.template | while read src; do
+  SRC_BASENAME=`basename $src .java.template`
+  dest=$DEST_SRC_DIR/`echo $SRC_BASENAME | sed "s/ACTIVITY/$ACTIVITY/g"`.java
+  process_template $src $dest $SUBST_PARAMS
+done;
+
+# Copy AndroidManifest.xml override, if it exists
+OVERRIDE_MANIFEST="$DRIVER/AndroidManifest.xml"
+if [ -e $OVERRIDE_MANIFEST ]; then
+  process_template $OVERRIDE_MANIFEST $OUT_DIR/AndroidManifest.xml $SUBST_PARAMS
+fi
+
+# Copy RS testcase to project directory.
+TESTCASE_DEST=$DEST_SRC_DIR/`basename $TESTCASE_PATH`
+process_template $TESTCASE_PATH $TESTCASE_DEST $SUBST_PARAMS
+
+# Buid signed and aligned apk
+cd $OUT_DIR
+run ant clean debug install
+
+if [ $? != 0 ] ; then
+    echo "ERROR: Apk build and install failed"
+    exit 1
+fi
+
+exit 0
diff --git a/libbcc/tests/debuginfo/host-tests/aggregate-indirect-arg.cpp b/libbcc/tests/debuginfo/host-tests/aggregate-indirect-arg.cpp
new file mode 100644
index 0000000..bf38030
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/aggregate-indirect-arg.cpp
@@ -0,0 +1,32 @@
+// RUN: %clangxx %s -O0 -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// XFAIL: host-bcc
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break aggregate-indirect-arg.cpp:22
+// DEBUGGER: r
+// DEBUGGER: p v
+// CHECK: $1 = (SVal &)
+// CHECK:  Data = 0x0,
+// CHECK:  Kind = 2142
+
+class SVal {
+public:
+  ~SVal() {}
+  const void* Data;
+  unsigned Kind;
+};
+
+void bar(SVal &v) {}
+class A {
+public:
+  void foo(SVal v) { bar(v); }
+};
+
+int main() {
+  SVal v;
+  v.Data = 0;
+  v.Kind = 2142;
+  A a;
+  a.foo(v);
+  return 0;
+}
diff --git a/libbcc/tests/debuginfo/host-tests/forward-declare-class.cpp b/libbcc/tests/debuginfo/host-tests/forward-declare-class.cpp
new file mode 100644
index 0000000..2f06dbe
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/forward-declare-class.cpp
@@ -0,0 +1,30 @@
+// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// Radar 9168773
+
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: b forward-declare-class.cpp:28
+// DEBUGGER: r
+// DEBUGGER: ptype A
+// CHECK: type = class A {
+// CHECK-NEXT: public:
+// CHECK-NEXT: int MyData;
+// CHECK-NEXT: }
+class A;
+class B {
+public:
+  void foo(const A *p);
+};
+
+B iEntry;
+
+class A {
+public:
+  int MyData;
+};
+
+A irp;
+
+int main() {
+  return 0;
+}
diff --git a/libbcc/tests/debuginfo/host-tests/func_invoke_and_crash.cpp b/libbcc/tests/debuginfo/host-tests/func_invoke_and_crash.cpp
new file mode 100644
index 0000000..0f39f41
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/func_invoke_and_crash.cpp
@@ -0,0 +1,29 @@
+// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: set verbose on
+// DEBUGGER: run
+// DEBUGGER: bt 2
+// CHECK: function_with_a_segfault
+// CHECK: some_function
+
+static int function_with_a_segfault() {
+  int* bla = 0;
+  *bla = 5;
+  return 0;
+}
+
+static int some_function() {
+  return function_with_a_segfault();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int main() {
+  return bar();
+}
diff --git a/libbcc/tests/debuginfo/host-tests/global_struct.c b/libbcc/tests/debuginfo/host-tests/global_struct.c
new file mode 100644
index 0000000..344972e
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/global_struct.c
@@ -0,0 +1,36 @@
+// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// XFAIL: host-bcc
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break %s:34
+// DEBUGGER: run
+// DEBUGGER: print s
+// CHECK: $1 = {d = 0.001, d2 = {10000, 100.5}}
+// DEBUGGER: continue
+
+struct double_struct {
+  double d;
+  double d2[2];
+} compound_double;
+
+
+float f = 0.f;
+float *pf = &f;
+
+const double d[2][2] = {{0, 1}, {2, 3.0}};
+struct double_struct s;
+
+unsigned short us = -1;
+const unsigned long l = 1;
+
+int main(int argc, char* argv[])
+{
+  int f = 10; // shadow
+
+  s.d = 10e-4;
+  s.d2[0] = 1e4;
+  s.d2[1] = 100.5;
+
+  double result = pf[0] * d[1][1] * s.d * us * l;
+  return (result == 0 ? 0 : -1);
+}
diff --git a/libbcc/tests/debuginfo/host-tests/globals.c b/libbcc/tests/debuginfo/host-tests/globals.c
new file mode 100644
index 0000000..f6150ae
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/globals.c
@@ -0,0 +1,43 @@
+// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break %s:42
+// DEBUGGER: run
+// DEBUGGER: print pf[0]
+// CHECK: $1 = 0
+// DEBUGGER: print d[0][0]
+// CHECK: $2 = 0
+// DEBUGGER: print us
+// CHECK: $3 = 65535
+// DEBUGGER: print l
+// CHECK: $4 = 1
+// DEBUGGER: print f
+// CHECK: $5 = 10
+// DEBUGGER: continue
+
+struct double_struct {
+  double d;
+  double d2[2];
+} compound_double;
+
+
+float f = 0.f;
+float *pf = &f;
+
+const double d[2][2] = {{0, 1}, {2, 3.0}};
+struct double_struct s;
+
+unsigned short us = -1;
+const unsigned long l = 1;
+
+int main(int argc, char* argv[])
+{
+  int f = 10; // shadow
+
+  s.d = 10e-4;
+  s.d2[0] = 1e4;
+  s.d2[1] = 100.5;
+
+  double result = pf[0] * d[1][1] * s.d * us * l;
+  return (result == 0 ? 0 : -1);
+}
diff --git a/libbcc/tests/debuginfo/host-tests/jit.cpp b/libbcc/tests/debuginfo/host-tests/jit.cpp
new file mode 100644
index 0000000..2da7b23
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/jit.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break three
+// DEBUGGER: run
+// DEBUGGER: bt 4
+// CHECK: #0
+// CHECK:  three () at
+// CHECK: #1
+// CHECK:  in two
+// CHECK: #2
+// CHECK:  in one
+// CHECK: #3
+// CHECK:  in main
+
+int three()
+{
+  return 0;
+}
+
+int two()
+{
+  return three();
+}
+
+int one()
+{
+  return two();
+}
+
+int main(int argc, char** argv)
+{
+  return one();
+}
diff --git a/libbcc/tests/debuginfo/host-tests/lit.cfg b/libbcc/tests/debuginfo/host-tests/lit.cfg
new file mode 100644
index 0000000..b212daa
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/lit.cfg
@@ -0,0 +1,66 @@
+# -*- Python -*-
+#
+# 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.
+#
+
+#
+### Configuration file for target side debugger integration tests
+#
+
+# Set up the suite name, extensions that are recognized as testcases, and
+# the target triple string that must be used in cases marked expected failures
+config.name = 'host_bcc_debugger_integration'
+config.suffixes = ['.cpp', '.c']
+config.target_triple = 'host-bcc'
+
+# If the user is running an individual tests directory, we have to load
+# the libbcc site configuration first
+build_top = getattr(config, 'build_top', None)
+if build_top is None:
+  lit.load_config(config, os.path.join(os.getenv('ANDROID_BUILD_TOP',
+    '../../../../../'), 'frameworks', 'compile', 'libbcc', 'tests',
+    'debuginfo', 'lit.site.cfg'))
+  build_top = config.build_top
+
+# Output directory in the android source tree
+config.test_exec_root = os.path.join(config.build_top, 'out', 'host',
+  'tests', 'bcc-host')
+
+#
+## Set up environment variables
+#
+
+# - LD_LIBRARY_PATH for finding libbcc.so from the android build
+config.environment['LD_LIBRARY_PATH'] = \
+  os.path.join(config.base_build_path, 'lib') + ":" + \
+    config.environment['LD_LIBRARY_PATH']
+
+# - DEBUGGER and DEBUGGER_ARGS denote how to invoke the debugger
+config.environment['DEBUGGER'] = config.gdb
+config.environment['DEBUGGER_ARGS'] = '-q -batch -n --args ' \
+                                    + config.bcc_driver + ' -R '
+
+if not lit.quiet:
+    lit.note('using clang: %r' % config.clang)
+    lit.note('using bcc driver: %r' % config.bcc_driver)
+    lit.note('LD_LIBRARY_PATH is %r' % config.environment['LD_LIBRARY_PATH'])
+
+# Apply host-side test macro substitutions
+config.substitutions.append( ('%clangxx', ' ' + config.clang + \
+                                ' -ccc-clang-cxx -ccc-cxx ') )
+
+config.substitutions.append( ('%extra-clang-opts', ' -emit-llvm -c ') )
+
+config.substitutions.append( ('%clang', ' ' + config.clang + ' ') )
diff --git a/libbcc/tests/debuginfo/host-tests/locals.cpp b/libbcc/tests/debuginfo/host-tests/locals.cpp
new file mode 100644
index 0000000..0dcaec0
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/locals.cpp
@@ -0,0 +1,46 @@
+// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break %s:45
+// DEBUGGER: run
+// DEBUGGER: info locals
+// CHECK: pf = 0x
+// CHECK: s = {f = 0.00100000005, f2 = {10000, 100.5}}
+// CHECK: us = 65535
+// CHECK: f = 0
+// CHECK: d = {{[{][{]}}0, 1}, {2, 3{{[}][}]}}
+// CHECK: l = 0
+// CHECK: result = 0
+// DEBUGGER: continue
+
+struct float_struct {
+  float f;
+  float f2[2];
+} compound_float;
+
+
+int main(int argc, char* argv[])
+{
+  float f = 0.f;
+  float *pf = &f;
+
+  double d[2][2] = {{0, 1}, {2, 3.0}};
+  struct float_struct s;
+
+  unsigned short us = -1;
+  const unsigned long l = static_cast<unsigned long>(-1.0e8f);
+
+  {
+    int** ppn = 0;
+    if (ppn) {
+      return -1;
+    }
+  }
+
+  s.f = 10e-4f;
+  s.f2[0] = 1e4f;
+  s.f2[1] = 100.5f;
+
+  double result = pf[0] * d[1][1] * s.f * us * l;
+  return (result == 0 ? 0 : -1);
+}
diff --git a/libbcc/tests/debuginfo/host-tests/nested-struct.cpp b/libbcc/tests/debuginfo/host-tests/nested-struct.cpp
new file mode 100644
index 0000000..ccfa20b
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/nested-struct.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+
+// If debug info for my_number() is emitted outside function foo's scope
+// then a debugger may not be able to handle it. At least one version of
+// gdb crashes in such cases.
+
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: b nested-struct.cpp:28
+// DEBUGGER: run
+// DEBUGGER: ptype foo
+// CHECK: type = int (void)
+
+int foo() {
+  struct Local {
+    static int my_number() {
+      return 42;
+    }
+  };
+
+  int i = 0;
+  i = Local::my_number();
+  return i + 1;
+}
+
+int main() {
+  foo();
+  return 0;
+}
diff --git a/libbcc/tests/debuginfo/host-tests/parameters.cpp b/libbcc/tests/debuginfo/host-tests/parameters.cpp
new file mode 100644
index 0000000..bdc86f5
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/parameters.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break test_parameters
+// DEBUGGER: run
+// DEBUGGER: step
+// DEBUGGER: print pf[0]
+// CHECK: $1 = 0
+// DEBUGGER: print ppd[1][1]
+// CHECK: $2 = 3
+// DEBUGGER: print s
+// CHECK: $3 = (char_struct &)
+// CHECK: {c = 97 'a', c2 = "01"}
+// DEBUGGER: print ppn
+// CHECK: $4 = (int **) 0x0
+// DEBUGGER: print us
+// CHECK: $5 = 10
+// DEBUGGER: print l
+// CHECK: $6 = 42
+// DEBUGGER: continue
+
+struct char_struct {
+  char c;
+  char c2[2];
+} compound_char;
+
+
+double test_parameters(float* pf, double ppd[][2], struct char_struct& s, int** ppn = 0, unsigned short us = 10u, const unsigned long l = 42)
+{
+  double result = pf[0] * ppd[1][1] * s.c * us * l;
+  return result;
+}
+
+int main(int argc, char* argv[])
+{
+  struct char_struct s;
+  float f = 0.f;
+  double d[2][2] = {{0, 1}, {2, 3.0}};
+
+  s.c = 'a';
+  s.c2[0] = '0';
+  s.c2[1] = '1';
+
+  double result = test_parameters(&f, d, s);
+  return(result == 0 ? 0 : -1);
+}
diff --git a/libbcc/tests/debuginfo/host-tests/pass-function.c b/libbcc/tests/debuginfo/host-tests/pass-function.c
new file mode 100644
index 0000000..41b0082
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/pass-function.c
@@ -0,0 +1,75 @@
+// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break function_test
+// DEBUGGER: break %s:47
+// DEBUGGER: break %s:55
+// DEBUGGER: break %s:60
+// DEBUGGER: break %s:66
+// DEBUGGER: break %s:69
+// DEBUGGER: run
+// DEBUGGER: bt 2
+// CHECK: #0
+// CHECK:  function_test
+// CHECK: #1
+// CHECK:  main
+// DEBUGGER: continue
+// DEBUGGER: print j
+// CHECK: $1 = 0
+// DEBUGGER: step
+// DEBUGGER: print j
+// CHECK: $2 = 1
+// DEBUGGER: continue
+// DEBUGGER: print j
+// CHECK: $3 = -1
+// DEBUGGER: continue
+// DEBUGGER: bt 3
+// CHECK: #0
+// CHECK:  inline_test
+// CHECK: #1
+// CHECK:  function_test
+// CHECK: #2
+// CHECK:  main
+// DEBUGGER: continue
+// DEBUGGER: print j
+// CHECK: $4 = 2
+// DEBUGGER: continue
+// DEBUGGER: print j
+// CHECK: $5 = 0
+// DEBUGGER: continue
+
+__attribute__((noinline)) static int function_test();
+__attribute__((always_inline)) static int inline_test();
+
+int inline_test()
+{
+  int i = 0;
+  i++;
+  return i;
+}
+
+int function_test(int c)
+{
+  int i, j = 0;
+  for (i = 0; i < c; i++) {
+    j++;
+  }
+
+  {
+    int j = -1;
+    j++;
+  }
+
+  j += inline_test();
+
+  if (j > 0) {
+    j = 0;
+  }
+
+  return j;
+}
+
+int main(int argc, char** argv)
+{
+  return function_test(1);
+}
diff --git a/libbcc/tests/debuginfo/host-tests/pass-struct.c b/libbcc/tests/debuginfo/host-tests/pass-struct.c
new file mode 100644
index 0000000..4014cfc
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/pass-struct.c
@@ -0,0 +1,37 @@
+// RUN: %clangxx %s -O0 -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// XFAIL: host-bcc
+// (This testcase is expected to fail because of bcc optimizations that
+//  are enabled by default in the absence of metadata)
+
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break test_struct
+// DEBUGGER: run
+// DEBUGGER: step
+// DEBUGGER: print s
+// CHECK: $1 = {n = 10, n2 = {20, 21}}
+// DEBUGGER: continue
+
+struct int_struct {
+  int n;
+  int n2[2];
+} compound_int;
+
+
+int test_struct(struct int_struct s)
+{
+  s.n2[1]++;
+  return s.n > s.n2[0] ? s.n : s.n2[0];
+}
+
+int main(int argc, char* argv[])
+{
+  struct int_struct s;
+
+  s.n = 10;
+  s.n2[0] = 20;
+  s.n2[1] = 21;
+
+  int result = test_struct(s);
+  return(result == 20 ? 0 : -1);
+}
diff --git a/libbcc/tests/debuginfo/host-tests/simple_func_invoke_and_crash.cpp b/libbcc/tests/debuginfo/host-tests/simple_func_invoke_and_crash.cpp
new file mode 100644
index 0000000..590b958
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/simple_func_invoke_and_crash.cpp
@@ -0,0 +1,16 @@
+// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: run
+// DEBUGGER: bt 2
+// CHECK: function_with_a_segfault
+// CHECK: main
+
+static int function_with_a_segfault() {
+  int* bla = 0;
+  *bla = 5;
+  return 0;
+}
+
+int main() {
+  return function_with_a_segfault();
+}
diff --git a/libbcc/tests/debuginfo/host-tests/test_info_sources.cpp b/libbcc/tests/debuginfo/host-tests/test_info_sources.cpp
new file mode 100644
index 0000000..4937aa1
--- /dev/null
+++ b/libbcc/tests/debuginfo/host-tests/test_info_sources.cpp
@@ -0,0 +1,31 @@
+// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: set verbose on
+// DEBUGGER: b __jit_debug_register_code
+// DEBUGGER: run
+// DEBUGGER: info sources
+// CHECK: test_info_sources.cpp
+// DEBUGGER: c
+
+
+static int function_with_a_segfault() {
+  int* bla = 0;
+  *bla = 5;
+  return 0;
+}
+
+static int some_function() {
+  return function_with_a_segfault();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int main() {
+  return bar();
+}
diff --git a/libbcc/tests/debuginfo/lit.site.cfg b/libbcc/tests/debuginfo/lit.site.cfg
new file mode 100644
index 0000000..ad29ce0
--- /dev/null
+++ b/libbcc/tests/debuginfo/lit.site.cfg
@@ -0,0 +1,102 @@
+# -*- Python -*-
+#
+# 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.
+#
+
+# Configuration file for the 'lit' test runner in Android libbcc
+# This file is common to both host and target side tests 
+
+import os
+
+# Used to determine the absolute path of a tool. If env_var is set, it
+# overrides the default behaviour of searching PATH for binary_name
+def inferTool(lit, binary_name, env_var, PATH):
+    # Determine which tool to use.
+    tool = os.getenv(env_var)
+
+    # If the user set the overriding environment variable, use it
+    if tool and os.path.isfile(tool):
+        return tool
+
+    # Otherwise look in the path.
+    tool = lit.util.which(binary_name, PATH)
+
+    if not tool:
+        lit.fatal("couldn't find " + binary_name + " program in " + PATH + " \
+                  , try setting " + env_var + " in your environment")
+
+    return os.path.abspath(tool)
+
+# Get the base build directory for the android source tree from environment.
+config.build_top = os.getenv('ANDROID_BUILD_TOP')
+
+config.base_build_path = os.path.join(config.build_top, 'out', 'host',
+  'linux-x86')
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.ShTest()
+
+# Tool used to verify debugger output against expected output in source
+config.filecheck = inferTool(lit, 'FileCheck', 'FILECHECK', \
+  os.path.join(config.base_build_path, 'bin'))
+
+# Invokes GDB and captures output
+config.test_bcc_debuginfo = inferTool(lit, 'test_bcc_debuginfo.pl', \
+  'TEST_JIT_DEBUGINFO', os.path.join(config.build_top, 'frameworks', \
+  'compile', 'libbcc', 'tests', 'debuginfo'))
+
+# GDB
+config.gdb = inferTool(lit, 'arm-linux-androideabi-gdb', 'GDB',
+  config.environment['PATH'])
+
+# GDB python plugin
+config.gdb_plugin = inferTool(lit, 'android-commands.py',
+  'ANDROID_GDB_PLUGIN', os.path.join(config.build_top, 'frameworks',
+    'compile', 'libbcc', 'gdb_plugin'))
+config.gdb_plugin_directory = os.path.dirname(config.gdb_plugin)
+
+# Script interpreters that are not python
+config.perl = inferTool(lit, 'perl', 'PERL', config.environment['PATH'])
+config.sh = inferTool(lit, 'bash', 'BASH', config.environment['PATH'])
+
+# Tools that are specific to running host-side debugger integration tests:
+config.clang = inferTool(lit, 'clang', 'CLANG',
+  os.path.join(config.base_build_path, 'bin')).replace('\\', '/')
+config.bcc_driver = inferTool(lit, 'bcc', 'BCC_DRIVER',
+  os.path.join(config.base_build_path, 'obj', 'EXECUTABLES', \
+    'bcc_intermediates')).replace('\\', '/')
+
+# Tools that are specific to running target-side debugger integration tests:
+config.build_test_apk = inferTool(lit, 'build_test_apk.sh',
+  'BUILD_TEST_APK',
+  os.path.join(config.build_top, 'frameworks', 'compile', 'libbcc',
+    'tests', 'debuginfo'))
+
+#
+## Apply common substitutions
+#
+config.substitutions.append( ('%Test_jit_debuginfo', config.perl \
+                                + ' ' + config.test_bcc_debuginfo \
+                                + ' ' + config.filecheck + ' ' ) )
+
+#
+## Print common configuration
+#
+if not lit.quiet:
+    lit.note('using bash: %r' % config.sh)
+    lit.note('using perl: %r' % config.perl)
+    lit.note('using verification script: %r' % config.test_bcc_debuginfo)
+    lit.note('using FileCheck: %r' % config.filecheck)
+    lit.note('using GDB: %r' % config.gdb)
diff --git a/libbcc/tests/debuginfo/llvm-lit b/libbcc/tests/debuginfo/llvm-lit
new file mode 100755
index 0000000..117fe76
--- /dev/null
+++ b/libbcc/tests/debuginfo/llvm-lit
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+# In the Android tree, use the environment variables set by envsetup.sh
+# to determine correct path for the root of the source tree.
+# TODO: To run clang tests, @LLVM_BINARY_DIR@ must be substituted also.
+android_source_root = os.getenv('ANDROID_BUILD_TOP', ".")
+llvm_source_root = os.path.join(android_source_root, 'external', 'llvm')
+libbcc_source_root = os.path.join(android_source_root, 'frameworks', 'compile',
+  'libbcc')
+
+# Make sure we can find the lit package.
+sys.path.append(os.path.join(llvm_source_root, 'utils', 'lit'))
+
+# Set up some builtin parameters, so that by default the LLVM test suite
+# configuration file knows how to find the object tree.
+builtin_parameters = {
+    'llvm_site_config' : os.path.join(libbcc_source_root, 'test', 'debuginfo',
+                                      'lit.site.cfg')
+    }
+
+if __name__=='__main__':
+    import lit
+    lit.main(builtin_parameters)
diff --git a/libbcc/tests/debuginfo/target-tests/breakpoint_function.rs b/libbcc/tests/debuginfo/target-tests/breakpoint_function.rs
new file mode 100644
index 0000000..bb5f59e
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/breakpoint_function.rs
@@ -0,0 +1,37 @@
+// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: b entry
+// DEBUGGER: run-android-app
+// DEBUGGER: bt
+// CHECK: entry
+// CHECK: breakpoint_function.rs
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.test.rsdebug.breakpoint_function)
+
+static int twenty() {
+  return 20;
+}
+
+static int some_function() {
+  return twenty();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int root() {
+  return bar();
+}
+
+void entry() {
+  bar();
+}
diff --git a/libbcc/tests/debuginfo/target-tests/breakpoint_inlined_function.rs b/libbcc/tests/debuginfo/target-tests/breakpoint_inlined_function.rs
new file mode 100644
index 0000000..c769c89
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/breakpoint_inlined_function.rs
@@ -0,0 +1,41 @@
+// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: b twenty
+// DEBUGGER: run-android-app
+// DEBUGGER: bt
+// CHECK: twenty
+// CHECK: some_function
+// CHECK: foo
+// CHECK: bar
+// CHECK: entry
+// CHECK: breakpoint_inlined_function.rs:
+
+#pragma version(1)
+#pragma rs java_package_name(%PACKAGE%)
+
+static int twenty() {
+  return 20;
+}
+
+static int some_function() {
+  return twenty();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int root() {
+  return bar();
+}
+
+void entry() {
+  bar();
+}
diff --git a/libbcc/tests/debuginfo/target-tests/breakpoint_inlined_sourceline.rs b/libbcc/tests/debuginfo/target-tests/breakpoint_inlined_sourceline.rs
new file mode 100644
index 0000000..9022a87
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/breakpoint_inlined_sourceline.rs
@@ -0,0 +1,40 @@
+// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: b %s:18
+// DEBUGGER: run-android-app
+// DEBUGGER: bt
+// CHECK: some_function
+// CHECK: foo
+// CHECK: bar
+// CHECK: entry
+// CHECK: breakpoint_inlined_sourceline.rs:
+
+#pragma version(1)
+#pragma rs java_package_name(%PACKAGE%)
+
+static int twenty() {
+  return 20;
+}
+
+static int some_function() {
+  return twenty();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int root() {
+  return bar();
+}
+
+void entry() {
+  bar();
+}
diff --git a/libbcc/tests/debuginfo/target-tests/breakpoint_sourceline.rs b/libbcc/tests/debuginfo/target-tests/breakpoint_sourceline.rs
new file mode 100644
index 0000000..c0700a6
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/breakpoint_sourceline.rs
@@ -0,0 +1,36 @@
+// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: b %s:35
+// DEBUGGER: run-android-app
+// DEBUGGER: bt
+// CHECK: entry
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.test.rsdebug.breakpoint_sourceline)
+
+static int twenty() {
+  return 20;
+}
+
+static int some_function() {
+  return twenty();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int root() {
+  return bar();
+}
+
+void entry() {
+  bar();
+}
diff --git a/libbcc/tests/debuginfo/target-tests/crash.rs b/libbcc/tests/debuginfo/target-tests/crash.rs
new file mode 100644
index 0000000..c4980bc
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/crash.rs
@@ -0,0 +1,36 @@
+// RUN: %build_test_apk --driver driver-simple --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: run-android-app
+// DEBUGGER: bt
+// CHECK: entry
+
+#pragma version(1)
+#pragma rs java_package_name(%PACKAGE%)
+
+static int function_with_a_segfault() {
+  int* bla = 0;
+  *bla = 5;
+  return 0;
+}
+
+static int some_function() {
+  return function_with_a_segfault();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int root() {
+  return bar();
+}
+
+void entry() {
+  bar();
+}
diff --git a/libbcc/tests/debuginfo/target-tests/driver-common/AndroidManifest.xml b/libbcc/tests/debuginfo/target-tests/driver-common/AndroidManifest.xml
new file mode 100644
index 0000000..7e3e058
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/driver-common/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="%PACKAGE%"
+      android:versionCode="1"
+      android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="%MINSDK%" />
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name="%ACTIVITY%"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/libbcc/tests/debuginfo/target-tests/driver-common/SRC/DriverRS.java.template b/libbcc/tests/debuginfo/target-tests/driver-common/SRC/DriverRS.java.template
new file mode 100644
index 0000000..5706fa2
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/driver-common/SRC/DriverRS.java.template
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package %PACKAGE%;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+// This is the renderer for the driver
+public class DriverRS {
+    private Resources mRes;
+    private RenderScriptGL mRS;
+
+    private ScriptC_%TESTCASE% mScript;
+
+    public DriverRS() {
+    }
+
+    // This provides us with the renderscript context and resources that
+    // allow us to create the script that does rendering
+    public void init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        initRS();
+    }
+
+    private void initRS() {
+        mScript = new ScriptC_%TESTCASE% (mRS, mRes, R.raw.%TESTCASE%);
+        mScript.invoke_entry();
+    }
+}
+
diff --git a/libbcc/tests/debuginfo/target-tests/driver-common/SRC/DriverView.java.template b/libbcc/tests/debuginfo/target-tests/driver-common/SRC/DriverView.java.template
new file mode 100644
index 0000000..4c99c08
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/driver-common/SRC/DriverView.java.template
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+package %PACKAGE%;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.view.MotionEvent;
+
+public class DriverView extends RSSurfaceView {
+    // Renderscipt context
+    private RenderScriptGL mRS;
+    // Script that does the rendering
+    private DriverRS mRender;
+
+    public DriverView(Context context) {
+        super(context);
+        ensureRenderScript();
+    }
+
+    private void ensureRenderScript() {
+        if (mRS == null) {
+            // Initialize renderscript with desired surface characteristics.
+            // In this case, just use the defaults
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            mRS = createRenderScriptGL(sc);
+            // Create an instance of the script that does the rendering
+            mRender = new DriverRS();
+            mRender.init(mRS, getResources());
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        ensureRenderScript();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        // Handle the system event and clean up
+        mRender = null;
+        if (mRS != null) {
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+}
+
+
diff --git a/libbcc/tests/debuginfo/target-tests/driver-int-param/ACTIVITY.java.template b/libbcc/tests/debuginfo/target-tests/driver-int-param/ACTIVITY.java.template
new file mode 100644
index 0000000..e90da34
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/driver-int-param/ACTIVITY.java.template
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package %PACKAGE%;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+// Renderscript activity
+public class %ACTIVITY% extends Activity {
+
+    // Custom view to use with RenderScript
+    private DriverView mView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our view and set it as the content of our Activity
+        mView = new DriverView(this);
+        setContentView(mView);
+
+        // explicit kill
+        this.finish();
+        android.os.Process.killProcess(android.os.Process.myPid());
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally an app should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally an app should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onPause();
+        mView.pause();
+    }
+
+}
+
diff --git a/libbcc/tests/debuginfo/target-tests/driver-int-param/DriverRS.java.template b/libbcc/tests/debuginfo/target-tests/driver-int-param/DriverRS.java.template
new file mode 100644
index 0000000..9a8bb17
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/driver-int-param/DriverRS.java.template
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package %PACKAGE%;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+// This is the renderer for the driver
+public class DriverRS {
+    private Resources mRes;
+    private RenderScriptGL mRS;
+
+    private ScriptC_%TESTCASE% mScript;
+
+    public DriverRS() {
+    }
+
+    // This provides us with the renderscript context and resources that
+    // allow us to create the script that does rendering
+    public void init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        initRS();
+    }
+
+    private void initRS() {
+        mScript = new ScriptC_%TESTCASE% (mRS, mRes, R.raw.%TESTCASE%);
+        mScript.invoke_entry(40);
+    }
+}
+
diff --git a/libbcc/tests/debuginfo/target-tests/driver-simple-exit/ACTIVITY.java.template b/libbcc/tests/debuginfo/target-tests/driver-simple-exit/ACTIVITY.java.template
new file mode 100644
index 0000000..e90da34
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/driver-simple-exit/ACTIVITY.java.template
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package %PACKAGE%;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+// Renderscript activity
+public class %ACTIVITY% extends Activity {
+
+    // Custom view to use with RenderScript
+    private DriverView mView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our view and set it as the content of our Activity
+        mView = new DriverView(this);
+        setContentView(mView);
+
+        // explicit kill
+        this.finish();
+        android.os.Process.killProcess(android.os.Process.myPid());
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally an app should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally an app should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onPause();
+        mView.pause();
+    }
+
+}
+
diff --git a/libbcc/tests/debuginfo/target-tests/driver-simple/ACTIVITY.java.template b/libbcc/tests/debuginfo/target-tests/driver-simple/ACTIVITY.java.template
new file mode 100644
index 0000000..71e4539
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/driver-simple/ACTIVITY.java.template
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package %PACKAGE%;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+// Renderscript activity
+public class %ACTIVITY% extends Activity {
+
+    // Custom view to use with RenderScript
+    private DriverView mView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our view and set it as the content of our Activity
+        mView = new DriverView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally an app should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally an app should implement onResume() and onPause()
+        // to take appropriate action when the activity loses focus
+        super.onPause();
+        mView.pause();
+    }
+
+}
+
diff --git a/libbcc/tests/debuginfo/target-tests/global_int.rs b/libbcc/tests/debuginfo/target-tests/global_int.rs
new file mode 100644
index 0000000..6560e3c
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/global_int.rs
@@ -0,0 +1,48 @@
+// RUN: %build_test_apk --driver driver-int-param --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: set breakpoint pending on 
+// DEBUGGER: b %s:46
+// DEBUGGER: run-android-app
+// DEBUGGER: p global_zero
+// DEBUGGER: p global_value
+// CHECK: $1 = 0
+// CHECK: $2 = 11
+
+#pragma version(1)
+#pragma rs java_package_name(%PACKAGE%)
+
+// a global value
+int global_zero = 0;
+int global_value = 1;
+
+static int twenty() {
+  return 20;
+}
+
+static int some_function() {
+  return twenty();
+}
+
+static int foo() {
+  return some_function();
+}
+
+static int bar() {
+  return foo();
+}
+
+int root() {
+  return bar();
+}
+
+void entry(int parameter) {
+  bar();
+  if (parameter != 0) {
+    global_value += 10;
+  } else {
+    global_zero += 1;
+  }
+  global_zero += global_value;
+}
diff --git a/libbcc/tests/debuginfo/target-tests/info_sources.rs b/libbcc/tests/debuginfo/target-tests/info_sources.rs
new file mode 100644
index 0000000..546333d
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/info_sources.rs
@@ -0,0 +1,20 @@
+// RUN: %build_test_apk --driver driver-simple --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: run-android-app
+// DEBUGGER: info sources
+// CHECK: info_sources/info_sources.rs
+
+#pragma version(1)
+#pragma rs java_package_name(%PACKAGE%)
+
+static int function_with_a_segfault() {
+  int* bla = 0;
+  *bla = 5;
+  return 0;
+}
+
+void entry() {
+  function_with_a_segfault();
+}
diff --git a/libbcc/tests/debuginfo/target-tests/lit.cfg b/libbcc/tests/debuginfo/target-tests/lit.cfg
new file mode 100644
index 0000000..c81c5ed
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/lit.cfg
@@ -0,0 +1,90 @@
+# -*- Python -*-
+#
+# 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.
+#
+
+#
+### Configuration file for target side debugger integration tests
+#
+# Parameters available through lit --param options:
+#   android_sdk - Path to the android SDK directory 
+#   sdk_version - SDK target to pass to 'android' for creating test projects
+#   minimum_sdk - SDK minimum version to embed in AndroidManifest.xml
+
+# If the user is running an individual tests directory, we have to load
+# the libbcc site configuration first
+build_top = getattr(config, 'build_top', None)
+if build_top is None:
+  lit.load_config(config, os.path.join(os.getenv('ANDROID_BUILD_TOP',
+    '../../../../../'), 'frameworks', 'compile', 'libbcc', 'tests',
+    'debuginfo', 'lit.site.cfg'))
+  build_top = config.build_top
+
+# Default SDK path and version
+default_sdk_dir = os.path.join(config.base_build_path, 'sdk', 'android-sdk_' \
+                    + os.getenv('TARGET_BUILD_VARIANT') + '.' \
+                    + os.getenv('USER') + '_linux-x86')
+default_sdk_version = "android-JellyBean"
+default_minimum_sdk = "JellyBean"
+
+# Set up the suite name, extensions that are recognized as testcases, and
+# the target triple string that must be used in cases marked expected failures
+config.name = 'target_renderscript_debug'
+config.suffixes = ['.rs']
+config.target_triple = 'target-bcc'
+
+# Output directory in the android source tree
+if os.getenv('TARGET_BUILD_TYPE', None) == 'debug':
+  config.test_exec_root = os.path.join(config.build_top, 'out', 'debug',
+    'target', 'tests', 'rsdebug')
+else:
+  config.test_exec_root = os.path.join(config.build_top, 'out', 'target',
+    'tests', 'rsdebug')
+
+#
+## Set up SDK path and version
+#
+config.sdk_dir = lit.params.get('android_sdk', default_sdk_dir)
+if not os.path.isdir(config.sdk_dir):
+  lit.fatal("Android SDK directory " + config.sdk_dir + " does " \
+    + "not exist. Check --param android_sdk=<path> lit parameter in test " \
+    + "suite invocation.")
+
+config.sdk_version = lit.params.get('sdk_version', default_sdk_version)
+config.minimum_sdk = lit.params.get('minimum_sdk', default_minimum_sdk)
+
+#
+## Set up environment variables
+#
+
+# Propagate ANDROID_PRODUCT_OUT to child environment
+config.environment['ANDROID_PRODUCT_OUT'] = os.getenv('ANDROID_PRODUCT_OUT')
+config.environment['ANDROID_BUILD_TOP'] = os.getenv('ANDROID_BUILD_TOP')
+
+config.environment['DEBUGGER'] = config.gdb
+config.environment['DEBUGGER_ARGS'] = "-d " + config.gdb_plugin_directory + ' '
+
+if not lit.quiet:
+    lit.note('using Android SDK: %r' % config.sdk_dir)
+    lit.note('using Android SDK Version: %r' % config.sdk_version)
+    lit.note('using test apk builder: %r' % config.build_test_apk)
+    lit.note('using GDB plugin directory: %r' % config.gdb_plugin_directory)
+
+# Apply target-side test macro substitutions
+config.substitutions.append( ('%build_test_apk_opts', ' --sdk ' + config.sdk_dir \
+                                                    + ' --target ' + config.sdk_version \
+                                                    + ' --minsdk ' + config.minimum_sdk))
+config.substitutions.append( ('%build_test_apk', ' ' + config.sh \
+                                               + ' ' + config.build_test_apk + ' '))
diff --git a/libbcc/tests/debuginfo/target-tests/locals.rs b/libbcc/tests/debuginfo/target-tests/locals.rs
new file mode 100644
index 0000000..b1e4682
--- /dev/null
+++ b/libbcc/tests/debuginfo/target-tests/locals.rs
@@ -0,0 +1,57 @@
+// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
+// RUN: %Test_jit_debuginfo %s %t
+// DEBUGGER: source android-commands.py
+// DEBUGGER: load-android-app %t
+// DEBUGGER: set breakpoint pending on
+// DEBUGGER: break locals.rs:48
+// DEBUGGER: run-android-app
+// DEBUGGER: info locals
+// CHECK: pf = 0x
+// CHECK: s = {f = 0.00100000005, f2 = {10000, 100.5}}
+// CHECK: us = 65535
+// CHECK: f = 0
+// CHECK: d = {{[{][{]}}0, 1}, {2, 3{{[}][}]}}
+// CHECK: l = 0
+// CHECK: result = 0
+// DEBUGGER: continue 
+
+struct float_struct {
+  float f;
+  float f2[2];
+} compound_float;
+
+
+static
+int main(int argc, char* argv[])
+{
+  float f = 0.f;
+  float *pf = &f;
+
+  double d[2][2] = {{0, 1}, {2, 3.0}};
+  struct float_struct s;
+
+  unsigned short us = -1;
+  const unsigned long l = (unsigned long) -1.0e8f;
+
+  {
+    int** ppn = 0;
+    if (ppn) {
+      return -1;
+    }
+  }
+
+  s.f = 10e-4f;
+  s.f2[0] = 1e4f;
+  s.f2[1] = 100.5f;
+
+  double result = pf[0] * d[1][1] * s.f * us * l; 
+  return (result == 0 ? 0 : -1);
+}
+
+void entry() {
+  main(0, 0);
+}
+
+#pragma version(1)
+#pragma rs java_package_name(%PACKAGE%)
+
diff --git a/libbcc/tests/debuginfo/test_bcc_debuginfo.pl b/libbcc/tests/debuginfo/test_bcc_debuginfo.pl
new file mode 100755
index 0000000..fd2057d
--- /dev/null
+++ b/libbcc/tests/debuginfo/test_bcc_debuginfo.pl
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+#===-- test_bcc_debuginfo.pl - Debugger integration test driver script ---===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===----------------------------------------------------------------------===#
+#
+# This script tests debugging information generated by a compiler.
+# Input arguments
+#   - Path to FileCheck tool.
+#   - Input source program. Usually this source file is decorated using
+#     special comments (//DEBUGGER:, //CHECK:)to communicate debugger commands.
+#   - Executable file. This file is generated by the compiler.
+#
+# This perl script extracts debugger commands from input source program
+# comments in a script. A debugger is used to load the executable file
+# and run the script generated from source program comments. Finally,
+# the debugger output is checked, using FileCheck, to validate
+# debugging information.
+#
+#===----------------------------------------------------------------------===#
+
+use File::Basename;
+
+my $filecheck_tool = $ARGV[0];
+my $testcase_file = $ARGV[1];
+my $testcase_output = $ARGV[2];
+
+my $input_filename = basename $testcase_file;
+my $output_dir = dirname $testcase_output;
+
+my $debugger_script_file = "$output_dir/$input_filename.debugger.script";
+my $output_file = "$output_dir/$input_filename.gdb.output";
+
+open(OUTPUT, ">$debugger_script_file");
+
+# Enable extra verbosity in GDB
+print OUTPUT "set verbose on\n";
+
+# Extract debugger commands from testcase. They are marked with DEBUGGER:
+# at the beginning of a comment line.
+open(INPUT, $testcase_file);
+while(<INPUT>) {
+    my($line) = $_;
+    $i = index($line, "DEBUGGER:");
+    if ( $i >= 0) {
+        $l = length("DEBUGGER:");
+        $s = substr($line, $i + $l);
+        $s =~ s/\%s/$input_filename/g;
+        $s =~ s/\%t/$testcase_output/g;
+        print OUTPUT  "$s";
+    }
+}
+print OUTPUT "\n";
+print OUTPUT "quit\n";
+close(INPUT);
+close(OUTPUT);
+
+# setup debugger and debugger options to run a script.
+my $debugger = $ENV{'DEBUGGER'};
+my $debugger_options = $ENV{'DEBUGGER_ARGS'};
+if (!$debugger) {
+    print "Please set DEBUGGER prior to using this script";
+    exit 1;
+}
+$debugger_options = "-x $debugger_script_file $debugger_options $testcase_output";
+
+# run debugger and capture output.
+system("$debugger $debugger_options > $output_file 2>&1") ;
+if ($?>>8 != 0) {
+  print "Error during debugger invocation. Command used was: \n";
+  print("$debugger $debugger_options > $output_file 2>&1\n") ;
+  exit 1;
+}
+
+# validate output.
+system("$filecheck_tool", "-input-file", "$output_file", "$testcase_file");
+if ($?>>8 != 0) {
+    print "Error during verification. Debugger command used was: \n";
+    print("$debugger $debugger_options > $output_file 2>&1\n") ;
+    print "Verification command used was: \n";
+    print "$filecheck_tool -input-file $output_file $testcase_file\n";
+    exit 1;
+}
+else {
+    exit 0;
+}
diff --git a/libbcc/tests/libbcc/getelementptr.ll b/libbcc/tests/libbcc/getelementptr.ll
new file mode 100644
index 0000000..1cf201a
--- /dev/null
+++ b/libbcc/tests/libbcc/getelementptr.ll
@@ -0,0 +1,70 @@
+; This checks that RSForEachExpand generates getelementptr
+; instructions into the driver info structure as expected - namely,
+; that they index into the right positions of the structure and that
+; the instructions that are generated are in the loop header.
+
+; RUN: opt -load libbcc.so -kernelexp -S < %s | FileCheck %s
+
+; ModuleID = 'test_getelementptr.bc'
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Declarations expected by the expansion pass.
+declare void @_Z14rsGetElementAt13rs_allocationj()
+declare void @_Z14rsGetElementAt13rs_allocationjj()
+declare void @_Z14rsGetElementAt13rs_allocationjjj()
+declare void @_Z14rsSetElementAt13rs_allocationPvj()
+declare void @_Z14rsSetElementAt13rs_allocationPvjj()
+declare void @_Z14rsSetElementAt13rs_allocationPvjjj()
+declare void @_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj()
+declare void @_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj()
+declare void @_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj()
+
+; Old-style kernel
+define void @root(i32* nocapture %ain, i32* nocapture %out, i32 %x, i32 %y, i32 %z) {
+  ret void
+; CHECK: define void @root.expand(%RsExpandKernelDriverInfoPfx* %p, i32 %x1, i32 %x2, i32 %outstep)
+; CHECK: Begin:
+; CHECK: %instep_addr.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 1, i32 0
+; CHECK: load i32, i32* %instep_addr.gep
+; CHECK: %input_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 0, i32 0
+; CHECK: load i8*, i8** %input_buf.gep
+; CHECK: %out_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 3, i32 0
+; CHECK: load i8*, i8** %out_buf.gep
+; CHECK: %Y.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 1
+; CHECK: load i32, i32* %Y.gep
+; CHECK: %Z.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 2
+; CHECK: load i32, i32* %Z.gep
+; CHECK: Loop:
+}
+
+; New style kernel with multiple inputs
+define i32 @foo(i32 %in0, i32 %in1, i32 %x, i32 %y, i32 %z) {
+  ret i32 0
+; CHECK: define void @foo.expand(%RsExpandKernelDriverInfoPfx* %p, i32 %x1, i32 %x2, i32 %arg_outstep)
+; CHECK: Begin:
+; CHECK: %out_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 3, i32 0
+; CHECK: load i8*, i8** %out_buf.gep
+; CHECK: %Y.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 1
+; CHECK: load i32, i32* %Y.gep
+; CHECK: %Z.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 2
+; CHECK: load i32, i32* %Z.gep
+; CHECK: %input_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 0, i32 0
+; CHECK: load i8*, i8** %input_buf.gep
+; CHECK: %input_buf.gep1 = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 0, i32 1
+; CHECK: load i8*, i8** %input_buf.gep1
+; CHECK: Loop:
+}
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2}
+!\23rs_export_foreach_name = !{!3, !4}
+!\23rs_export_foreach = !{!5, !6}
+
+!0 = !{!"clang version 3.6 "}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"foo"}
+!3 = !{!"root"}
+!4 = !{!"foo"}
+!5 = !{!"91"}
+!6 = !{!"123"}
diff --git a/libbcc/tests/libbcc/lit.cfg b/libbcc/tests/libbcc/lit.cfg
new file mode 100644
index 0000000..331b771
--- /dev/null
+++ b/libbcc/tests/libbcc/lit.cfg
@@ -0,0 +1,53 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+import re
+
+# name: The name of this test suite.
+config.name = 'libbcc'
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.ll']
+
+# testFormat: The test format to use to interpret tests.
+import lit.formats
+config.test_format = lit.formats.ShTest()
+
+ANDROID_HOST_OUT = os.getenv("ANDROID_HOST_OUT")
+ANDROID_PRODUCT_OUT = os.getenv("ANDROID_PRODUCT_OUT")
+
+if not ANDROID_HOST_OUT or not ANDROID_PRODUCT_OUT:
+    import sys
+    sys.exit(1)
+
+# test_source_root: The path where tests are located (default is the test suite
+# root).
+config.test_source_root = None
+config.test_exec_root = os.path.join(ANDROID_HOST_OUT, 'tests', 'libbcc')
+
+tools_dir = os.pathsep.join([os.path.join(ANDROID_HOST_OUT, 'bin'),
+                             os.path.join(ANDROID_HOST_OUT, 'lib64'),
+                             os.path.join(ANDROID_PRODUCT_OUT, 'system/lib')])
+
+# Based on LLVM's lit.cfg: "For each occurrence of an llvm tool name
+# as its own word, replace it with the full path to the build directory
+# holding that tool."
+for pattern in [r"\bFileCheck\b",
+                r"\bllvm-rs-as\b",
+                r"\bbcinfo\b",
+                r"\bopt\b",
+                r"\blibbcc.so\b",
+                r"\bllvm-objdump\b",
+                r"\bbcc\b",
+                r"\blibclcore.bc\b"]:
+    tool_match = re.match(r"^(\\)?((\| )?)\W+b([\.0-9A-Za-z-_]+)\\b\W*$",
+                          pattern)
+    tool_pipe = tool_match.group(2)
+    tool_name = tool_match.group(4)
+    import lit.util
+    tool_path = lit.util.which(tool_name, tools_dir)
+    if not tool_path:
+        lit_config.note("Did not find " + tool_name + " in " + tools_dir)
+        tool_path = os.path.join(tools_dir, tool_name)
+    config.substitutions.append((pattern, tool_pipe + tool_path))
diff --git a/libbcc/tests/libbcc/tbaa-through-alloca.ll b/libbcc/tests/libbcc/tbaa-through-alloca.ll
new file mode 100644
index 0000000..5b0a270
--- /dev/null
+++ b/libbcc/tests/libbcc/tbaa-through-alloca.ll
@@ -0,0 +1,71 @@
+; This test checks that the code doesn't aggressively apply TBAA
+; metadata to temporaries that are passed by pointer to kernels.
+
+; RUN: opt -load libbcc.so -kernelexp -inline -tbaa -aa-eval -print-may-aliases -evaluate-aa-metadata < %s -S -o - 2>&1 | FileCheck %s
+
+; ModuleID = 'kernel.bc'
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Declarations expected by the expansion pass.
+declare void @_Z14rsGetElementAt13rs_allocationj()
+declare void @_Z14rsGetElementAt13rs_allocationjj()
+declare void @_Z14rsGetElementAt13rs_allocationjjj()
+declare void @_Z14rsSetElementAt13rs_allocationPvj()
+declare void @_Z14rsSetElementAt13rs_allocationPvjj()
+declare void @_Z14rsSetElementAt13rs_allocationPvjjj()
+declare void @_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj()
+declare void @_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj()
+declare void @_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj()
+
+%struct.int5.0 = type { [5 x i32] }
+
+; Function Attrs: nounwind
+define void @add1_int5(%struct.int5.0* noalias nocapture sret %agg.result, %struct.int5.0* nocapture %in) #0 {
+  br label %1
+
+; <label>:1                                       ; preds = %1, %0
+  %indvars.iv = phi i64 [ 0, %0 ], [ %indvars.iv.next, %1 ]
+  %2 = getelementptr inbounds %struct.int5.0, %struct.int5.0* %in, i64 0, i32 0, i64 %indvars.iv
+; CHECK: MayAlias: %load_from_input{{.*}} <-> store %struct.int5.0 %input, %struct.int5.0* %input_struct_slot
+  %load_from_input = load i32, i32* %2, align 4, !tbaa !9
+  %3 = add nsw i32 %load_from_input, 1
+  store i32 %3, i32* %2, align 4, !tbaa !9
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 5
+  br i1 %exitcond, label %4, label %1
+
+; <label>:4                                       ; preds = %1
+  %5 = bitcast %struct.int5.0* %agg.result to i8*
+  %6 = bitcast %struct.int5.0* %in to i8*
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* %6, i64 20, i32 4, i1 false), !tbaa.struct !13
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
+
+attributes #0 = { nounwind }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2}
+!\23rs_export_foreach_name = !{!3, !4}
+!\23rs_export_foreach = !{!5, !6}
+!\23rs_export_type = !{!7}
+!\25int5 = !{!8}
+
+!0 = !{!"clang version 3.6 "}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"foo"}
+!3 = !{!"root"}
+!4 = !{!"add1_int5"}
+!5 = !{!"0"}
+!6 = !{!"35"}
+!7 = !{!"int5"}
+!8 = !{!"data", !"<ConstantArray>"}
+!9 = !{!10, !10, i64 0}
+!10 = !{!"int", !11, i64 0}
+!11 = !{!"omnipotent char", !12, i64 0}
+!12 = !{!"Simple C/C++ TBAA"}
+!13 = !{i64 0, i64 20, !14}
+!14 = !{!11, !11, i64 0}
diff --git a/libbcc/tests/libbcc/tbaa.ll b/libbcc/tests/libbcc/tbaa.ll
new file mode 100644
index 0000000..6d8cb48
--- /dev/null
+++ b/libbcc/tests/libbcc/tbaa.ll
@@ -0,0 +1,43 @@
+; Basic test of TBAA that should report that pointer loads do not
+; alias with stores to allocations.
+
+; RUN: opt -load libbcc.so -kernelexp -tbaa -aa-eval -print-no-aliases -evaluate-aa-metadata < %s -S -o - 2>&1 | FileCheck %s
+
+; ModuleID = 'kernel.bc'
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Declarations expected by the expansion pass.
+declare void @_Z14rsGetElementAt13rs_allocationj()
+declare void @_Z14rsGetElementAt13rs_allocationjj()
+declare void @_Z14rsGetElementAt13rs_allocationjjj()
+declare void @_Z14rsSetElementAt13rs_allocationPvj()
+declare void @_Z14rsSetElementAt13rs_allocationPvjj()
+declare void @_Z14rsSetElementAt13rs_allocationPvjjj()
+declare void @_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj()
+declare void @_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj()
+declare void @_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj()
+
+; CHECK:   NoAlias:   %0 = load {{.*}}, i8** %out_buf.gep, !tbaa {{.*}} <->   store i32 %call.result, i32* {{.*}}, !tbaa {{.*}}
+; CHECK:   NoAlias:   %input_buf = load i8*, i8** %input_buf.gep, !tbaa {{.*}} <->   store i32 %call.result, i32* {{.*}}, !tbaa {{.*}}
+
+; Function Attrs: nounwind readnone
+define i32 @add1(i32 %in) #0 {
+  %1 = add nsw i32 %in, 1
+  ret i32 %1
+}
+
+attributes #0 = { nounwind readnone }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2}
+!\23rs_export_foreach_name = !{!3, !4}
+!\23rs_export_foreach = !{!5, !6}
+
+!0 = !{!"clang version 3.6 "}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"foo"}
+!3 = !{!"root"}
+!4 = !{!"add1"}
+!5 = !{!"0"}
+!6 = !{!"35"}
diff --git a/libbcc/tests/libbcc/test_reduce_general_cleanup.ll b/libbcc/tests/libbcc/test_reduce_general_cleanup.ll
new file mode 100644
index 0000000..214bc5c
--- /dev/null
+++ b/libbcc/tests/libbcc/test_reduce_general_cleanup.ll
@@ -0,0 +1,355 @@
+; Check that the unexpanded accumulator functions and the dummy variables are deleted.
+; There doesn't seem to be any way to compute the basename of %s, hence the unfortunate
+;   explicit uses of "test_reduce_general_cleanup" below.
+; There doesn't seem to be a way to write a CHECK-NOT pattern that matches only at the
+;   end of a line (llvm-objdump dumps symbol name at end of line), so sed is employed
+;   to add a '<' at the end of each line (symbol name).  This allows us to use (e.g.)
+;   "aiAccum<" to match the symbol "aiAccum" but not the symbol "aiAccum.expand".
+
+; RUN: llvm-rs-as %s -o %t
+; RUN: bcc -o test_reduce_general_cleanup -output_path %T -bclib libclcore.bc -mtriple armv7-none-linux-gnueabi %t
+; RUN: llvm-objdump -t %T/test_reduce_general_cleanup.o | sed -e 's!$!<!' | FileCheck %s
+
+; CHECK-NOT: .rs.reduce_fn
+; CHECK-NOT: aiAccum<
+; CHECK-NOT: mpyAccum<
+; CHECK-NOT: dpAccum<
+; CHECK-NOT: fMMAccumulator<
+; CHECK-NOT: fzAccum<
+; CHECK-NOT: fz2Accum<
+; CHECK-NOT: hsgAccum<
+
+; ModuleID = 'reduce.bc'
+target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none-linux-gnueabi"
+
+%struct.MinAndMax = type { %struct.IndexedVal, %struct.IndexedVal }
+%struct.IndexedVal = type { float, i32 }
+
+@.rs.reduce_fn.aiAccum = global i8* bitcast (void (i32*, i32)* @aiAccum to i8*), align 4
+@.rs.reduce_fn.dpAccum = global i8* bitcast (void (float*, float, float)* @dpAccum to i8*), align 4
+@.rs.reduce_fn.dpSum = global i8* bitcast (void (float*, float*)* @dpSum to i8*), align 4
+@.rs.reduce_fn.fMMInit = global i8* bitcast (void (%struct.MinAndMax*)* @fMMInit to i8*), align 4
+@.rs.reduce_fn.fMMAccumulator = global i8* bitcast (void (%struct.MinAndMax*, float, i32)* @fMMAccumulator to i8*), align 4
+@.rs.reduce_fn.fMMCombiner = global i8* bitcast (void (%struct.MinAndMax*, %struct.MinAndMax*)* @fMMCombiner to i8*), align 4
+@.rs.reduce_fn.fMMOutConverter = global i8* bitcast (void (<2 x i32>*, %struct.MinAndMax*)* @fMMOutConverter to i8*), align 4
+@.rs.reduce_fn.fzInit = global i8* bitcast (void (i32*)* @fzInit to i8*), align 4
+@.rs.reduce_fn.fzAccum = global i8* bitcast (void (i32*, i32, i32)* @fzAccum to i8*), align 4
+@.rs.reduce_fn.fzCombine = global i8* bitcast (void (i32*, i32*)* @fzCombine to i8*), align 4
+@.rs.reduce_fn.fz2Init = global i8* bitcast (void (<2 x i32>*)* @fz2Init to i8*), align 4
+@.rs.reduce_fn.fz2Accum = global i8* bitcast (void (<2 x i32>*, i32, i32, i32)* @fz2Accum to i8*), align 4
+@.rs.reduce_fn.fz2Combine = global i8* bitcast (void (<2 x i32>*, <2 x i32>*)* @fz2Combine to i8*), align 4
+@.rs.reduce_fn.fz3Init = global i8* bitcast (void (<3 x i32>*)* @fz3Init to i8*), align 4
+@.rs.reduce_fn.fz3Accum = global i8* bitcast (void (<3 x i32>*, i32, i32, i32, i32)* @fz3Accum to i8*), align 4
+@.rs.reduce_fn.fz3Combine = global i8* bitcast (void (<3 x i32>*, <3 x i32>*)* @fz3Combine to i8*), align 4
+@.rs.reduce_fn.hsgAccum = global i8* bitcast (void ([256 x i32]*, i8)* @hsgAccum to i8*), align 4
+@.rs.reduce_fn.hsgCombine = global i8* bitcast (void ([256 x i32]*, [256 x i32]*)* @hsgCombine to i8*), align 4
+@.rs.reduce_fn.modeOutConvert = global i8* bitcast (void (<2 x i32>*, [256 x i32]*)* @modeOutConvert to i8*), align 4
+@negInf = common global float 0.000000e+00, align 4
+@posInf = common global float 0.000000e+00, align 4
+
+; Function Attrs: nounwind
+define internal void @aiAccum(i32* nocapture %accum, i32 %val) #0 {
+  %1 = load i32, i32* %accum, align 4, !tbaa !22
+  %2 = add nsw i32 %1, %val
+  store i32 %2, i32* %accum, align 4, !tbaa !22
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @dpAccum(float* nocapture %accum, float %in1, float %in2) #0 {
+  %1 = fmul float %in1, %in2
+  %2 = load float, float* %accum, align 4, !tbaa !26
+  %3 = fadd float %1, %2
+  store float %3, float* %accum, align 4, !tbaa !26
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @dpSum(float* nocapture %accum, float* nocapture %val) #0 {
+  %1 = load float, float* %val, align 4, !tbaa !26
+  %2 = load float, float* %accum, align 4, !tbaa !26
+  %3 = fadd float %1, %2
+  store float %3, float* %accum, align 4, !tbaa !26
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fMMInit(%struct.MinAndMax* nocapture %accum) #0 {
+  %1 = load i32, i32* bitcast (float* @posInf to i32*), align 4, !tbaa !26
+  %2 = bitcast %struct.MinAndMax* %accum to i32*
+  store i32 %1, i32* %2, align 4, !tbaa !26
+  %3 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 0, i32 1
+  store i32 -1, i32* %3, align 4, !tbaa !22
+  %4 = load i32, i32* bitcast (float* @negInf to i32*), align 4, !tbaa !26
+  %5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1
+  %6 = bitcast %struct.IndexedVal* %5 to i32*
+  store i32 %4, i32* %6, align 4, !tbaa !26
+  %7 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1, i32 1
+  store i32 -1, i32* %7, align 4, !tbaa !22
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fMMAccumulator(%struct.MinAndMax* nocapture %accum, float %in, i32 %x) #0 {
+  %1 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 0, i32 0
+  %2 = load float, float* %1, align 4, !tbaa !26
+  %3 = fcmp ogt float %2, %in
+  br i1 %3, label %4, label %6
+
+; <label>:4                                       ; preds = %0
+  store float %in, float* %1, align 4
+  %5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 0, i32 1
+  store i32 %x, i32* %5, align 4
+  br label %6
+
+; <label>:6                                       ; preds = %4, %0
+  %7 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1, i32 0
+  %8 = load float, float* %7, align 4, !tbaa !26
+  %9 = fcmp olt float %8, %in
+  br i1 %9, label %10, label %12
+
+; <label>:10                                      ; preds = %6
+  store float %in, float* %7, align 4
+  %11 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1, i32 1
+  store i32 %x, i32* %11, align 4
+  br label %12
+
+; <label>:12                                      ; preds = %10, %6
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fMMCombiner(%struct.MinAndMax* nocapture %accum, %struct.MinAndMax* nocapture %val) #0 {
+  %1 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 0, i32 0
+  %2 = load float, float* %1, align 4, !tbaa !26
+  %3 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 0, i32 1
+  %4 = load i32, i32* %3, align 4, !tbaa !22
+  tail call void @fMMAccumulator(%struct.MinAndMax* %accum, float %2, i32 %4)
+  %5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 1, i32 0
+  %6 = load float, float* %5, align 4, !tbaa !26
+  %7 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 1, i32 1
+  %8 = load i32, i32* %7, align 4, !tbaa !22
+  tail call void @fMMAccumulator(%struct.MinAndMax* %accum, float %6, i32 %8)
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fMMOutConverter(<2 x i32>* nocapture %result, %struct.MinAndMax* nocapture %val) #0 {
+  %1 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 0, i32 1
+  %2 = load i32, i32* %1, align 4, !tbaa !22
+  %3 = load <2 x i32>, <2 x i32>* %result, align 8
+  %4 = insertelement <2 x i32> %3, i32 %2, i32 0
+  store <2 x i32> %4, <2 x i32>* %result, align 8
+  %5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 1, i32 1
+  %6 = load i32, i32* %5, align 4, !tbaa !22
+  %7 = insertelement <2 x i32> %4, i32 %6, i32 1
+  store <2 x i32> %7, <2 x i32>* %result, align 8
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fzInit(i32* nocapture %accumIdx) #0 {
+  store i32 -1, i32* %accumIdx, align 4, !tbaa !22
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fzAccum(i32* nocapture %accumIdx, i32 %inVal, i32 %x) #0 {
+  %1 = icmp eq i32 %inVal, 0
+  br i1 %1, label %2, label %3
+
+; <label>:2                                       ; preds = %0
+  store i32 %x, i32* %accumIdx, align 4, !tbaa !22
+  br label %3
+
+; <label>:3                                       ; preds = %2, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fzCombine(i32* nocapture %accumIdx, i32* nocapture %accumIdx2) #0 {
+  %1 = load i32, i32* %accumIdx2, align 4, !tbaa !22
+  %2 = icmp sgt i32 %1, -1
+  br i1 %2, label %3, label %4
+
+; <label>:3                                       ; preds = %0
+  store i32 %1, i32* %accumIdx, align 4, !tbaa !22
+  br label %4
+
+; <label>:4                                       ; preds = %3, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz2Init(<2 x i32>* nocapture %accum) #0 {
+  store <2 x i32> <i32 -1, i32 -1>, <2 x i32>* %accum, align 8
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz2Accum(<2 x i32>* nocapture %accum, i32 %inVal, i32 %x, i32 %y) #0 {
+  %1 = icmp eq i32 %inVal, 0
+  br i1 %1, label %2, label %5
+
+; <label>:2                                       ; preds = %0
+  %3 = insertelement <2 x i32> undef, i32 %x, i32 0
+  %4 = insertelement <2 x i32> %3, i32 %y, i32 1
+  store <2 x i32> %4, <2 x i32>* %accum, align 8
+  br label %5
+
+; <label>:5                                       ; preds = %2, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz2Combine(<2 x i32>* nocapture %accum, <2 x i32>* nocapture %accum2) #0 {
+  %1 = load <2 x i32>, <2 x i32>* %accum2, align 8
+  %2 = extractelement <2 x i32> %1, i32 0
+  %3 = icmp sgt i32 %2, -1
+  br i1 %3, label %4, label %5
+
+; <label>:4                                       ; preds = %0
+  store <2 x i32> %1, <2 x i32>* %accum, align 8, !tbaa !28
+  br label %5
+
+; <label>:5                                       ; preds = %4, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz3Init(<3 x i32>* nocapture %accum) #0 {
+  store <3 x i32> <i32 -1, i32 -1, i32 -1>, <3 x i32>* %accum, align 16
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz3Accum(<3 x i32>* nocapture %accum, i32 %inVal, i32 %x, i32 %y, i32 %z) #0 {
+  %1 = icmp eq i32 %inVal, 0
+  br i1 %1, label %2, label %6
+
+; <label>:2                                       ; preds = %0
+  %3 = insertelement <3 x i32> undef, i32 %x, i32 0
+  %4 = insertelement <3 x i32> %3, i32 %y, i32 1
+  %5 = insertelement <3 x i32> %4, i32 %z, i32 2
+  store <3 x i32> %5, <3 x i32>* %accum, align 16
+  br label %6
+
+; <label>:6                                       ; preds = %2, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz3Combine(<3 x i32>* nocapture %accum, <3 x i32>* nocapture %accum2) #0 {
+  %1 = load <3 x i32>, <3 x i32>* %accum, align 16
+  %2 = extractelement <3 x i32> %1, i32 0
+  %3 = icmp sgt i32 %2, -1
+  br i1 %3, label %4, label %8
+
+; <label>:4                                       ; preds = %0
+  %5 = bitcast <3 x i32>* %accum2 to <4 x i32>*
+  %6 = load <4 x i32>, <4 x i32>* %5, align 8
+  %7 = bitcast <3 x i32>* %accum to <4 x i32>*
+  store <4 x i32> %6, <4 x i32>* %7, align 16, !tbaa !28
+  br label %8
+
+; <label>:8                                       ; preds = %4, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @hsgAccum([256 x i32]* nocapture %h, i8 zeroext %in) #0 {
+  %1 = zext i8 %in to i32
+  %2 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %1
+  %3 = load i32, i32* %2, align 4, !tbaa !22
+  %4 = add i32 %3, 1
+  store i32 %4, i32* %2, align 4, !tbaa !22
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @hsgCombine([256 x i32]* nocapture %accum, [256 x i32]* nocapture %addend) #0 {
+  br label %2
+
+; <label>:1                                       ; preds = %2
+  ret void
+
+; <label>:2                                       ; preds = %2, %0
+  %i.01 = phi i32 [ 0, %0 ], [ %8, %2 ]
+  %3 = getelementptr inbounds [256 x i32], [256 x i32]* %addend, i32 0, i32 %i.01
+  %4 = load i32, i32* %3, align 4, !tbaa !22
+  %5 = getelementptr inbounds [256 x i32], [256 x i32]* %accum, i32 0, i32 %i.01
+  %6 = load i32, i32* %5, align 4, !tbaa !22
+  %7 = add i32 %6, %4
+  store i32 %7, i32* %5, align 4, !tbaa !22
+  %8 = add nuw nsw i32 %i.01, 1
+  %exitcond = icmp eq i32 %8, 256
+  br i1 %exitcond, label %1, label %2
+}
+
+; Function Attrs: nounwind
+define internal void @modeOutConvert(<2 x i32>* nocapture %result, [256 x i32]* nocapture %h) #0 {
+  br label %7
+
+; <label>:1                                       ; preds = %7
+  %2 = load <2 x i32>, <2 x i32>* %result, align 8
+  %3 = insertelement <2 x i32> %2, i32 %i.0.mode.0, i32 0
+  store <2 x i32> %3, <2 x i32>* %result, align 8
+  %4 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %i.0.mode.0
+  %5 = load i32, i32* %4, align 4, !tbaa !22
+  %6 = insertelement <2 x i32> %3, i32 %5, i32 1
+  store <2 x i32> %6, <2 x i32>* %result, align 8
+  ret void
+
+; <label>:7                                       ; preds = %7, %0
+  %i.02 = phi i32 [ 1, %0 ], [ %13, %7 ]
+  %mode.01 = phi i32 [ 0, %0 ], [ %i.0.mode.0, %7 ]
+  %8 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %i.02
+  %9 = load i32, i32* %8, align 4, !tbaa !22
+  %10 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %mode.01
+  %11 = load i32, i32* %10, align 4, !tbaa !22
+  %12 = icmp ugt i32 %9, %11
+  %i.0.mode.0 = select i1 %12, i32 %i.02, i32 %mode.01
+  %13 = add nuw nsw i32 %i.02, 1
+  %exitcond = icmp eq i32 %13, 256
+  br i1 %exitcond, label %1, label %7
+}
+
+attributes #0 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+!\23pragma = !{!3, !4}
+!\23rs_export_var = !{!5, !6}
+!\23rs_object_slots = !{}
+!\23rs_export_reduce = !{!7, !9, !11, !13, !15, !17, !19, !21}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"min_enum_size", i32 4}
+!2 = !{!"clang version 3.6 "}
+!3 = !{!"version", !"1"}
+!4 = !{!"java_package_name", !"com.android.rs.test"}
+!5 = !{!"negInf", !"1"}
+!6 = !{!"posInf", !"1"}
+!7 = !{!"addint", !"4", !8}
+!8 = !{!"aiAccum", !"1"}
+!9 = !{!"dp", !"4", !10, null, !"dpSum"}
+!10 = !{!"dpAccum", !"1"}
+!11 = !{!"findMinAndMax", !"16", !12, !"fMMInit", !"fMMCombiner", !"fMMOutConverter"}
+!12 = !{!"fMMAccumulator", !"9"}
+!13 = !{!"fz", !"4", !14, !"fzInit", !"fzCombine"}
+!14 = !{!"fzAccum", !"9"}
+!15 = !{!"fz2", !"8", !16, !"fz2Init", !"fz2Combine"}
+!16 = !{!"fz2Accum", !"25"}
+!17 = !{!"fz3", !"16", !18, !"fz3Init", !"fz3Combine"}
+!18 = !{!"fz3Accum", !"89"}
+!19 = !{!"histogram", !"1024", !20, null, !"hsgCombine"}
+!20 = !{!"hsgAccum", !"1"}
+!21 = !{!"mode", !"1024", !20, null, !"hsgCombine", !"modeOutConvert"}
+!22 = !{!23, !23, i64 0}
+!23 = !{!"int", !24, i64 0}
+!24 = !{!"omnipotent char", !25, i64 0}
+!25 = !{!"Simple C/C++ TBAA"}
+!26 = !{!27, !27, i64 0}
+!27 = !{!"float", !24, i64 0}
+!28 = !{!24, !24, i64 0}
diff --git a/libbcc/tests/libbcc/test_reduce_general_metadata.ll b/libbcc/tests/libbcc/test_reduce_general_metadata.ll
new file mode 100644
index 0000000..ebf1df4
--- /dev/null
+++ b/libbcc/tests/libbcc/test_reduce_general_metadata.ll
@@ -0,0 +1,333 @@
+; Check that the #rs_export_reduce node is recognized.
+
+; RUN: llvm-rs-as %s -o %t
+; RUN: bcinfo %t | FileCheck %s
+
+; CHECK: exportReduceCount: 8
+; CHECK: exportReduceList[0]: addint - 0x00000001 - 1 - 4
+; CHECK:   accumulator(aiAccum)
+; CHECK: exportReduceList[1]: mpyint - 0x00000001 - 1 - 4
+; CHECK:   initializer(mpyInit)
+; CHECK:   accumulator(mpyAccum)
+; CHECK: exportReduceList[2]: dp - 0x00000001 - 2 - 4
+; CHECK:   accumulator(dpAccum)
+; CHECK:   combiner(dpSum)
+; CHECK: exportReduceList[3]: findMinAndMax - 0x00000009 - 1 - 16
+; CHECK:   initializer(fMMInit)
+; CHECK:   accumulator(fMMAccumulator)
+; CHECK:   combiner(fMMCombiner)
+; CHECK:   outconverter(fMMOutConverter)
+; CHECK: exportReduceList[4]: fz - 0x00000009 - 1 - 4
+; CHECK:   initializer(fzInit)
+; CHECK:   accumulator(fzAccum)
+; CHECK:   combiner(fzCombine)
+; CHECK:   halter(fzFound)
+; CHECK: exportReduceList[5]: fz2 - 0x00000019 - 1 - 8
+; CHECK:   initializer(fz2Init)
+; CHECK:   accumulator(fz2Accum)
+; CHECK:   combiner(fz2Combine)
+; CHECK:   halter(fz2Found)
+; CHECK: exportReduceList[6]: histogram - 0x00000001 - 1 - 1024
+; CHECK:   accumulator(hsgAccum)
+; CHECK:   combiner(hsgCombine)
+; CHECK: exportReduceList[7]: mode - 0x00000001 - 1 - 1024
+; CHECK:   accumulator(hsgAccum)
+; CHECK:   combiner(hsgCombine)
+; CHECK:   outconverter(modeOutConvert)
+
+; ModuleID = 'reduce_general_examples.bc'
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+%struct.MinAndMax.0 = type { %struct.IndexedVal.1, %struct.IndexedVal.1 }
+%struct.IndexedVal.1 = type { float, i32 }
+
+@fMMInit.r = internal unnamed_addr constant %struct.MinAndMax.0 { %struct.IndexedVal.1 { float 0.000000e+00, i32 -1 }, %struct.IndexedVal.1 { float -0.000000e+00, i32 -1 } }, align 4
+@llvm.used = appending global [20 x i8*] [i8* bitcast (void (<2 x i32>*)* @fz2Init to i8*), i8* bitcast (void ([256 x i32]*, [256 x i32]*)* @hsgCombine to i8*), i8* bitcast (i1 (<2 x i32>*)* @fz2Found to i8*), i8* bitcast (void (i32*, i32)* @mpyAccum to i8*), i8* bitcast (void (%struct.MinAndMax.0*)* @fMMInit to i8*), i8* bitcast (void (float*, float, float)* @dpAccum to i8*), i8* bitcast (void (<2 x i32>*, [256 x i32]*)* @modeOutConvert to i8*), i8* bitcast (void ([256 x i32]*, i8)* @hsgAccum to i8*), i8* bitcast (void (i32*)* @mpyInit to i8*), i8* bitcast (void (%struct.MinAndMax.0*, float, i32)* @fMMAccumulator to i8*), i8* bitcast (void (float*, float*)* @dpSum to i8*), i8* bitcast (void (%struct.MinAndMax.0*, %struct.MinAndMax.0*)* @fMMCombiner to i8*), i8* bitcast (void (i32*, i32*)* @fzCombine to i8*), i8* bitcast (void (i32*, i32)* @aiAccum to i8*), i8* bitcast (void (i32*)* @fzInit to i8*), i8* bitcast (void (i32*, i32, i32)* @fzAccum to i8*), i8* bitcast (i1 (i32*)* @fzFound to i8*), i8* bitcast (void (<2 x i32>*, i32, i32, i32)* @fz2Accum to i8*), i8* bitcast (void (<2 x i32>*, %struct.MinAndMax.0*)* @fMMOutConverter to i8*), i8* bitcast (void (<2 x i32>*, <2 x i32>*)* @fz2Combine to i8*)], section "llvm.metadata"
+
+; Function Attrs: nounwind
+define internal void @aiAccum(i32* nocapture %accum, i32 %val) #0 {
+  %1 = load i32, i32* %accum, align 4, !tbaa !18
+  %2 = add nsw i32 %1, %val
+  store i32 %2, i32* %accum, align 4, !tbaa !18
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @mpyInit(i32* nocapture %accum) #0 {
+  store i32 1, i32* %accum, align 4, !tbaa !18
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @mpyAccum(i32* nocapture %accum, i32 %val) #0 {
+  %1 = load i32, i32* %accum, align 4, !tbaa !18
+  %2 = mul nsw i32 %1, %val
+  store i32 %2, i32* %accum, align 4, !tbaa !18
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @dpAccum(float* nocapture %accum, float %in1, float %in2) #0 {
+  %1 = fmul float %in1, %in2
+  %2 = load float, float* %accum, align 4, !tbaa !22
+  %3 = fadd float %1, %2
+  store float %3, float* %accum, align 4, !tbaa !22
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @dpSum(float* nocapture %accum, float* nocapture %val) #0 {
+  %1 = load float, float* %val, align 4, !tbaa !22
+  %2 = load float, float* %accum, align 4, !tbaa !22
+  %3 = fadd float %1, %2
+  store float %3, float* %accum, align 4, !tbaa !22
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fMMInit(%struct.MinAndMax.0* nocapture %accum) #0 {
+  %1 = bitcast %struct.MinAndMax.0* %accum to i8*
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast (%struct.MinAndMax.0* @fMMInit.r to i8*), i64 16, i32 4, i1 false), !tbaa.struct !24
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
+
+; Function Attrs: nounwind
+define internal void @fMMAccumulator(%struct.MinAndMax.0* nocapture %accum, float %in, i32 %x) #0 {
+  %1 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 0, i32 0
+  %2 = load float, float* %1, align 4, !tbaa !22
+  %3 = fcmp ogt float %2, %in
+  br i1 %3, label %4, label %6
+
+; <label>:4                                       ; preds = %0
+  store float %in, float* %1, align 4
+  %5 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 0, i32 1
+  store i32 %x, i32* %5, align 4
+  br label %6
+
+; <label>:6                                       ; preds = %4, %0
+  %7 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 1, i32 0
+  %8 = load float, float* %7, align 4, !tbaa !22
+  %9 = fcmp olt float %8, %in
+  br i1 %9, label %10, label %12
+
+; <label>:10                                      ; preds = %6
+  store float %in, float* %7, align 4
+  %11 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 1, i32 1
+  store i32 %x, i32* %11, align 4
+  br label %12
+
+; <label>:12                                      ; preds = %10, %6
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fMMCombiner(%struct.MinAndMax.0* nocapture %accum, %struct.MinAndMax.0* nocapture %val) #0 {
+  %1 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 0, i32 0
+  %2 = load float, float* %1, align 4, !tbaa !22
+  %3 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 0, i32 1
+  %4 = load i32, i32* %3, align 4, !tbaa !18
+  tail call void @fMMAccumulator(%struct.MinAndMax.0* %accum, float %2, i32 %4)
+  %5 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 1, i32 0
+  %6 = load float, float* %5, align 4, !tbaa !22
+  %7 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 1, i32 1
+  %8 = load i32, i32* %7, align 4, !tbaa !18
+  tail call void @fMMAccumulator(%struct.MinAndMax.0* %accum, float %6, i32 %8)
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fMMOutConverter(<2 x i32>* nocapture %result, %struct.MinAndMax.0* nocapture %val) #0 {
+  %1 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 0, i32 1
+  %2 = load i32, i32* %1, align 4, !tbaa !18
+  %3 = load <2 x i32>, <2 x i32>* %result, align 8
+  %4 = insertelement <2 x i32> %3, i32 %2, i64 0
+  store <2 x i32> %4, <2 x i32>* %result, align 8
+  %5 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 1, i32 1
+  %6 = load i32, i32* %5, align 4, !tbaa !18
+  %7 = insertelement <2 x i32> %4, i32 %6, i64 1
+  store <2 x i32> %7, <2 x i32>* %result, align 8
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fzInit(i32* nocapture %accumIdx) #0 {
+  store i32 -1, i32* %accumIdx, align 4, !tbaa !18
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fzAccum(i32* nocapture %accumIdx, i32 %inVal, i32 %x) #0 {
+  %1 = icmp eq i32 %inVal, 0
+  br i1 %1, label %2, label %3
+
+; <label>:2                                       ; preds = %0
+  store i32 %x, i32* %accumIdx, align 4, !tbaa !18
+  br label %3
+
+; <label>:3                                       ; preds = %2, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fzCombine(i32* nocapture %accumIdx, i32* nocapture %accumIdx2) #0 {
+  %1 = load i32, i32* %accumIdx2, align 4, !tbaa !18
+  %2 = icmp sgt i32 %1, -1
+  br i1 %2, label %3, label %4
+
+; <label>:3                                       ; preds = %0
+  store i32 %1, i32* %accumIdx, align 4, !tbaa !18
+  br label %4
+
+; <label>:4                                       ; preds = %3, %0
+  ret void
+}
+
+; Function Attrs: nounwind readonly
+define internal i1 @fzFound(i32* nocapture %accumIdx) #1 {
+  %1 = load i32, i32* %accumIdx, align 4, !tbaa !18
+  %2 = icmp sgt i32 %1, -1
+  ret i1 %2
+}
+
+; Function Attrs: nounwind
+define internal void @fz2Init(<2 x i32>* nocapture %accum) #0 {
+  store <2 x i32> <i32 -1, i32 -1>, <2 x i32>* %accum, align 8
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz2Accum(<2 x i32>* nocapture %accum, i32 %inVal, i32 %x, i32 %y) #0 {
+  %1 = icmp eq i32 %inVal, 0
+  br i1 %1, label %2, label %5
+
+; <label>:2                                       ; preds = %0
+  %3 = insertelement <2 x i32> undef, i32 %x, i64 0
+  %4 = insertelement <2 x i32> %3, i32 %y, i64 1
+  store <2 x i32> %4, <2 x i32>* %accum, align 8
+  br label %5
+
+; <label>:5                                       ; preds = %2, %0
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @fz2Combine(<2 x i32>* nocapture %accum, <2 x i32>* nocapture %accum2) #0 {
+  %1 = load <2 x i32>, <2 x i32>* %accum2, align 8
+  %2 = extractelement <2 x i32> %1, i64 0
+  %3 = icmp sgt i32 %2, -1
+  br i1 %3, label %4, label %5
+
+; <label>:4                                       ; preds = %0
+  store <2 x i32> %1, <2 x i32>* %accum, align 8, !tbaa !25
+  br label %5
+
+; <label>:5                                       ; preds = %4, %0
+  ret void
+}
+
+; Function Attrs: nounwind readonly
+define internal i1 @fz2Found(<2 x i32>* nocapture %accum) #1 {
+  %1 = load <2 x i32>, <2 x i32>* %accum, align 8
+  %2 = extractelement <2 x i32> %1, i64 0
+  %3 = icmp sgt i32 %2, -1
+  ret i1 %3
+}
+
+; Function Attrs: nounwind
+define internal void @hsgAccum([256 x i32]* nocapture %h, i8 %in) #0 {
+  %1 = zext i8 %in to i64
+  %2 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %1
+  %3 = load i32, i32* %2, align 4, !tbaa !18
+  %4 = add i32 %3, 1
+  store i32 %4, i32* %2, align 4, !tbaa !18
+  ret void
+}
+
+; Function Attrs: nounwind
+define internal void @hsgCombine([256 x i32]* nocapture %accum, [256 x i32]* nocapture %addend) #0 {
+  br label %2
+
+; <label>:1                                       ; preds = %2
+  ret void
+
+; <label>:2                                       ; preds = %2, %0
+  %indvars.iv = phi i64 [ 0, %0 ], [ %indvars.iv.next, %2 ]
+  %3 = getelementptr inbounds [256 x i32], [256 x i32]* %addend, i64 0, i64 %indvars.iv
+  %4 = load i32, i32* %3, align 4, !tbaa !18
+  %5 = getelementptr inbounds [256 x i32], [256 x i32]* %accum, i64 0, i64 %indvars.iv
+  %6 = load i32, i32* %5, align 4, !tbaa !18
+  %7 = add i32 %6, %4
+  store i32 %7, i32* %5, align 4, !tbaa !18
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 256
+  br i1 %exitcond, label %1, label %2
+}
+
+; Function Attrs: nounwind
+define internal void @modeOutConvert(<2 x i32>* nocapture %result, [256 x i32]* nocapture %h) #0 {
+  br label %8
+
+; <label>:1                                       ; preds = %8
+  %2 = load <2 x i32>, <2 x i32>* %result, align 8
+  %3 = insertelement <2 x i32> %2, i32 %i.0.mode.0, i64 0
+  store <2 x i32> %3, <2 x i32>* %result, align 8
+  %4 = zext i32 %i.0.mode.0 to i64
+  %5 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %4
+  %6 = load i32, i32* %5, align 4, !tbaa !18
+  %7 = insertelement <2 x i32> %3, i32 %6, i64 1
+  store <2 x i32> %7, <2 x i32>* %result, align 8
+  ret void
+
+; <label>:8                                       ; preds = %8, %0
+  %indvars.iv = phi i64 [ 1, %0 ], [ %indvars.iv.next, %8 ]
+  %mode.01 = phi i32 [ 0, %0 ], [ %i.0.mode.0, %8 ]
+  %9 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %indvars.iv
+  %10 = load i32, i32* %9, align 4, !tbaa !18
+  %11 = zext i32 %mode.01 to i64
+  %12 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %11
+  %13 = load i32, i32* %12, align 4, !tbaa !18
+  %14 = icmp ugt i32 %10, %13
+  %15 = trunc i64 %indvars.iv to i32
+  %i.0.mode.0 = select i1 %14, i32 %15, i32 %mode.01
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 256
+  br i1 %exitcond, label %1, label %8
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2}
+!\23rs_export_reduce = !{!3, !5, !7, !9, !11, !13, !15, !17}
+
+!0 = !{!"clang version 3.6 "}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"examples"}
+!3 = !{!"addint", !"4", !4}
+!4 = !{!"aiAccum", !"1"}
+!5 = !{!"mpyint", !"4", !6, !"mpyInit"}
+!6 = !{!"mpyAccum", !"1"}
+!7 = !{!"dp", !"4", !8, null, !"dpSum"}
+!8 = !{!"dpAccum", !"1"}
+!9 = !{!"findMinAndMax", !"16", !10, !"fMMInit", !"fMMCombiner", !"fMMOutConverter"}
+!10 = !{!"fMMAccumulator", !"9"}
+!11 = !{!"fz", !"4", !12, !"fzInit", !"fzCombine", null, !"fzFound"}
+!12 = !{!"fzAccum", !"9"}
+!13 = !{!"fz2", !"8", !14, !"fz2Init", !"fz2Combine", null, !"fz2Found"}
+!14 = !{!"fz2Accum", !"25"}
+!15 = !{!"histogram", !"1024", !16, null, !"hsgCombine"}
+!16 = !{!"hsgAccum", !"1"}
+!17 = !{!"mode", !"1024", !16, null, !"hsgCombine", !"modeOutConvert"}
+!18 = !{!19, !19, i64 0}
+!19 = !{!"int", !20, i64 0}
+!20 = !{!"omnipotent char", !21, i64 0}
+!21 = !{!"Simple C/C++ TBAA"}
+!22 = !{!23, !23, i64 0}
+!23 = !{!"float", !20, i64 0}
+!24 = !{i64 0, i64 4, !22, i64 4, i64 4, !18, i64 8, i64 4, !22, i64 12, i64 4, !18}
+!25 = !{!20, !20, i64 0}
diff --git a/libbcc/tests/run-lit-tests.sh b/libbcc/tests/run-lit-tests.sh
new file mode 100755
index 0000000..8976555
--- /dev/null
+++ b/libbcc/tests/run-lit-tests.sh
@@ -0,0 +1,6 @@
+#!/bin/bash -e
+
+LIT_PATH=$ANDROID_BUILD_TOP/frameworks/compile/libbcc/tests/debuginfo/llvm-lit
+LIBBCC_TESTS=$ANDROID_BUILD_TOP/frameworks/compile/libbcc/tests/libbcc
+
+$LIT_PATH $LIBBCC_TESTS $@
diff --git a/libbcc/tools/Android.mk b/libbcc/tools/Android.mk
new file mode 100644
index 0000000..1106ba0
--- /dev/null
+++ b/libbcc/tools/Android.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libbcc/tools/bcc/Android.mk b/libbcc/tools/bcc/Android.mk
new file mode 100644
index 0000000..b2a8410
--- /dev/null
+++ b/libbcc/tools/bcc/Android.mk
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# Executable for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bcc
+LOCAL_MODULE_CLASS := EXECUTABLES
+
+LOCAL_SRC_FILES := Main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+  libbcc \
+  libbcinfo \
+  libLLVM
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/../../include
+
+LOCAL_LDLIBS = -ldl
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(BUILD_HOST_EXECUTABLE)
+
+# Executable for target
+# ========================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bcc
+LOCAL_MODULE_CLASS := EXECUTABLES
+
+LOCAL_SRC_FILES := Main.cpp
+
+LOCAL_SHARED_LIBRARIES := libdl liblog libbcinfo libbcc libLLVM libutils libcutils
+
+include $(LIBBCC_DEVICE_BUILD_MK)
+include $(LLVM_DEVICE_BUILD_MK)
+include $(BUILD_EXECUTABLE)
+endif
diff --git a/libbcc/tools/bcc/Main.cpp b/libbcc/tools/bcc/Main.cpp
new file mode 100644
index 0000000..1181e43
--- /dev/null
+++ b/libbcc/tools/bcc/Main.cpp
@@ -0,0 +1,371 @@
+/*
+ * 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 <iostream>
+#include <list>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/ADT/SmallString.h>
+#include <llvm/Config/config.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/Path.h>
+#include <llvm/Support/PluginLoader.h>
+#include <llvm/Support/raw_ostream.h>
+
+#include <bcc/BCCContext.h>
+#include <bcc/Compiler.h>
+#include <bcc/Config/Config.h>
+#include <bcc/Renderscript/RSCompilerDriver.h>
+#include <bcc/Script.h>
+#include <bcc/Source.h>
+#include <bcc/Support/Log.h>
+#include <bcc/Support/CompilerConfig.h>
+#include <bcc/Support/Initialization.h>
+#include <bcc/Support/InputFile.h>
+#include <bcc/Support/OutputFile.h>
+
+using namespace bcc;
+
+#define STR2(a) #a
+#define STR(a) STR2(a)
+
+//===----------------------------------------------------------------------===//
+// General Options
+//===----------------------------------------------------------------------===//
+namespace {
+
+llvm::cl::list<std::string>
+OptInputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
+                  llvm::cl::desc("<input bitcode files>"));
+
+llvm::cl::list<std::string>
+OptMergePlans("merge", llvm::cl::ZeroOrMore,
+               llvm::cl::desc("Lists of kernels to merge (as source-and-slot "
+                              "pairs) and names for the final merged kernels"));
+
+llvm::cl::list<std::string>
+OptInvokes("invoke", llvm::cl::ZeroOrMore,
+           llvm::cl::desc("Invocable functions"));
+
+llvm::cl::opt<std::string>
+OptOutputFilename("o", llvm::cl::desc("Specify the output filename"),
+                  llvm::cl::value_desc("filename"),
+                  llvm::cl::init("bcc_output"));
+
+llvm::cl::opt<std::string>
+OptBCLibFilename("bclib", llvm::cl::desc("Specify the bclib filename"),
+                 llvm::cl::value_desc("bclib"));
+
+llvm::cl::opt<std::string>
+OptBCLibRelaxedFilename("bclib_relaxed", llvm::cl::desc("Specify the bclib filename optimized for "
+                                                        "relaxed precision floating point maths"),
+                        llvm::cl::init(""),
+                        llvm::cl::value_desc("bclib_relaxed"));
+
+llvm::cl::opt<std::string>
+OptOutputPath("output_path", llvm::cl::desc("Specify the output path"),
+              llvm::cl::value_desc("output path"),
+              llvm::cl::init("."));
+
+llvm::cl::opt<bool>
+OptEmitLLVM("emit-llvm",
+            llvm::cl::desc("Emit an LLVM-IR version of the generated program"));
+
+llvm::cl::opt<std::string>
+OptTargetTriple("mtriple",
+                llvm::cl::desc("Specify the target triple (default: "
+                               DEFAULT_TARGET_TRIPLE_STRING ")"),
+                llvm::cl::init(DEFAULT_TARGET_TRIPLE_STRING),
+                llvm::cl::value_desc("triple"));
+
+llvm::cl::alias OptTargetTripleC("C", llvm::cl::NotHidden,
+                                 llvm::cl::desc("Alias for -mtriple"),
+                                 llvm::cl::aliasopt(OptTargetTriple));
+
+llvm::cl::opt<bool>
+OptRSDebugContext("rs-debug-ctx",
+    llvm::cl::desc("Enable build to work with a RenderScript debug context"));
+
+llvm::cl::opt<bool>
+OptRSGlobalInfo("rs-global-info",
+    llvm::cl::desc("Embed information about global variables in the code"));
+
+llvm::cl::opt<bool>
+OptRSGlobalInfoSkipConstant("rs-global-info-skip-constant",
+    llvm::cl::desc("Skip embedding information about constant global "
+                   "variables in the code"));
+
+llvm::cl::opt<std::string>
+OptChecksum("build-checksum",
+            llvm::cl::desc("Embed a checksum of this compiler invocation for"
+                           " cache invalidation at a later time"),
+            llvm::cl::value_desc("checksum"));
+
+//===----------------------------------------------------------------------===//
+// Compiler Options
+//===----------------------------------------------------------------------===//
+llvm::cl::opt<bool>
+OptPIC("fPIC", llvm::cl::desc("Generate fully relocatable, position independent"
+                              " code"));
+
+// If set, use buildForCompatLib to embed RS symbol information into the object
+// file.  The information is stored in the .rs.info variable.  This option is
+// to be used in tandem with -fPIC.
+llvm::cl::opt<bool>
+OptEmbedRSInfo("embedRSInfo",
+    llvm::cl::desc("Embed RS Info into the object file instead of generating"
+                   " a separate .o.info file"));
+
+// RenderScript uses -O3 by default
+llvm::cl::opt<char>
+OptOptLevel("O", llvm::cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+                                "(default: -O3)"),
+            llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::init('3'));
+
+// Override "bcc -version" since the LLVM version information is not correct on
+// Android build.
+void BCCVersionPrinter() {
+  llvm::raw_ostream &os = llvm::outs();
+  os << "libbcc (The Android Open Source Project, http://www.android.com/):\n"
+     << "  Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n\n"
+     << "LLVM (http://llvm.org/):\n"
+     << "  Version: " << PACKAGE_VERSION << "\n";
+  return;
+}
+
+void extractSourcesAndSlots(const llvm::cl::list<std::string>& optList,
+                            std::list<std::string>* batchNames,
+                            std::list<std::list<std::pair<int, int>>>* sourcesAndSlots) {
+  for (unsigned i = 0; i < optList.size(); ++i) {
+    std::string plan = optList[i];
+    unsigned found = plan.find(':');
+
+    std::string name = plan.substr(0, found);
+    std::cerr << "new kernel name: " << name << std::endl;
+    batchNames->push_back(name);
+
+    std::istringstream iss(plan.substr(found + 1));
+    std::string s;
+    std::list<std::pair<int, int>> planList;
+    while (getline(iss, s, '.')) {
+      found = s.find(',');
+      std::string sourceStr = s.substr(0, found);
+      std::string slotStr = s.substr(found + 1);
+
+      std::cerr << "source " << sourceStr << ", slot " << slotStr << std::endl;
+
+      int source = std::stoi(sourceStr);
+      int slot = std::stoi(slotStr);
+      planList.push_back(std::make_pair(source, slot));
+    }
+
+    sourcesAndSlots->push_back(planList);
+  }
+}
+
+bool compileScriptGroup(BCCContext& Context, RSCompilerDriver& RSCD) {
+  std::vector<bcc::Source*> sources;
+  for (unsigned i = 0; i < OptInputFilenames.size(); ++i) {
+    bcc::Source* source =
+        bcc::Source::CreateFromFile(Context, OptInputFilenames[i]);
+    if (!source) {
+      llvm::errs() << "Error loading file '" << OptInputFilenames[i]<< "'\n";
+      return false;
+    }
+    sources.push_back(source);
+  }
+
+  std::list<std::string> fusedKernelNames;
+  std::list<std::list<std::pair<int, int>>> sourcesAndSlots;
+  extractSourcesAndSlots(OptMergePlans, &fusedKernelNames, &sourcesAndSlots);
+
+  std::list<std::string> invokeBatchNames;
+  std::list<std::list<std::pair<int, int>>> invokeSourcesAndSlots;
+  extractSourcesAndSlots(OptInvokes, &invokeBatchNames, &invokeSourcesAndSlots);
+
+  std::string outputFilepath(OptOutputPath);
+  outputFilepath.append("/");
+  outputFilepath.append(OptOutputFilename);
+
+  bool success = RSCD.buildScriptGroup(
+    Context, outputFilepath.c_str(), OptBCLibFilename.c_str(),
+    OptBCLibRelaxedFilename.c_str(), OptEmitLLVM, OptChecksum.c_str(),
+    sources, sourcesAndSlots, fusedKernelNames,
+    invokeSourcesAndSlots, invokeBatchNames);
+
+  return success;
+}
+
+} // end anonymous namespace
+
+static inline
+bool ConfigCompiler(RSCompilerDriver &pRSCD) {
+  Compiler *RSC = pRSCD.getCompiler();
+  CompilerConfig *config = nullptr;
+
+  config = new (std::nothrow) CompilerConfig(OptTargetTriple);
+  if (config == nullptr) {
+    llvm::errs() << "Out of memory when create the compiler configuration!\n";
+    return false;
+  }
+
+  if (OptPIC) {
+    config->setRelocationModel(llvm::Reloc::PIC_);
+
+    // For x86_64, CodeModel needs to be small if PIC_ reloc is used.
+    // Otherwise, we end up with TEXTRELs in the shared library.
+    if (config->getTriple().find("x86_64") != std::string::npos) {
+        config->setCodeModel(llvm::CodeModel::Small);
+    }
+  }
+  switch (OptOptLevel) {
+    case '0': config->setOptimizationLevel(llvm::CodeGenOpt::None); break;
+    case '1': config->setOptimizationLevel(llvm::CodeGenOpt::Less); break;
+    case '2': config->setOptimizationLevel(llvm::CodeGenOpt::Default); break;
+    case '3':
+    default: {
+      config->setOptimizationLevel(llvm::CodeGenOpt::Aggressive);
+      break;
+    }
+  }
+
+  pRSCD.setConfig(config);
+  Compiler::ErrorCode result = RSC->config(*config);
+
+  if (OptRSDebugContext) {
+    pRSCD.setDebugContext(true);
+  }
+
+  if (OptRSGlobalInfo) {
+    pRSCD.setEmbedGlobalInfo(true);
+  }
+
+  if (OptRSGlobalInfoSkipConstant) {
+    pRSCD.setEmbedGlobalInfoSkipConstant(true);
+  }
+
+  if (result != Compiler::kSuccess) {
+    llvm::errs() << "Failed to configure the compiler! (detail: "
+                 << Compiler::GetErrorString(result) << ")\n";
+    return false;
+  }
+
+  return true;
+}
+
+int main(int argc, char **argv) {
+
+  llvm::llvm_shutdown_obj Y;
+  init::Initialize();
+  llvm::cl::SetVersionPrinter(BCCVersionPrinter);
+  llvm::cl::ParseCommandLineOptions(argc, argv);
+
+  BCCContext context;
+  RSCompilerDriver RSCD;
+
+  if (OptBCLibFilename.empty()) {
+    ALOGE("Failed to compile bitcode, -bclib was not specified");
+    return EXIT_FAILURE;
+  }
+
+  if (!ConfigCompiler(RSCD)) {
+    ALOGE("Failed to configure compiler");
+    return EXIT_FAILURE;
+  }
+
+  // Attempt to dynamically initialize the compiler driver if such a function
+  // is present. It is only present if passed via "-load libFOO.so".
+  RSCompilerDriverInit_t rscdi = (RSCompilerDriverInit_t)
+      dlsym(RTLD_DEFAULT, STR(RS_COMPILER_DRIVER_INIT_FN));
+  if (rscdi != nullptr) {
+    rscdi(&RSCD);
+  }
+
+  if (OptMergePlans.size() > 0) {
+    bool success = compileScriptGroup(context, RSCD);
+
+    if (!success) {
+      return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+  }
+
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb_or_error =
+      llvm::MemoryBuffer::getFile(OptInputFilenames[0].c_str());
+  if (mb_or_error.getError()) {
+    ALOGE("Failed to load bitcode from path %s! (%s)",
+          OptInputFilenames[0].c_str(), mb_or_error.getError().message().c_str());
+    return EXIT_FAILURE;
+  }
+  std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get());
+
+  const char *bitcode = input_data->getBufferStart();
+  size_t bitcodeSize = input_data->getBufferSize();
+
+  if (!OptEmbedRSInfo) {
+    bool built = RSCD.build(context, OptOutputPath.c_str(),
+                            OptOutputFilename.c_str(),
+                            bitcode, bitcodeSize,
+                            OptChecksum.c_str(), OptBCLibFilename.c_str(),
+                            nullptr, OptEmitLLVM);
+
+    if (!built) {
+      return EXIT_FAILURE;
+    }
+  } else {
+    // embedRSInfo is set.  Use buildForCompatLib to embed RS symbol information
+    // into the .rs.info symbol.
+    Source *source = Source::CreateFromBuffer(context, OptInputFilenames[0].c_str(),
+                                              bitcode, bitcodeSize);
+
+    // If the bitcode fails verification in the bitcode loader, the returned Source is set to NULL.
+    if (!source) {
+      ALOGE("Failed to load source from file %s", OptInputFilenames[0].c_str());
+      return EXIT_FAILURE;
+    }
+
+    std::unique_ptr<RSScript> s(new (std::nothrow) RSScript(*source, RSCD.getConfig()));
+    if (s == nullptr) {
+      llvm::errs() << "Out of memory when creating script for file `"
+                   << OptInputFilenames[0] << "'!\n";
+      delete source;
+      return EXIT_FAILURE;
+    }
+
+    llvm::SmallString<80> output(OptOutputPath);
+    llvm::sys::path::append(output, "/", OptOutputFilename);
+    llvm::sys::path::replace_extension(output, ".o");
+
+    if (!RSCD.buildForCompatLib(*s, output.c_str(), OptChecksum.c_str(),
+                                OptBCLibFilename.c_str(), OptEmitLLVM)) {
+      fprintf(stderr, "Failed to compile script!");
+      return EXIT_FAILURE;
+    }
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/libbcc/tools/bcc_compat/Android.mk b/libbcc/tools/bcc_compat/Android.mk
new file mode 100644
index 0000000..49f5f36
--- /dev/null
+++ b/libbcc/tools/bcc_compat/Android.mk
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# Don't build for unbundled branches
+ifeq (,$(TARGET_BUILD_APPS))
+
+# Executable for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bcc_compat
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_HOST_OS := darwin linux windows
+
+LOCAL_SHARED_LIBRARIES := \
+  libbcc \
+  libbcinfo \
+  libLLVM
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/../../include
+
+LOCAL_LDLIBS_darwin = -ldl
+LOCAL_LDLIBS_linux = -ldl
+
+LOCAL_SRC_FILES := Main.cpp
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(BUILD_HOST_EXECUTABLE)
+
+endif  # Don't build for PDK or unbundled branches
diff --git a/libbcc/tools/bcc_compat/Main.cpp b/libbcc/tools/bcc_compat/Main.cpp
new file mode 100644
index 0000000..79b0f70
--- /dev/null
+++ b/libbcc/tools/bcc_compat/Main.cpp
@@ -0,0 +1,284 @@
+/*
+ * 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 <string>
+#include <vector>
+
+#include <stdlib.h>
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/ADT/SmallString.h>
+#include <llvm/Config/config.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/Path.h>
+#include <llvm/Support/raw_ostream.h>
+
+#include <bcc/BCCContext.h>
+#include <bcc/Compiler.h>
+#include <bcc/Config/Config.h>
+#include <bcc/Renderscript/RSCompilerDriver.h>
+#include <bcc/Script.h>
+#include <bcc/Source.h>
+#include <bcc/Support/CompilerConfig.h>
+#include <bcc/Support/Initialization.h>
+#include <bcc/Support/InputFile.h>
+#include <bcc/Support/OutputFile.h>
+
+using namespace bcc;
+
+//===----------------------------------------------------------------------===//
+// General Options
+//===----------------------------------------------------------------------===//
+namespace {
+
+llvm::cl::list<std::string>
+OptInputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
+                  llvm::cl::desc("<input bitcode files>"));
+
+llvm::cl::opt<std::string>
+OptOutputFilename("o", llvm::cl::desc("Specify the output filename"),
+                  llvm::cl::value_desc("filename"));
+
+llvm::cl::opt<std::string>
+OptRuntimePath("rt-path", llvm::cl::desc("Specify the runtime library path"),
+               llvm::cl::value_desc("path"));
+
+llvm::cl::opt<std::string>
+OptTargetTriple("mtriple",
+                llvm::cl::desc("Specify the target triple (default: "
+                               DEFAULT_TARGET_TRIPLE_STRING ")"),
+                llvm::cl::init(DEFAULT_TARGET_TRIPLE_STRING),
+                llvm::cl::value_desc("triple"));
+
+llvm::cl::alias OptTargetTripleC("C", llvm::cl::NotHidden,
+                                 llvm::cl::desc("Alias for -mtriple"),
+                                 llvm::cl::aliasopt(OptTargetTriple));
+
+//===----------------------------------------------------------------------===//
+// Compiler Options
+//===----------------------------------------------------------------------===//
+llvm::cl::opt<bool>
+OptPIC("fPIC", llvm::cl::desc("Generate fully relocatable, position independent"
+                              " code"));
+
+llvm::cl::opt<char>
+OptOptLevel("O", llvm::cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+                                "(default: -O2)"),
+            llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::init('2'));
+
+llvm::cl::opt<bool>
+OptC("c", llvm::cl::desc("Compile and assemble, but do not link."));
+
+//===----------------------------------------------------------------------===//
+// Linker Options
+//===----------------------------------------------------------------------===//
+// FIXME: this option will be removed in the future when MCLinker is capable
+//        of generating shared library directly from given bitcode. It only
+//        takes effect when -shared is supplied.
+llvm::cl::opt<std::string>
+OptImmObjectOutput("or", llvm::cl::desc("Specify the filename for output the "
+                                        "intermediate relocatable when linking "
+                                        "the input bitcode to the shared "
+                                        "library"), llvm::cl::ValueRequired);
+
+llvm::cl::opt<bool>
+OptShared("shared", llvm::cl::desc("Create a shared library from input bitcode "
+                                   "files"));
+
+
+// Override "bcc -version" since the LLVM version information is not correct on
+// Android build.
+void BCCVersionPrinter() {
+  llvm::raw_ostream &os = llvm::outs();
+  os << "libbcc (The Android Open Source Project, http://www.android.com/):\n"
+     << "  Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n\n"
+     << "LLVM (http://llvm.org/):\n"
+     << "  Version: " << PACKAGE_VERSION << "\n";
+  return;
+}
+
+} // end anonymous namespace
+
+RSScript *PrepareRSScript(BCCContext &pContext,
+                          const llvm::cl::list<std::string> &pBitcodeFiles) {
+  RSScript *result = nullptr;
+
+  for (unsigned i = 0; i < pBitcodeFiles.size(); i++) {
+    const std::string &input_bitcode = pBitcodeFiles[i];
+    Source *source = Source::CreateFromFile(pContext, input_bitcode);
+    if (source == nullptr) {
+      llvm::errs() << "Failed to load llvm module from file `" << input_bitcode
+                   << "'!\n";
+      return nullptr;
+    }
+
+    if (result != nullptr) {
+      if (!result->mergeSource(*source)) {
+        llvm::errs() << "Failed to merge the llvm module `" << input_bitcode
+                     << "' to compile!\n";
+        delete source;
+        return nullptr;
+      }
+    } else {
+      result = new (std::nothrow) RSScript(*source);
+      if (result == nullptr) {
+        llvm::errs() << "Out of memory when create script for file `"
+                     << input_bitcode << "'!\n";
+        delete source;
+        return nullptr;
+      }
+    }
+  }
+
+  return result;
+}
+
+static inline
+bool ConfigCompiler(RSCompilerDriver &pCompilerDriver) {
+  Compiler *compiler = pCompilerDriver.getCompiler();
+  CompilerConfig *config = nullptr;
+
+  config = new (std::nothrow) CompilerConfig(OptTargetTriple);
+  if (config == nullptr) {
+    llvm::errs() << "Out of memory when create the compiler configuration!\n";
+    return false;
+  }
+
+  // Explicitly set ARM feature vector
+  if (config->getTriple().find("arm") != std::string::npos) {
+    std::vector<std::string> fv;
+    fv.push_back("+vfp3");
+    fv.push_back("+d16");
+    fv.push_back("-neon");
+    fv.push_back("-neonfp");
+    config->setFeatureString(fv);
+  }
+
+  // Explicitly set X86 feature vector
+  if ((config->getTriple().find("i686") != std::string::npos) ||
+    (config->getTriple().find("x86_64") != std::string::npos)) {
+    std::vector<std::string> fv;
+    fv.push_back("+sse3");
+    config->setFeatureString(fv);
+  }
+
+  // Compatibility mode on x86 requires atom code generation.
+  if (config->getTriple().find("i686") != std::string::npos) {
+    config->setCPU("atom");
+  }
+
+  // Setup the config according to the value of command line option.
+  if (OptPIC) {
+    config->setRelocationModel(llvm::Reloc::PIC_);
+    // For x86_64, CodeModel needs to be small if PIC_ reloc is used.
+    // Otherwise, we end up with TEXTRELs in the shared library.
+    if (config->getTriple().find("x86_64") != std::string::npos) {
+        config->setCodeModel(llvm::CodeModel::Small);
+    }
+  }
+  switch (OptOptLevel) {
+    case '0': config->setOptimizationLevel(llvm::CodeGenOpt::None); break;
+    case '1': config->setOptimizationLevel(llvm::CodeGenOpt::Less); break;
+    case '3': config->setOptimizationLevel(llvm::CodeGenOpt::Aggressive); break;
+    case '2':
+    default: {
+      config->setOptimizationLevel(llvm::CodeGenOpt::Default);
+      break;
+    }
+  }
+
+  pCompilerDriver.setConfig(config);
+  Compiler::ErrorCode result = compiler->config(*config);
+
+  if (result != Compiler::kSuccess) {
+    llvm::errs() << "Failed to configure the compiler! (detail: "
+                 << Compiler::GetErrorString(result) << ")\n";
+    return false;
+  }
+
+  return true;
+}
+
+#define DEFAULT_OUTPUT_PATH   "/sdcard/a.out"
+static inline
+std::string DetermineOutputFilename(const std::string &pOutputPath) {
+  if (!pOutputPath.empty()) {
+    return pOutputPath;
+  }
+
+  // User doesn't specify the value to -o.
+  if (OptInputFilenames.size() > 1) {
+    llvm::errs() << "Use " DEFAULT_OUTPUT_PATH " for output file!\n";
+    return DEFAULT_OUTPUT_PATH;
+  }
+
+  // There's only one input bitcode file.
+  const std::string &input_path = OptInputFilenames[0];
+  llvm::SmallString<200> output_path(input_path);
+
+  std::error_code err = llvm::sys::fs::make_absolute(output_path);
+  if (err) {
+    llvm::errs() << "Failed to determine the absolute path of `" << input_path
+                 << "'! (detail: " << err.message() << ")\n";
+    return "";
+  }
+
+  if (OptC) {
+    // -c was specified. Replace the extension to .o.
+    llvm::sys::path::replace_extension(output_path, "o");
+  } else {
+    // Use a.out under current working directory when compile executable or
+    // shared library.
+    llvm::sys::path::remove_filename(output_path);
+    llvm::sys::path::append(output_path, "a.out");
+  }
+
+  return output_path.c_str();
+}
+
+int main(int argc, char **argv) {
+  llvm::cl::SetVersionPrinter(BCCVersionPrinter);
+  llvm::cl::ParseCommandLineOptions(argc, argv);
+  init::Initialize();
+
+  if (OptRuntimePath.empty()) {
+    fprintf(stderr, "You must set \"-rt-path </path/to/libclcore.bc>\" with "
+                    "this tool\n");
+    return EXIT_FAILURE;
+  }
+
+  BCCContext context;
+  RSCompilerDriver rscd;
+  Compiler compiler;
+
+  if (!ConfigCompiler(rscd)) {
+    return EXIT_FAILURE;
+  }
+
+  std::string OutputFilename = DetermineOutputFilename(OptOutputFilename);
+  if (OutputFilename.empty()) {
+    return EXIT_FAILURE;
+  }
+
+  std::unique_ptr<RSScript> s(PrepareRSScript(context, OptInputFilenames));
+  if (!rscd.buildForCompatLib(*s, OutputFilename.c_str(), nullptr, OptRuntimePath.c_str(), false)) {
+    fprintf(stderr, "Failed to compile script!");
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/libbcc/tools/bcc_strip_attr/Android.mk b/libbcc/tools/bcc_strip_attr/Android.mk
new file mode 100644
index 0000000..1158f4e
--- /dev/null
+++ b/libbcc/tools/bcc_strip_attr/Android.mk
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2013 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# Executable for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bcc_strip_attr
+LOCAL_MODULE_CLASS := EXECUTABLES
+
+LOCAL_SHARED_LIBRARIES := libLLVM
+
+LOCAL_C_INCLUDES := \
+  $(LOCAL_PATH)/../../include
+
+LOCAL_LDLIBS += -lm
+LOCAL_LDLIBS_darwin += -lpthread -ldl
+LOCAL_LDLIBS_linux += -lpthread -ldl
+LOCAL_SRC_FILES := bcc_strip_attr.cpp
+
+include $(LIBBCC_HOST_BUILD_MK)
+include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_GEN_ATTRIBUTES_MK)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/libbcc/tools/bcc_strip_attr/bcc_strip_attr.cpp b/libbcc/tools/bcc_strip_attr/bcc_strip_attr.cpp
new file mode 100644
index 0000000..885ddc9
--- /dev/null
+++ b/libbcc/tools/bcc_strip_attr/bcc_strip_attr.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2013, 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 "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/ToolOutputFile.h"
+using namespace llvm;
+
+static cl::list<std::string>
+InputFilenames(cl::Positional,
+               cl::desc("<input bitcode files>"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
+               cl::value_desc("filename"));
+
+static cl::opt<bool>
+OutputAssembly("S",
+               cl::desc("Write output as LLVM assembly"), cl::Hidden);
+
+namespace {
+  class StripAttributes : public ModulePass {
+  public:
+    static char ID;
+
+    StripAttributes() : ModulePass(ID) {
+    }
+
+    virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+      AU.setPreservesAll();
+    }
+
+    bool runOnFunction(Function &F) {
+      // Remove any target-cpu and/or target-features attributes from each
+      // Function or Function declaration.
+      if (F.hasFnAttribute("target-cpu") ||
+          F.hasFnAttribute("target-features")) {
+
+        AttrBuilder B;
+        B.addAttribute("target-cpu").addAttribute("target-features");
+        AttributeSet ToStrip = AttributeSet::get(F.getContext(),
+            AttributeSet::FunctionIndex, B);
+        F.removeAttributes(AttributeSet::FunctionIndex, ToStrip);
+        return true;
+      }
+      return false;
+    }
+
+    // We have to use a ModulePass, since a FunctionPass only gets run on
+    // defined Functions (and not declared Functions).
+    virtual bool runOnModule(Module &M) {
+      bool Changed = false;
+      for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+        Changed |= runOnFunction(*I);
+      }
+      return Changed;
+    }
+  };
+
+  llvm::ModulePass * createStripAttributePass() {
+    return new StripAttributes();
+  }
+}
+
+
+char StripAttributes::ID = 0;
+static RegisterPass<StripAttributes> RPSA("StripAttributes",
+    "Strip Function Attributes Pass");
+
+
+static inline std::unique_ptr<Module> LoadFile(const char *argv0,
+                                               const std::string &FN,
+                                               LLVMContext& Context) {
+  SMDiagnostic Err;
+  std::unique_ptr<Module> Result = parseIRFile(FN, Err, Context);
+  if (Result) {
+    return Result;   // Load successful!
+  }
+
+  Err.print(argv0, errs());
+  return std::unique_ptr<Module>();
+}
+
+
+int main(int argc, char **argv) {
+  // Print a stack trace if we signal out.
+  sys::PrintStackTraceOnErrorSignal();
+  PrettyStackTraceProgram X(argc, argv);
+
+  LLVMContext &Context = getGlobalContext();
+  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
+  cl::ParseCommandLineOptions(argc, argv, "strip function attribute pass\n");
+
+  std::string ErrorMessage;
+
+  std::unique_ptr<Module> M(LoadFile(argv[0], InputFilenames[0], Context));
+  if (M.get() == 0) {
+    errs() << argv[0] << ": error loading file '"
+           << InputFilenames[0] << "'\n";
+    return 1;
+  }
+
+  // Perform the actual function attribute stripping.
+  legacy::PassManager PM;
+  PM.add(createStripAttributePass());
+  PM.run(*M.get());
+
+  std::error_code EC;
+  tool_output_file Out(OutputFilename.c_str(), EC,
+                       sys::fs::F_None);
+  if (EC) {
+    errs() << EC.message() << '\n';
+    return 1;
+  }
+
+  if (verifyModule(*M)) {
+    errs() << argv[0] << ": stripped module is broken!\n";
+    return 1;
+  }
+
+  if (OutputAssembly) {
+    Out.os() << *M;
+  } else if (!CheckBitcodeOutputToConsole(Out.os(), true)) {
+    WriteBitcodeToFile(M.get(), Out.os());
+  }
+
+  Out.keep();
+
+  return 0;
+}