Merge "Changing rsg to rs because functions don't rely on graphics. Renaming one of the includes for clarity."
diff --git a/Android.mk b/Android.mk
index e3948c8..213cc45 100644
--- a/Android.mk
+++ b/Android.mk
@@ -22,10 +22,6 @@
# Whole Static Library to Be Linked In
#=====================================================================
-ifeq ($(libbcc_USE_OLD_JIT),1)
-libbcc_WHOLE_STATIC_LIBRARIES += libbccCodeGen
-endif
-
ifeq ($(libbcc_USE_DISASSEMBLER),1)
libbcc_WHOLE_STATIC_LIBRARIES += libbccDisassembler
endif
@@ -80,9 +76,7 @@
LOCAL_WHOLE_STATIC_LIBRARIES += libbccCompilerRT
endif
-ifeq ($(libbcc_USE_MCJIT),1)
- LOCAL_STATIC_LIBRARIES += librsloader
-endif
+LOCAL_STATIC_LIBRARIES += librsloader
ifeq ($(libbcc_USE_DISASSEMBLER),1)
ifeq ($(TARGET_ARCH),arm)
@@ -192,9 +186,7 @@
LOCAL_WHOLE_STATIC_LIBRARIES += $(libbcc_WHOLE_STATIC_LIBRARIES)
-ifeq ($(libbcc_USE_MCJIT),1)
- LOCAL_STATIC_LIBRARIES += librsloader
-endif
+LOCAL_STATIC_LIBRARIES += librsloader
ifeq ($(libbcc_USE_DISASSEMBLER),1)
LOCAL_STATIC_LIBRARIES += \
diff --git a/Config.h b/Config.h
index ebe0044..b1ea833 100644
--- a/Config.h
+++ b/Config.h
@@ -4,62 +4,22 @@
#include "ConfigFromMk.h"
//---------------------------------------------------------------------------
-// Configuration for JIT & MC Assembler
-//---------------------------------------------------------------------------
-#if !USE_OLD_JIT && !USE_MCJIT
-#error "You should choose at least one code generation method."
-#endif
-
-//---------------------------------------------------------------------------
// Configuration for Disassembler
//---------------------------------------------------------------------------
-#if !USE_OLD_JIT
-#undef DEBUG_OLD_JIT_DISASSEMBLER
-#define DEBUG_OLD_JIT_DISASSEMBLER 0
-#endif
-
-#if !USE_MCJIT
-#undef DEBUG_MCJIT_DISASSEMBLER
-#define DEBUG_MCJIT_DISASSEMBLER 0
-#endif
-
-#if DEBUG_OLD_JIT_DISASSEMBLER || DEBUG_MCJIT_DISASSEMBLER
+#if DEBUG_MC_DISASSEMBLER
#define USE_DISASSEMBLER 1
#else
#define USE_DISASSEMBLER 0
#endif
#if defined(__HOST__)
-#define DEBUG_OLD_JIT_DISASSEMBLER_FILE "/tmp/oldjit-dis.s"
-#define DEBUG_MCJIT_DISASSEMBLER_FILE "/tmp/mcjit-dis.s"
+#define DEBUG_MC_DISASSEMBLER_FILE "/tmp/mc-dis.s"
#else
-#define DEBUG_OLD_JIT_DISASSEMBLER_FILE "/data/local/tmp/oldjit-dis.s"
-#define DEBUG_MCJIT_DISASSEMBLER_FILE "/data/local/tmp/mcjit-dis.s"
+#define DEBUG_MC_DISASSEMBLER_FILE "/data/local/tmp/mc-dis.s"
#endif // defined(__HOST__)
//---------------------------------------------------------------------------
-// Configuration for ContextManager
-//---------------------------------------------------------------------------
-
-#if USE_OLD_JIT
-
-// Note: Most of the code should NOT use these constants. Use the public
-// static member of ContextManager instead, which is type-safe. For example,
-// if you need BCC_CONTEXT_FIXED_ADDR_, then you should write:
-// ContextManager::ContextFixedAddr
-
-#define BCC_CONTEXT_FIXED_ADDR_ reinterpret_cast<char *>(0x7e000000)
-
-#define BCC_CONTEXT_SLOT_COUNT_ 8
-
-#define BCC_CONTEXT_CODE_SIZE_ (128 * 1024)
-
-#define BCC_CONTEXT_DATA_SIZE_ (128 * 1024)
-
-#endif // USE_OLD_JIT
-
-//---------------------------------------------------------------------------
// Configuration for CodeGen and CompilerRT
//---------------------------------------------------------------------------
diff --git a/README.html b/README.html
index 0b8b447..447312a 100644
--- a/README.html
+++ b/README.html
@@ -419,24 +419,24 @@
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> (OBCC_Header) - The header of a cache file. It contains the
+<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> (OBCC_StringPool) - A collection of serialized variable
+<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> (OBCC_DependencyTable) - The dependencies table.
+<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> (OBCC_RelocationTable) - <em>not enabled</em></li>
-<li><strong>Exported Variable List</strong> (OBCC_ExportVarList) -
+<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> (OBCC_ExportFuncList) -
+<li><strong>Exported Function List</strong> (MCO_ExportFuncList) -
The list of the addresses of exported functions.</li>
-<li><strong>Pragma List</strong> (OBCC_PragmaList) - The list of pragma key-value pair.</li>
-<li><strong>Function Information Table</strong> (OBCC_FuncTable) - This is a table of
+<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>
diff --git a/README.rst b/README.rst
index cf40138..97070c0 100644
--- a/README.rst
+++ b/README.rst
@@ -138,31 +138,31 @@
table, and bcc context. Every section should be aligned to a word size.
Here is the brief description of each sections:
-* **Header** (OBCC_Header) - The header of a cache file. It contains the
+* **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** (OBCC_StringPool) - A collection of serialized variable
+* **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** (OBCC_DependencyTable) - The dependencies table.
+* **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** (OBCC_RelocationTable) - *not enabled*
+* **Relocation Table** (MCO_RelocationTable) - *not enabled*
-* **Exported Variable List** (OBCC_ExportVarList) -
+* **Exported Variable List** (MCO_ExportVarList) -
The list of the addresses of exported variables.
-* **Exported Function List** (OBCC_ExportFuncList) -
+* **Exported Function List** (MCO_ExportFuncList) -
The list of the addresses of exported functions.
-* **Pragma List** (OBCC_PragmaList) - The list of pragma key-value pair.
+* **Pragma List** (MCO_PragmaList) - The list of pragma key-value pair.
-* **Function Information Table** (OBCC_FuncTable) - This is a table of
+* **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.
diff --git a/bcinfo/Android.mk b/bcinfo/Android.mk
index f813e77..5a53e07 100644
--- a/bcinfo/Android.mk
+++ b/bcinfo/Android.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright (C) 2011-2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -38,6 +38,7 @@
libbcinfo_C_INCLUDES := $(LOCAL_PATH)/../include
libbcinfo_STATIC_LIBRARIES := \
+ libLLVMWrap \
libLLVMBitReader \
libLLVMBitWriter \
libLLVMCore \
diff --git a/bcinfo/BitcodeTranslator.cpp b/bcinfo/BitcodeTranslator.cpp
index 3dcddfc..bd4cd4b 100644
--- a/bcinfo/BitcodeTranslator.cpp
+++ b/bcinfo/BitcodeTranslator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, The Android Open Source Project
+ * 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.
@@ -16,6 +16,8 @@
#include "bcinfo/BitcodeTranslator.h"
+#include "bcinfo/BitcodeWrapper.h"
+
#include "BitReader_2_7/BitReader_2_7.h"
#include "BitReader_3_0/BitReader_3_0.h"
@@ -88,6 +90,12 @@
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 != kCurrentAPIVersion) &&
((mVersion < kMinimumAPIVersion) ||
(mVersion > kMaximumAPIVersion))) {
@@ -136,11 +144,21 @@
llvm::WriteBitcodeToFile(module, OS);
OS.flush();
- char *c = new char[Buffer.size()];
- memcpy(c, Buffer.c_str(), Buffer.size());
+ AndroidBitcodeWrapper wrapper;
+ size_t actualWrapperLen = writeAndroidBitcodeWrapper(
+ &wrapper, Buffer.size(), BCWrapper.getTargetAPI(),
+ 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;
- mTranslatedBitcodeSize = Buffer.size();
return true;
}
diff --git a/bcinfo/BitcodeWrapper.cpp b/bcinfo/BitcodeWrapper.cpp
index c6f9c04..67f95b8 100644
--- a/bcinfo/BitcodeWrapper.cpp
+++ b/bcinfo/BitcodeWrapper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, The Android Open Source Project
+ * 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.
@@ -15,6 +15,8 @@
*/
#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>
@@ -28,8 +30,19 @@
BitcodeWrapper::BitcodeWrapper(const char *bitcode, size_t bitcodeSize)
: mFileType(BC_NOT_BC), mBitcode(bitcode),
- mBitcodeEnd(bitcode + bitcodeSize - 1), mBitcodeSize(bitcodeSize) {
- memset(&mBCHeader, 0, sizeof(mBCHeader));
+ mBitcodeEnd(bitcode + bitcodeSize - 1), mBitcodeSize(bitcodeSize),
+ mHeaderVersion(0), mTargetAPI(0) {
+ InMemoryWrapperInput inMem(mBitcode, mBitcodeSize);
+ BitcodeWrapperer wrapperer(&inMem, NULL);
+ 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;
+ }
}
@@ -39,30 +52,7 @@
bool BitcodeWrapper::unwrap() {
- if (!mBitcode || !mBitcodeSize) {
- ALOGE("Invalid/empty bitcode");
- return false;
- }
-
- if (llvm::isBitcodeWrapper((const unsigned char*) mBitcode,
- (const unsigned char*) mBitcodeEnd)) {
- if (mBitcodeSize < sizeof(mBCHeader)) {
- ALOGE("Invalid bitcode size");
- return false;
- }
-
- mFileType = BC_WRAPPER;
- memcpy(&mBCHeader, mBitcode, sizeof(mBCHeader));
- return true;
- } else if (llvm::isRawBitcode((const unsigned char*) mBitcode,
- (const unsigned char*) mBitcodeEnd)) {
- mFileType = BC_RAW;
- return true;
- } else {
- ALOGE("Not bitcode");
- mFileType = BC_NOT_BC;
- return false;
- }
+ return mFileType != BC_NOT_BC;
}
} // namespace bcinfo
diff --git a/bcinfo/Wrap/Android.mk b/bcinfo/Wrap/Android.mk
new file mode 100644
index 0000000..adc306a
--- /dev/null
+++ b/bcinfo/Wrap/Android.mk
@@ -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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+LLVM_ROOT_PATH := $(LOCAL_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_TAGS := optional
+
+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
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libLLVMWrap
+LOCAL_MODULE_TAGS := optional
+
+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)
diff --git a/bcinfo/Wrap/LLVMBuild.txt b/bcinfo/Wrap/LLVMBuild.txt
new file mode 100644
index 0000000..8750711
--- /dev/null
+++ b/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/bcinfo/Wrap/Makefile b/bcinfo/Wrap/Makefile
new file mode 100644
index 0000000..79aa2b3
--- /dev/null
+++ b/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/bcinfo/Wrap/bitcode_wrapperer.cpp b/bcinfo/Wrap/bitcode_wrapperer.cpp
new file mode 100644
index 0000000..c8b7d26
--- /dev/null
+++ b/bcinfo/Wrap/bitcode_wrapperer.cpp
@@ -0,0 +1,380 @@
+/*
+ * 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_->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;
+ }
+
+ // 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/bcinfo/Wrap/file_wrapper_input.cpp b/bcinfo/Wrap/file_wrapper_input.cpp
new file mode 100644
index 0000000..08212c2
--- /dev/null
+++ b/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 (NULL == _file) {
+ 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 (0 == stat(_name, &st)) {
+ _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 0 == fseek(_file, (long) pos, SEEK_SET);
+}
diff --git a/bcinfo/Wrap/file_wrapper_output.cpp b/bcinfo/Wrap/file_wrapper_output.cpp
new file mode 100644
index 0000000..4cdc54e
--- /dev/null
+++ b/bcinfo/Wrap/file_wrapper_output.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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 (NULL == _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_size > 0) {
+ return buffer_size == fwrite(buffer, 1, buffer_size, _file);
+ } else {
+ return true;
+ }
+}
diff --git a/bcinfo/Wrap/in_memory_wrapper_input.cpp b/bcinfo/Wrap/in_memory_wrapper_input.cpp
new file mode 100644
index 0000000..3f91f01
--- /dev/null
+++ b/bcinfo/Wrap/in_memory_wrapper_input.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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;
+ 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/bcinfo/Wrap/wrapper_output.cpp b/bcinfo/Wrap/wrapper_output.cpp
new file mode 100644
index 0000000..3c72422
--- /dev/null
+++ b/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/bcinfo/tools/main.cpp b/bcinfo/tools/main.cpp
index 6ecded0..bed24aa 100644
--- a/bcinfo/tools/main.cpp
+++ b/bcinfo/tools/main.cpp
@@ -120,8 +120,6 @@
}
printf("\n");
- printf("optimizationLevel: %u\n", ME->getOptimizationLevel());
-
return;
}
@@ -184,11 +182,6 @@
unsigned int version = 0;
bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize);
- if (!bcWrapper.unwrap()) {
- fprintf(stderr, "failed to unwrap bitcode wrapper\n");
- return 2;
- }
-
if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
version = bcWrapper.getTargetAPI();
printf("Found bitcodeWrapper\n");
@@ -196,7 +189,9 @@
version = 12;
}
- printf("bitcodeVersion: %u\n", version);
+ printf("targetAPI: %u\n", version);
+ printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion());
+ printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel());
bcinfo::BitcodeTranslator *BT =
new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version);
diff --git a/include/bcc/bcc_cache.h b/include/bcc/bcc_cache.h
deleted file mode 100644
index 6809cce..0000000
--- a/include/bcc/bcc_cache.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright 2010-2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_CACHE_H
-#define BCC_CACHE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-/* BCC Cache File Magic Word */
-#define OBCC_MAGIC "\0bcc"
-
-/* BCC Cache File Version, encoded in 4 bytes of ASCII */
-#define OBCC_VERSION "001\0"
-
-/* BCC Cache Header Structure */
-struct OBCC_Header {
- /* magic and version */
- uint8_t magic[4];
- uint8_t version[4];
-
- /* machine-dependent integer type size */
- uint8_t endianness;
- uint8_t sizeof_off_t;
- uint8_t sizeof_size_t;
- uint8_t sizeof_ptr_t;
-
- /* string pool section */
- off_t str_pool_offset;
- size_t str_pool_size;
-
- /* dependancy table */
- off_t depend_tab_offset;
- size_t depend_tab_size;
-
- /* relocation table section */
- off_t reloc_tab_offset;
- size_t reloc_tab_size;
-
- /* export variable list section */
- off_t export_var_list_offset;
- size_t export_var_list_size;
-
- /* export function list section */
- off_t export_func_list_offset;
- size_t export_func_list_size;
-
- /* pragma list section */
- off_t pragma_list_offset;
- size_t pragma_list_size;
-
- /* function table */
- off_t func_table_offset;
- size_t func_table_size;
-
- /* function table */
- off_t object_slot_list_offset;
- size_t object_slot_list_size;
-
- /* context section */
- char *context_cached_addr;
- uint32_t context_parity_checksum;
-
- /* dirty hack for libRS */
- /* TODO: This should be removed in the future */
- uint32_t libRS_threadable;
-
- /* export foreach list section */
- off_t export_foreach_list_offset;
- size_t export_foreach_list_size;
-};
-
-struct OBCC_String {
- size_t length; /* String length, without ending '\0' */
- off_t offset; /* Note: Offset related to string_pool_offset. */
-};
-
-struct OBCC_StringPool {
- size_t count;
- struct OBCC_String list[];
-};
-
-enum OBCC_ResourceType {
- BCC_APK_RESOURCE = 0,
- BCC_FILE_RESOURCE = 1,
-};
-
-struct OBCC_Dependency {
- size_t res_name_strp_index;
- uint32_t res_type; /* BCC_APK_RESOURCE or BCC_FILE_RESOURCE */
- unsigned char sha1[20];
-};
-
-struct OBCC_DependencyTable {
- size_t count;
- struct OBCC_Dependency table[];
-};
-
-struct OBCC_RelocationTable {
-/* TODO: Implement relocation table. */
-};
-
-struct OBCC_ExportVarList {
- size_t count;
- void *cached_addr_list[];
-};
-
-struct OBCC_ExportFuncList {
- size_t count;
- void *cached_addr_list[];
-};
-
-struct OBCC_ExportForEachList {
- size_t count;
- void *cached_addr_list[];
-};
-
-struct OBCC_Pragma {
- size_t key_strp_index;
- size_t value_strp_index;
-};
-
-struct OBCC_PragmaList {
- size_t count;
- struct OBCC_Pragma list[];
-};
-
-struct OBCC_ObjectSlotList {
- size_t count;
- uint32_t object_slot_list[];
-};
-
-struct OBCC_FuncInfo {
- size_t name_strp_index;
- void *cached_addr;
- size_t size;
-};
-
-struct OBCC_FuncTable {
- size_t count;
- struct OBCC_FuncInfo table[];
-};
-
-struct OBCC_String_Ptr {
- size_t count;
- size_t strp_indexs[];
-};
-
-
-#endif /* BCC_CACHE_H */
diff --git a/include/bcc/bcc_mccache.h b/include/bcc/bcc_mccache.h
index 292165d..a214831 100644
--- a/include/bcc/bcc_mccache.h
+++ b/include/bcc/bcc_mccache.h
@@ -20,8 +20,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include "bcc_cache.h"
-
/* BCC Cache File Magic Word */
#define MCO_MAGIC "\0bcc"
@@ -81,5 +79,77 @@
size_t export_foreach_name_list_size;
};
+struct MCO_String {
+ size_t length; /* String length, without ending '\0' */
+ off_t offset; /* Note: Offset related to string_pool_offset. */
+};
+
+struct MCO_StringPool {
+ size_t count;
+ struct MCO_String list[];
+};
+
+enum MCO_ResourceType {
+ BCC_APK_RESOURCE = 0,
+ BCC_FILE_RESOURCE = 1,
+};
+
+struct MCO_Dependency {
+ size_t res_name_strp_index;
+ uint32_t res_type; /* BCC_APK_RESOURCE or BCC_FILE_RESOURCE */
+ unsigned char sha1[20];
+};
+
+struct MCO_DependencyTable {
+ size_t count;
+ struct MCO_Dependency table[];
+};
+
+struct MCO_ExportVarList {
+ size_t count;
+ void *cached_addr_list[];
+};
+
+struct MCO_ExportFuncList {
+ size_t count;
+ void *cached_addr_list[];
+};
+
+struct MCO_ExportForEachList {
+ size_t count;
+ void *cached_addr_list[];
+};
+
+struct MCO_Pragma {
+ size_t key_strp_index;
+ size_t value_strp_index;
+};
+
+struct MCO_PragmaList {
+ size_t count;
+ struct MCO_Pragma list[];
+};
+
+struct MCO_ObjectSlotList {
+ size_t count;
+ uint32_t object_slot_list[];
+};
+
+struct MCO_FuncInfo {
+ size_t name_strp_index;
+ void *cached_addr;
+ size_t size;
+};
+
+struct MCO_FuncTable {
+ size_t count;
+ struct MCO_FuncInfo table[];
+};
+
+struct MCO_String_Ptr {
+ size_t count;
+ size_t strp_indexs[];
+};
+
#endif /* BCC_MCCACHE_H */
diff --git a/include/bcinfo/BitcodeWrapper.h b/include/bcinfo/BitcodeWrapper.h
index cde0a91..3e9ed52 100644
--- a/include/bcinfo/BitcodeWrapper.h
+++ b/include/bcinfo/BitcodeWrapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, The Android Open Source Project
+ * 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.
@@ -17,18 +17,27 @@
#ifndef __ANDROID_BCINFO_BITCODEWRAPPER_H__
#define __ANDROID_BCINFO_BITCODEWRAPPER_H__
+#include "bcinfo/Wrap/BCHeaderField.h"
+
#include <cstddef>
#include <stdint.h>
namespace bcinfo {
-struct BCWrapperHeader {
+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 {
@@ -44,7 +53,10 @@
const char *mBitcodeEnd;
size_t mBitcodeSize;
- struct BCWrapperHeader mBCHeader;
+ uint32_t mHeaderVersion;
+ uint32_t mTargetAPI;
+ uint32_t mCompilerVersion;
+ uint32_t mOptimizationLevel;
public:
/**
@@ -58,7 +70,7 @@
~BitcodeWrapper();
/**
- * Attempt to unwrap the target bitcode.
+ * Attempt to unwrap the target bitcode. This function is \deprecated.
*
* \return true on success and false if an error occurred.
*/
@@ -72,20 +84,71 @@
}
/**
- * \return header version of bitcode wrapper. This can only be 0 currently.
+ * \return header version of bitcode wrapper.
*/
uint32_t getHeaderVersion() const {
- return mBCHeader.HeaderVersion;
+ return mHeaderVersion;
}
/**
- * \return target API version of this script.
+ * \return target API version for this bitcode.
*/
uint32_t getTargetAPI() const {
- return mBCHeader.TargetAPI;
+ 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/include/bcinfo/Wrap/BCHeaderField.h b/include/bcinfo/Wrap/BCHeaderField.h
new file mode 100644
index 0000000..8652d78
--- /dev/null
+++ b/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 <limits>
+#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
+ if (buf_len < fields_len + pad_len ||
+ len_ > std::numeric_limits<FixedSubfield>::max()) 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/include/bcinfo/Wrap/bitcode_wrapperer.h b/include/bcinfo/Wrap/bitcode_wrapperer.h
new file mode 100644
index 0000000..2fbce21
--- /dev/null
+++ b/include/bcinfo/Wrap/bitcode_wrapperer.h
@@ -0,0 +1,215 @@
+/*
+ * 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() { return infile_->Size(); }
+
+ // 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/include/bcinfo/Wrap/file_wrapper_input.h b/include/bcinfo/Wrap/file_wrapper_input.h
new file mode 100644
index 0000000..2ff955f
--- /dev/null
+++ b/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:
+ 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/include/bcinfo/Wrap/file_wrapper_output.h b/include/bcinfo/Wrap/file_wrapper_output.h
new file mode 100644
index 0000000..fa01c93
--- /dev/null
+++ b/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:
+ 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/include/bcinfo/Wrap/in_memory_wrapper_input.h b/include/bcinfo/Wrap/in_memory_wrapper_input.h
new file mode 100644
index 0000000..634dd40
--- /dev/null
+++ b/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/include/bcinfo/Wrap/support_macros.h b/include/bcinfo/Wrap/support_macros.h
new file mode 100644
index 0000000..5d3b8ce
--- /dev/null
+++ b/include/bcinfo/Wrap/support_macros.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+#define DISALLOW_CLASS_COPY(class_name) \
+ class_name(class_name& arg) // 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) // 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/include/bcinfo/Wrap/wrapper_input.h b/include/bcinfo/Wrap/wrapper_input.h
new file mode 100644
index 0000000..d3330df
--- /dev/null
+++ b/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/include/bcinfo/Wrap/wrapper_output.h b/include/bcinfo/Wrap/wrapper_output.h
new file mode 100644
index 0000000..6498805
--- /dev/null
+++ b/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/lib/CodeGen/Android.mk b/lib/CodeGen/Android.mk
deleted file mode 100644
index 0eacfa1..0000000
--- a/lib/CodeGen/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# 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)
-include $(LOCAL_PATH)/../../libbcc-config.mk
-
-ifeq ($(libbcc_USE_OLD_JIT),1)
-
-#=====================================================================
-# Common: libbccCodeGen
-#=====================================================================
-
-libbcc_codegen_SRC_FILES := \
- CodeEmitter.cpp \
- CodeMemoryManager.cpp
-
-
-#=====================================================================
-# Device Static Library: libbccCodeGen
-#=====================================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbccCodeGen
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_CFLAGS += $(libbcc_CFLAGS)
-LOCAL_C_INCLUDES += $(libbcc_C_INCLUDES)
-LOCAL_SRC_FILES := $(libbcc_codegen_SRC_FILES)
-
-include $(LIBBCC_ROOT_PATH)/libbcc-gen-config-from-mk.mk
-include $(LIBBCC_ROOT_PATH)/libbcc-build-rules.mk
-include $(LLVM_ROOT_PATH)/llvm-device-build.mk
-include $(BUILD_STATIC_LIBRARY)
-
-
-#=====================================================================
-# Host Static Library: libbccCodeGen
-#=====================================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbccCodeGen
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_IS_HOST_MODULE := true
-
-LOCAL_CFLAGS += $(libbcc_CFLAGS)
-LOCAL_CFLAGS += -D__HOST__
-LOCAL_C_INCLUDES += $(libbcc_C_INCLUDES)
-
-LOCAL_SRC_FILES := $(libbcc_codegen_SRC_FILES)
-
-include $(LIBBCC_ROOT_PATH)/libbcc-gen-config-from-mk.mk
-include $(LIBBCC_ROOT_PATH)/libbcc-build-rules.mk
-include $(LLVM_ROOT_PATH)/llvm-host-build.mk
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-endif # $(libbcc_USE_OLD_JIT)
diff --git a/lib/CodeGen/CodeEmitter.cpp b/lib/CodeGen/CodeEmitter.cpp
deleted file mode 100644
index c3f37e1..0000000
--- a/lib/CodeGen/CodeEmitter.cpp
+++ /dev/null
@@ -1,1442 +0,0 @@
-//===-- CodeEmitter.cpp - CodeEmitter Class -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See external/llvm/LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the CodeEmitter class.
-//
-//===----------------------------------------------------------------------===//
-
-#define LOG_TAG "bcc"
-#include <cutils/log.h>
-
-#include "CodeEmitter.h"
-
-#include "Config.h"
-
-#if DEBUG_OLD_JIT_DISASSEMBLER
-#include "Disassembler/Disassembler.h"
-#endif
-
-#include "CodeMemoryManager.h"
-#include "ExecutionEngine/Runtime.h"
-#include "ExecutionEngine/ScriptCompiled.h"
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_cache.h>
-#include "ExecutionEngine/bcc_internal.h"
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-
-#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineRelocation.h"
-#include "llvm/CodeGen/MachineJumpTableInfo.h"
-#include "llvm/CodeGen/JITCodeEmitter.h"
-
-#include "llvm/ExecutionEngine/GenericValue.h"
-
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include "llvm/Support/Host.h"
-
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Target/TargetJITInfo.h"
-
-#include "llvm/Constant.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/GlobalAlias.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/Instruction.h"
-#include "llvm/Type.h"
-
-#include <algorithm>
-#include <vector>
-#include <set>
-#include <string>
-
-#include <stddef.h>
-
-
-namespace bcc {
-
-// Will take the ownership of @MemMgr
-CodeEmitter::CodeEmitter(ScriptCompiled *result, CodeMemoryManager *pMemMgr)
- : mpResult(result),
- mpMemMgr(pMemMgr),
- mpTarget(NULL),
- mpTJI(NULL),
- mpTD(NULL),
- mpCurEmitFunction(NULL),
- mpConstantPool(NULL),
- mpJumpTable(NULL),
- mpMMI(NULL),
- mpSymbolLookupFn(NULL),
- mpSymbolLookupContext(NULL) {
-}
-
-
-CodeEmitter::~CodeEmitter() {
-}
-
-
-// Once you finish the compilation on a translation unit, you can call this
-// function to recycle the memory (which is used at compilation time and not
-// needed for runtime).
-//
-// NOTE: You should not call this funtion until the code-gen passes for a
-// given module is done. Otherwise, the results is undefined and may
-// cause the system crash!
-void CodeEmitter::releaseUnnecessary() {
- mMBBLocations.clear();
- mLabelLocations.clear();
- mGlobalAddressMap.clear();
- mFunctionToLazyStubMap.clear();
- GlobalToIndirectSymMap.clear();
- ExternalFnToStubMap.clear();
- PendingFunctions.clear();
-}
-
-
-void CodeEmitter::reset() {
- releaseUnnecessary();
-
- mpResult = NULL;
-
- mpSymbolLookupFn = NULL;
- mpSymbolLookupContext = NULL;
-
- mpTJI = NULL;
- mpTD = NULL;
-
- mpMemMgr->reset();
-}
-
-
-void *CodeEmitter::UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
- if (Addr == NULL) {
- // Removing mapping
- GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
- void *OldVal;
-
- if (I == mGlobalAddressMap.end()) {
- OldVal = NULL;
- } else {
- OldVal = I->second;
- mGlobalAddressMap.erase(I);
- }
-
- return OldVal;
- }
-
- void *&CurVal = mGlobalAddressMap[GV];
- void *OldVal = CurVal;
-
- CurVal = Addr;
-
- return OldVal;
-}
-
-
-unsigned int CodeEmitter::GetConstantPoolSizeInBytes(
- llvm::MachineConstantPool *MCP) {
- const std::vector<llvm::MachineConstantPoolEntry> &Constants =
- MCP->getConstants();
-
- if (Constants.empty())
- return 0;
-
- unsigned int Size = 0;
- for (int i = 0, e = Constants.size(); i != e; i++) {
- llvm::MachineConstantPoolEntry CPE = Constants[i];
- unsigned int AlignMask = CPE.getAlignment() - 1;
- Size = (Size + AlignMask) & ~AlignMask;
- llvm::Type *Ty = CPE.getType();
- Size += mpTD->getTypeAllocSize(Ty);
- }
-
- return Size;
-}
-
-// This function converts a Constant* into a GenericValue. The interesting
-// part is if C is a ConstantExpr.
-void CodeEmitter::GetConstantValue(const llvm::Constant *C,
- llvm::GenericValue &Result) {
- if (C->getValueID() == llvm::Value::UndefValueVal)
- return;
- else if (C->getValueID() == llvm::Value::ConstantExprVal) {
- const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
- const llvm::Constant *Op0 = CE->getOperand(0);
-
- switch (CE->getOpcode()) {
- case llvm::Instruction::GetElementPtr: {
- // Compute the index
- llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
- CE->op_end());
- uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(), Indices);
-
- GetConstantValue(Op0, Result);
- Result.PointerVal =
- static_cast<uint8_t*>(Result.PointerVal) + Offset;
-
- return;
- }
- case llvm::Instruction::Trunc: {
- uint32_t BitWidth =
- llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
-
- GetConstantValue(Op0, Result);
- Result.IntVal = Result.IntVal.trunc(BitWidth);
-
- return;
- }
- case llvm::Instruction::ZExt: {
- uint32_t BitWidth =
- llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
-
- GetConstantValue(Op0, Result);
- Result.IntVal = Result.IntVal.zext(BitWidth);
-
- return;
- }
- case llvm::Instruction::SExt: {
- uint32_t BitWidth =
- llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
-
- GetConstantValue(Op0, Result);
- Result.IntVal = Result.IntVal.sext(BitWidth);
-
- return;
- }
- case llvm::Instruction::FPTrunc: {
- // TODO(all): fixme: long double
- GetConstantValue(Op0, Result);
- Result.FloatVal = static_cast<float>(Result.DoubleVal);
- return;
- }
- case llvm::Instruction::FPExt: {
- // TODO(all): fixme: long double
- GetConstantValue(Op0, Result);
- Result.DoubleVal = static_cast<double>(Result.FloatVal);
- return;
- }
- case llvm::Instruction::UIToFP: {
- GetConstantValue(Op0, Result);
- if (CE->getType()->isFloatTy())
- Result.FloatVal =
- static_cast<float>(Result.IntVal.roundToDouble());
- else if (CE->getType()->isDoubleTy())
- Result.DoubleVal = Result.IntVal.roundToDouble();
- else if (CE->getType()->isX86_FP80Ty()) {
- const uint64_t zero[] = { 0, 0 };
- llvm::APFloat apf(llvm::APInt(80, 2, zero));
- apf.convertFromAPInt(Result.IntVal,
- false,
- llvm::APFloat::rmNearestTiesToEven);
- Result.IntVal = apf.bitcastToAPInt();
- }
- return;
- }
- case llvm::Instruction::SIToFP: {
- GetConstantValue(Op0, Result);
- if (CE->getType()->isFloatTy())
- Result.FloatVal =
- static_cast<float>(Result.IntVal.signedRoundToDouble());
- else if (CE->getType()->isDoubleTy())
- Result.DoubleVal = Result.IntVal.signedRoundToDouble();
- else if (CE->getType()->isX86_FP80Ty()) {
- const uint64_t zero[] = { 0, 0 };
- llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
- apf.convertFromAPInt(Result.IntVal,
- true,
- llvm::APFloat::rmNearestTiesToEven);
- Result.IntVal = apf.bitcastToAPInt();
- }
- return;
- }
- // double->APInt conversion handles sign
- case llvm::Instruction::FPToUI:
- case llvm::Instruction::FPToSI: {
- uint32_t BitWidth =
- llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
-
- GetConstantValue(Op0, Result);
- if (Op0->getType()->isFloatTy())
- Result.IntVal =
- llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
- else if (Op0->getType()->isDoubleTy())
- Result.IntVal =
- llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
- BitWidth);
- else if (Op0->getType()->isX86_FP80Ty()) {
- llvm::APFloat apf = llvm::APFloat(Result.IntVal);
- uint64_t V;
- bool Ignored;
- apf.convertToInteger(&V,
- BitWidth,
- CE->getOpcode() == llvm::Instruction::FPToSI,
- llvm::APFloat::rmTowardZero,
- &Ignored);
- Result.IntVal = V; // endian?
- }
- return;
- }
- case llvm::Instruction::PtrToInt: {
- uint32_t PtrWidth = mpTD->getPointerSizeInBits();
-
- GetConstantValue(Op0, Result);
- Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
- (Result.PointerVal));
-
- return;
- }
- case llvm::Instruction::IntToPtr: {
- uint32_t PtrWidth = mpTD->getPointerSizeInBits();
-
- GetConstantValue(Op0, Result);
- if (PtrWidth != Result.IntVal.getBitWidth())
- Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
- bccAssert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
-
- Result.PointerVal =
- llvm::PointerTy(
- static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
-
- return;
- }
- case llvm::Instruction::BitCast: {
- GetConstantValue(Op0, Result);
- const llvm::Type *DestTy = CE->getType();
-
- switch (Op0->getType()->getTypeID()) {
- case llvm::Type::IntegerTyID: {
- bccAssert(DestTy->isFloatingPointTy() && "invalid bitcast");
- if (DestTy->isFloatTy())
- Result.FloatVal = Result.IntVal.bitsToFloat();
- else if (DestTy->isDoubleTy())
- Result.DoubleVal = Result.IntVal.bitsToDouble();
- break;
- }
- case llvm::Type::FloatTyID: {
- bccAssert(DestTy->isIntegerTy(32) && "Invalid bitcast");
- Result.IntVal.floatToBits(Result.FloatVal);
- break;
- }
- case llvm::Type::DoubleTyID: {
- bccAssert(DestTy->isIntegerTy(64) && "Invalid bitcast");
- Result.IntVal.doubleToBits(Result.DoubleVal);
- break;
- }
- case llvm::Type::PointerTyID: {
- bccAssert(DestTy->isPointerTy() && "Invalid bitcast");
- break; // getConstantValue(Op0) above already converted it
- }
- default: {
- llvm_unreachable("Invalid bitcast operand");
- }
- }
- return;
- }
- case llvm::Instruction::Add:
- case llvm::Instruction::FAdd:
- case llvm::Instruction::Sub:
- case llvm::Instruction::FSub:
- case llvm::Instruction::Mul:
- case llvm::Instruction::FMul:
- case llvm::Instruction::UDiv:
- case llvm::Instruction::SDiv:
- case llvm::Instruction::URem:
- case llvm::Instruction::SRem:
- case llvm::Instruction::And:
- case llvm::Instruction::Or:
- case llvm::Instruction::Xor: {
- llvm::GenericValue LHS, RHS;
- GetConstantValue(Op0, LHS);
- GetConstantValue(CE->getOperand(1), RHS);
-
- switch (Op0->getType()->getTypeID()) {
- case llvm::Type::IntegerTyID: {
- switch (CE->getOpcode()) {
- case llvm::Instruction::Add: {
- Result.IntVal = LHS.IntVal + RHS.IntVal;
- break;
- }
- case llvm::Instruction::Sub: {
- Result.IntVal = LHS.IntVal - RHS.IntVal;
- break;
- }
- case llvm::Instruction::Mul: {
- Result.IntVal = LHS.IntVal * RHS.IntVal;
- break;
- }
- case llvm::Instruction::UDiv: {
- Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
- break;
- }
- case llvm::Instruction::SDiv: {
- Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
- break;
- }
- case llvm::Instruction::URem: {
- Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
- break;
- }
- case llvm::Instruction::SRem: {
- Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
- break;
- }
- case llvm::Instruction::And: {
- Result.IntVal = LHS.IntVal & RHS.IntVal;
- break;
- }
- case llvm::Instruction::Or: {
- Result.IntVal = LHS.IntVal | RHS.IntVal;
- break;
- }
- case llvm::Instruction::Xor: {
- Result.IntVal = LHS.IntVal ^ RHS.IntVal;
- break;
- }
- default: {
- llvm_unreachable("Invalid integer opcode");
- }
- }
- break;
- }
- case llvm::Type::FloatTyID: {
- switch (CE->getOpcode()) {
- case llvm::Instruction::FAdd: {
- Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
- break;
- }
- case llvm::Instruction::FSub: {
- Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
- break;
- }
- case llvm::Instruction::FMul: {
- Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
- break;
- }
- case llvm::Instruction::FDiv: {
- Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
- break;
- }
- case llvm::Instruction::FRem: {
- Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
- break;
- }
- default: {
- llvm_unreachable("Invalid float opcode");
- }
- }
- break;
- }
- case llvm::Type::DoubleTyID: {
- switch (CE->getOpcode()) {
- case llvm::Instruction::FAdd: {
- Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
- break;
- }
- case llvm::Instruction::FSub: {
- Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
- break;
- }
- case llvm::Instruction::FMul: {
- Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
- break;
- }
- case llvm::Instruction::FDiv: {
- Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
- break;
- }
- case llvm::Instruction::FRem: {
- Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
- break;
- }
- default: {
- llvm_unreachable("Invalid double opcode");
- }
- }
- break;
- }
- case llvm::Type::X86_FP80TyID:
- case llvm::Type::PPC_FP128TyID:
- case llvm::Type::FP128TyID: {
- llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
- switch (CE->getOpcode()) {
- case llvm::Instruction::FAdd: {
- apfLHS.add(llvm::APFloat(RHS.IntVal),
- llvm::APFloat::rmNearestTiesToEven);
- break;
- }
- case llvm::Instruction::FSub: {
- apfLHS.subtract(llvm::APFloat(RHS.IntVal),
- llvm::APFloat::rmNearestTiesToEven);
- break;
- }
- case llvm::Instruction::FMul: {
- apfLHS.multiply(llvm::APFloat(RHS.IntVal),
- llvm::APFloat::rmNearestTiesToEven);
- break;
- }
- case llvm::Instruction::FDiv: {
- apfLHS.divide(llvm::APFloat(RHS.IntVal),
- llvm::APFloat::rmNearestTiesToEven);
- break;
- }
- case llvm::Instruction::FRem: {
- apfLHS.mod(llvm::APFloat(RHS.IntVal),
- llvm::APFloat::rmNearestTiesToEven);
- break;
- }
- default: {
- llvm_unreachable("Invalid long double opcode");
- }
- }
- Result.IntVal = apfLHS.bitcastToAPInt();
- break;
- }
- default: {
- llvm_unreachable("Bad add type!");
- }
- } // End switch (Op0->getType()->getTypeID())
- return;
- }
- default: {
- break;
- }
- } // End switch (CE->getOpcode())
-
- std::string msg;
- llvm::raw_string_ostream Msg(msg);
- Msg << "ConstantExpr not handled: " << *CE;
- llvm::report_fatal_error(Msg.str());
- } // C->getValueID() == llvm::Value::ConstantExprVal
-
- switch (C->getType()->getTypeID()) {
- case llvm::Type::FloatTyID: {
- Result.FloatVal =
- llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
- break;
- }
- case llvm::Type::DoubleTyID: {
- Result.DoubleVal =
- llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
- break;
- }
- case llvm::Type::X86_FP80TyID:
- case llvm::Type::FP128TyID:
- case llvm::Type::PPC_FP128TyID: {
- Result.IntVal =
- llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
- break;
- }
- case llvm::Type::IntegerTyID: {
- Result.IntVal =
- llvm::cast<llvm::ConstantInt>(C)->getValue();
- break;
- }
- case llvm::Type::PointerTyID: {
- switch (C->getValueID()) {
- case llvm::Value::ConstantPointerNullVal: {
- Result.PointerVal = NULL;
- break;
- }
- case llvm::Value::FunctionVal: {
- const llvm::Function *F = static_cast<const llvm::Function*>(C);
- Result.PointerVal =
- GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
- break;
- }
- case llvm::Value::GlobalVariableVal: {
- const llvm::GlobalVariable *GV =
- static_cast<const llvm::GlobalVariable*>(C);
- Result.PointerVal =
- GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
- break;
- }
- case llvm::Value::BlockAddressVal: {
- bccAssert(false && "JIT does not support address-of-label yet!");
- }
- default: {
- llvm_unreachable("Unknown constant pointer type!");
- }
- }
- break;
- }
- default: {
- std::string msg;
- llvm::raw_string_ostream Msg(msg);
- Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
- llvm::report_fatal_error(Msg.str());
- break;
- }
- }
- return;
-}
-
-
-// Stores the data in @Val of type @Ty at address @Addr.
-void CodeEmitter::StoreValueToMemory(const llvm::GenericValue &Val,
- void *Addr,
- llvm::Type *Ty) {
- const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
-
- switch (Ty->getTypeID()) {
- case llvm::Type::IntegerTyID: {
- const llvm::APInt &IntVal = Val.IntVal;
- bccAssert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
- "Integer too small!");
-
- const uint8_t *Src =
- reinterpret_cast<const uint8_t*>(IntVal.getRawData());
-
- if (llvm::sys::isLittleEndianHost()) {
- // Little-endian host - the source is ordered from LSB to MSB.
- // Order the destination from LSB to MSB: Do a straight copy.
- memcpy(Addr, Src, StoreBytes);
- } else {
- // Big-endian host - the source is an array of 64 bit words
- // ordered from LSW to MSW.
- //
- // Each word is ordered from MSB to LSB.
- //
- // Order the destination from MSB to LSB:
- // Reverse the word order, but not the bytes in a word.
- unsigned int i = StoreBytes;
- while (i > sizeof(uint64_t)) {
- i -= sizeof(uint64_t);
- ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
- Src,
- sizeof(uint64_t));
- Src += sizeof(uint64_t);
- }
- ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
- }
- break;
- }
- case llvm::Type::FloatTyID: {
- *reinterpret_cast<float*>(Addr) = Val.FloatVal;
- break;
- }
- case llvm::Type::DoubleTyID: {
- *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
- break;
- }
- case llvm::Type::X86_FP80TyID: {
- memcpy(Addr, Val.IntVal.getRawData(), 10);
- break;
- }
- case llvm::Type::PointerTyID: {
- // Ensure 64 bit target pointers are fully initialized on 32 bit
- // hosts.
- if (StoreBytes != sizeof(llvm::PointerTy))
- memset(Addr, 0, StoreBytes);
- *((llvm::PointerTy*) Addr) = Val.PointerVal;
- break;
- }
- default: {
- break;
- }
- }
-
- if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
- std::reverse(reinterpret_cast<uint8_t*>(Addr),
- reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
-
- return;
-}
-
-
-// Recursive function to apply a @Constant value into the specified memory
-// location @Addr.
-void CodeEmitter::InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
- switch (C->getValueID()) {
- case llvm::Value::UndefValueVal: {
- // Nothing to do
- break;
- }
- case llvm::Value::ConstantVectorVal: {
- // dynamic cast may hurt performance
- const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
-
- unsigned int ElementSize = mpTD->getTypeAllocSize
- (CP->getType()->getElementType());
-
- for (int i = 0, e = CP->getNumOperands(); i != e;i++)
- InitializeConstantToMemory(
- CP->getOperand(i),
- reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
- break;
- }
- case llvm::Value::ConstantAggregateZeroVal: {
- memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
- break;
- }
- case llvm::Value::ConstantArrayVal: {
- const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
- unsigned int ElementSize = mpTD->getTypeAllocSize
- (CPA->getType()->getElementType());
-
- for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
- InitializeConstantToMemory(
- CPA->getOperand(i),
- reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
- break;
- }
- case llvm::Value::ConstantStructVal: {
- const llvm::ConstantStruct *CPS =
- static_cast<const llvm::ConstantStruct*>(C);
- const llvm::StructLayout *SL = mpTD->getStructLayout
- (llvm::cast<llvm::StructType>(CPS->getType()));
-
- for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
- InitializeConstantToMemory(
- CPS->getOperand(i),
- reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
- break;
- }
- default: {
- if (C->getType()->isFirstClassType()) {
- llvm::GenericValue Val;
- GetConstantValue(C, Val);
- StoreValueToMemory(Val, Addr, C->getType());
- } else {
- llvm_unreachable("Unknown constant type to initialize memory "
- "with!");
- }
- break;
- }
- }
- return;
-}
-
-
-void CodeEmitter::emitConstantPool(llvm::MachineConstantPool *MCP) {
- if (mpTJI->hasCustomConstantPool())
- return;
-
- // Constant pool address resolution is handled by the target itself in ARM
- // (TargetJITInfo::hasCustomConstantPool() returns true).
-#if !defined(PROVIDE_ARM_CODEGEN)
- const std::vector<llvm::MachineConstantPoolEntry> &Constants =
- MCP->getConstants();
-
- if (Constants.empty())
- return;
-
- unsigned Size = GetConstantPoolSizeInBytes(MCP);
- unsigned Align = MCP->getConstantPoolAlignment();
-
- mpConstantPoolBase = allocateSpace(Size, Align);
- mpConstantPool = MCP;
-
- if (mpConstantPoolBase == NULL)
- return; // out of memory
-
- unsigned Offset = 0;
- for (int i = 0, e = Constants.size(); i != e; i++) {
- llvm::MachineConstantPoolEntry CPE = Constants[i];
- unsigned AlignMask = CPE.getAlignment() - 1;
- Offset = (Offset + AlignMask) & ~AlignMask;
-
- uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
- mConstPoolAddresses.push_back(CAddr);
-
- if (CPE.isMachineConstantPoolEntry())
- llvm::report_fatal_error
- ("Initialize memory with machine specific constant pool"
- " entry has not been implemented!");
-
- InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
-
- llvm::Type *Ty = CPE.Val.ConstVal->getType();
- Offset += mpTD->getTypeAllocSize(Ty);
- }
-#endif
- return;
-}
-
-
-void CodeEmitter::initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
- if (mpTJI->hasCustomJumpTables())
- return;
-
- const std::vector<llvm::MachineJumpTableEntry> &JT =
- MJTI->getJumpTables();
- if (JT.empty())
- return;
-
- unsigned NumEntries = 0;
- for (int i = 0, e = JT.size(); i != e; i++)
- NumEntries += JT[i].MBBs.size();
-
- unsigned EntrySize = MJTI->getEntrySize(*mpTD);
-
- mpJumpTable = MJTI;
- mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
- MJTI->getEntryAlignment(*mpTD));
-
- return;
-}
-
-
-void CodeEmitter::emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
- if (mpTJI->hasCustomJumpTables())
- return;
-
- const std::vector<llvm::MachineJumpTableEntry> &JT =
- MJTI->getJumpTables();
- if (JT.empty() || mpJumpTableBase == 0)
- return;
-
- bccAssert(mpTargetMachine->getRelocationModel() == llvm::Reloc::Static &&
- (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
- "Cross JIT'ing?");
-
- // For each jump table, map each target in the jump table to the
- // address of an emitted MachineBasicBlock.
- intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
- for (int i = 0, ie = JT.size(); i != ie; i++) {
- const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
- // Store the address of the basic block for this jump table slot in the
- // memory we allocated for the jump table in 'initJumpTableInfo'
- for (int j = 0, je = MBBs.size(); j != je; j++)
- *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
- }
-}
-
-
-void *CodeEmitter::GetPointerToGlobal(llvm::GlobalValue *V,
- void *Reference,
- bool MayNeedFarStub) {
- switch (V->getValueID()) {
- case llvm::Value::FunctionVal: {
- llvm::Function *F = (llvm::Function*) V;
-
- // If we have code, go ahead and return that.
- if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
- return ResultPtr;
-
- if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
- // Return the function stub if it's already created.
- // We do this first so that:
- // we're returning the same address for the function as any
- // previous call.
- //
- // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
- // guaranteed to be close enough to call.
- return FnStub;
-
- // If we know the target can handle arbitrary-distance calls, try to
- // return a direct pointer.
- if (!MayNeedFarStub) {
- //
- // x86_64 architecture may encounter the bug:
- // http://llvm.org/bugs/show_bug.cgi?id=5201
- // which generate instruction "call" instead of "callq".
- //
- // And once the real address of stub is greater than 64-bit
- // long, the replacement will truncate to 32-bit resulting a
- // serious problem.
-#if !defined(__x86_64__)
- // If this is an external function pointer, we can force the JIT
- // to 'compile' it, which really just adds it to the map.
- if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
- return GetPointerToFunction(F, /* AbortOnFailure = */false);
- // Changing to false because wanting to allow later calls to
- // mpTJI->relocate() without aborting. For caching purpose
- }
-#endif
- }
-
- // Otherwise, we may need a to emit a stub, and, conservatively, we
- // always do so.
- return GetLazyFunctionStub(F);
- break;
- }
- case llvm::Value::GlobalVariableVal: {
- return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
- break;
- }
- case llvm::Value::GlobalAliasVal: {
- llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
- const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
-
- switch (GV->getValueID()) {
- case llvm::Value::FunctionVal: {
- // TODO(all): is there's any possibility that the function is not
- // code-gen'd?
- return GetPointerToFunction(
- static_cast<const llvm::Function*>(GV),
- /* AbortOnFailure = */false);
- // Changing to false because wanting to allow later calls to
- // mpTJI->relocate() without aborting. For caching purpose
- break;
- }
- case llvm::Value::GlobalVariableVal: {
- if (void *P = mGlobalAddressMap[GV])
- return P;
-
- llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
- EmitGlobalVariable(GVar);
-
- return mGlobalAddressMap[GV];
- break;
- }
- case llvm::Value::GlobalAliasVal: {
- bccAssert(false && "Alias should be resolved ultimately!");
- }
- }
- break;
- }
- default: {
- break;
- }
- }
- llvm_unreachable("Unknown type of global value!");
-}
-
-
-// If the specified function has been code-gen'd, return a pointer to the
-// function. If not, compile it, or use a stub to implement lazy compilation
-// if available.
-void *CodeEmitter::GetPointerToFunctionOrStub(llvm::Function *F) {
- // If we have already code generated the function, just return the
- // address.
- if (void *Addr = GetPointerToGlobalIfAvailable(F))
- return Addr;
-
- // Get a stub if the target supports it.
- return GetLazyFunctionStub(F);
-}
-
-
-void *CodeEmitter::GetLazyFunctionStub(llvm::Function *F) {
- // If we already have a lazy stub for this function, recycle it.
- void *&Stub = mFunctionToLazyStubMap[F];
- if (Stub)
- return Stub;
-
- // In any cases, we should NOT resolve function at runtime (though we are
- // able to). We resolve this right now.
- void *Actual = NULL;
- if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
- Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
- // Changing to false because wanting to allow later calls to
- // mpTJI->relocate() without aborting. For caching purpose
- }
-
- // Codegen a new stub, calling the actual address of the external
- // function, if it was resolved.
- llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
- startGVStub(F, SL.Size, SL.Alignment);
- Stub = mpTJI->emitFunctionStub(F, Actual, *this);
- finishGVStub();
-
- // We really want the address of the stub in the GlobalAddressMap for the
- // JIT, not the address of the external function.
- UpdateGlobalMapping(F, Stub);
-
- if (!Actual) {
- PendingFunctions.insert(F);
- } else {
-#if DEBUG_OLD_JIT_DISASSEMBLER
- Disassemble(DEBUG_OLD_JIT_DISASSEMBLER_FILE,
- mpTarget, mpTargetMachine, F->getName(),
- (unsigned char const *)Stub, SL.Size);
-#endif
- }
-
- return Stub;
-}
-
-
-void *CodeEmitter::GetPointerToFunction(const llvm::Function *F,
- bool AbortOnFailure) {
- void *Addr = GetPointerToGlobalIfAvailable(F);
- if (Addr)
- return Addr;
-
- bccAssert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
- "Internal error: only external defined function routes here!");
-
- // Handle the failure resolution by ourselves.
- Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
- /* AbortOnFailure = */ false);
-
- // If we resolved the symbol to a null address (eg. a weak external)
- // return a null pointer let the application handle it.
- if (Addr == NULL) {
- if (AbortOnFailure)
- llvm::report_fatal_error("Could not resolve external function "
- "address: " + F->getName());
- else
- return NULL;
- }
-
- AddGlobalMapping(F, Addr);
-
- return Addr;
-}
-
-
-void *CodeEmitter::GetPointerToNamedSymbol(const std::string &Name,
- bool AbortOnFailure) {
- if (void *Addr = FindRuntimeFunction(Name.c_str()))
- return Addr;
-
- if (mpSymbolLookupFn)
- if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
- return Addr;
-
- if (AbortOnFailure)
- llvm::report_fatal_error("Program used external symbol '" + Name +
- "' which could not be resolved!");
-
- return NULL;
-}
-
-
-// Return the address of the specified global variable, possibly emitting it
-// to memory if needed. This is used by the Emitter.
-void *CodeEmitter::GetOrEmitGlobalVariable(llvm::GlobalVariable *GV) {
- void *Ptr = GetPointerToGlobalIfAvailable(GV);
- if (Ptr)
- return Ptr;
-
- if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
- // If the global is external, just remember the address.
- Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
- AddGlobalMapping(GV, Ptr);
- } else {
- // If the global hasn't been emitted to memory yet, allocate space and
- // emit it into memory.
- Ptr = GetMemoryForGV(GV);
- AddGlobalMapping(GV, Ptr);
- EmitGlobalVariable(GV);
- }
-
- return Ptr;
-}
-
-
-// This method abstracts memory allocation of global variable so that the
-// JIT can allocate thread local variables depending on the target.
-void *CodeEmitter::GetMemoryForGV(llvm::GlobalVariable *GV) {
- void *Ptr;
-
- llvm::Type *GlobalType = GV->getType()->getElementType();
- size_t S = mpTD->getTypeAllocSize(GlobalType);
- size_t A = mpTD->getPreferredAlignment(GV);
-
- if (GV->isThreadLocal()) {
- // We can support TLS by
- //
- // Ptr = TJI.allocateThreadLocalMemory(S);
- //
- // But I tend not to.
- // (should we disable this in the front-end (i.e., slang)?).
- llvm::report_fatal_error
- ("Compilation of Thread Local Storage (TLS) is disabled!");
-
- } else if (mpTJI->allocateSeparateGVMemory()) {
- if (A <= 8) {
- Ptr = malloc(S);
- } else {
- // Allocate (S + A) bytes of memory, then use an aligned pointer
- // within that space.
- Ptr = malloc(S + A);
- unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
- Ptr = reinterpret_cast<uint8_t*>(Ptr) +
- (MisAligned ? (A - MisAligned) : 0);
- }
- } else {
- Ptr = allocateGlobal(S, A);
- }
-
- return Ptr;
-}
-
-
-void CodeEmitter::EmitGlobalVariable(llvm::GlobalVariable *GV) {
- void *GA = GetPointerToGlobalIfAvailable(GV);
-
- if (GV->isThreadLocal())
- llvm::report_fatal_error
- ("We don't support Thread Local Storage (TLS)!");
-
- if (GA == NULL) {
- // If it's not already specified, allocate memory for the global.
- GA = GetMemoryForGV(GV);
- AddGlobalMapping(GV, GA);
- }
-
- InitializeConstantToMemory(GV->getInitializer(), GA);
-
- // You can do some statistics on global variable here.
- return;
-}
-
-
-void *CodeEmitter::GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
- // Make sure GV is emitted first, and create a stub containing the fully
- // resolved address.
- void *GVAddress = GetPointerToGlobal(V, Reference, false);
-
- // If we already have a stub for this global variable, recycle it.
- void *&IndirectSym = GlobalToIndirectSymMap[V];
- // Otherwise, codegen a new indirect symbol.
- if (!IndirectSym)
- IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
-
- return IndirectSym;
-}
-
-
-// Return a stub for the function at the specified address.
-void *CodeEmitter::GetExternalFunctionStub(void *FnAddr) {
- void *&Stub = ExternalFnToStubMap[FnAddr];
- if (Stub)
- return Stub;
-
- llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
- startGVStub(0, SL.Size, SL.Alignment);
- Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
- finishGVStub();
-
- return Stub;
-}
-
-
-void CodeEmitter::setTargetMachine(llvm::TargetMachine &TM) {
- mpTargetMachine = &TM;
-
- // Set Target
- mpTarget = &TM.getTarget();
- // Set TargetJITInfo
- mpTJI = TM.getJITInfo();
- // set TargetData
- mpTD = TM.getTargetData();
-
- bccAssert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
-
- return;
-}
-
-
-// This callback is invoked when the specified function is about to be code
-// generated. This initializes the BufferBegin/End/Ptr fields.
-void CodeEmitter::startFunction(llvm::MachineFunction &F) {
- uintptr_t ActualSize = 0;
-
- mpMemMgr->setMemoryWritable();
-
- // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
- // MachineCodeEmitter, which is the super class of the class
- // JITCodeEmitter.
- //
- // BufferBegin/BufferEnd - Pointers to the start and end of the memory
- // allocated for this code buffer.
- //
- // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
- // code. This is guranteed to be in the range
- // [BufferBegin, BufferEnd]. If this pointer is at
- // BufferEnd, it will never move due to code emission, and
- // all code emission requests will be ignored (this is the
- // buffer overflow condition).
- BufferBegin = CurBufferPtr =
- mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
- BufferEnd = BufferBegin + ActualSize;
-
- if (mpCurEmitFunction == NULL) {
- mpCurEmitFunction = new FuncInfo(); // TODO(all): Allocation check!
- mpCurEmitFunction->name = NULL;
- mpCurEmitFunction->addr = NULL;
- mpCurEmitFunction->size = 0;
- }
-
- // Ensure the constant pool/jump table info is at least 4-byte aligned.
- emitAlignment(16);
-
- emitConstantPool(F.getConstantPool());
- if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
- initJumpTableInfo(MJTI);
-
- // About to start emitting the machine code for the function.
- emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
-
- UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
-
- mpCurEmitFunction->addr = CurBufferPtr;
-
- mMBBLocations.clear();
-}
-
-
-// This callback is invoked when the specified function has finished code
-// generation. If a buffer overflow has occurred, this method returns true
-// (the callee is required to try again).
-bool CodeEmitter::finishFunction(llvm::MachineFunction &F) {
- if (CurBufferPtr == BufferEnd) {
- // No enough memory
- mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
- return false;
- }
-
- if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
- emitJumpTableInfo(MJTI);
-
- if (!mRelocations.empty()) {
- //ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
-
- // Resolve the relocations to concrete pointers.
- for (int i = 0, e = mRelocations.size(); i != e; i++) {
- llvm::MachineRelocation &MR = mRelocations[i];
- void *ResultPtr = NULL;
-
- if (!MR.letTargetResolve()) {
- if (MR.isExternalSymbol()) {
- ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
-
- if (MR.mayNeedFarStub()) {
- ResultPtr = GetExternalFunctionStub(ResultPtr);
- }
-
- } else if (MR.isGlobalValue()) {
- ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
- BufferBegin
- + MR.getMachineCodeOffset(),
- MR.mayNeedFarStub());
- } else if (MR.isIndirectSymbol()) {
- ResultPtr =
- GetPointerToGVIndirectSym(
- MR.getGlobalValue(),
- BufferBegin + MR.getMachineCodeOffset());
- } else if (MR.isBasicBlock()) {
- ResultPtr =
- (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
- } else if (MR.isConstantPoolIndex()) {
- ResultPtr =
- (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
- } else {
- bccAssert(MR.isJumpTableIndex() && "Unknown type of relocation");
- ResultPtr =
- (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
- }
-
- if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
- // TODO(logan): Cache external symbol relocation entry.
- // Currently, we are not caching them. But since Android
- // system is using prelink, it is not a problem.
-#if 0
- // Cache the relocation result address
- mCachingRelocations.push_back(
- oBCCRelocEntry(MR.getRelocationType(),
- MR.getMachineCodeOffset() + BufferOffset,
- ResultPtr));
-#endif
- }
-
- MR.setResultPointer(ResultPtr);
- }
- }
-
- mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
- mpMemMgr->getGOTBase());
- }
-
- mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
- // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
- // global variables that were referenced in the relocations.
- if (CurBufferPtr == BufferEnd)
- return false;
-
- // Now that we've succeeded in emitting the function.
- mpCurEmitFunction->size = CurBufferPtr - BufferBegin;
-
-#if DEBUG_OLD_JIT_DISASSEMBLER
- // FnStart is the start of the text, not the start of the constant pool
- // and other per-function data.
- uint8_t *FnStart =
- reinterpret_cast<uint8_t*>(
- GetPointerToGlobalIfAvailable(F.getFunction()));
-
- // FnEnd is the end of the function's machine code.
- uint8_t *FnEnd = CurBufferPtr;
-#endif
-
- BufferBegin = CurBufferPtr = 0;
-
- if (F.getFunction()->hasName()) {
- std::string const &name = F.getFunction()->getNameStr();
- mpResult->mEmittedFunctions[name] = mpCurEmitFunction;
- mpCurEmitFunction = NULL;
- }
-
- mRelocations.clear();
- mConstPoolAddresses.clear();
-
- if (mpMMI)
- mpMMI->EndFunction();
-
- updateFunctionStub(F.getFunction());
-
- // Mark code region readable and executable if it's not so already.
- mpMemMgr->setMemoryExecutable();
-
-#if DEBUG_OLD_JIT_DISASSEMBLER
- Disassemble(DEBUG_OLD_JIT_DISASSEMBLER_FILE,
- mpTarget, mpTargetMachine, F.getFunction()->getName(),
- (unsigned char const *)FnStart, FnEnd - FnStart);
-#endif
-
- return false;
-}
-
-
-void CodeEmitter::startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
- unsigned Alignment) {
- mpSavedBufferBegin = BufferBegin;
- mpSavedBufferEnd = BufferEnd;
- mpSavedCurBufferPtr = CurBufferPtr;
-
- BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
- Alignment);
- BufferEnd = BufferBegin + StubSize + 1;
-
- return;
-}
-
-
-void CodeEmitter::startGVStub(void *Buffer, unsigned StubSize) {
- mpSavedBufferBegin = BufferBegin;
- mpSavedBufferEnd = BufferEnd;
- mpSavedCurBufferPtr = CurBufferPtr;
-
- BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
- BufferEnd = BufferBegin + StubSize + 1;
-
- return;
-}
-
-
-void CodeEmitter::finishGVStub() {
- bccAssert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
-
- // restore
- BufferBegin = mpSavedBufferBegin;
- BufferEnd = mpSavedBufferEnd;
- CurBufferPtr = mpSavedCurBufferPtr;
-}
-
-
-// Allocates and fills storage for an indirect GlobalValue, and returns the
-// address.
-void *CodeEmitter::allocIndirectGV(const llvm::GlobalValue *GV,
- const uint8_t *Buffer, size_t Size,
- unsigned Alignment) {
- uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
- memcpy(IndGV, Buffer, Size);
- return IndGV;
-}
-
-
-// Allocate memory for a global. Unlike allocateSpace, this method does not
-// allocate memory in the current output buffer, because a global may live
-// longer than the current function.
-void *CodeEmitter::allocateGlobal(uintptr_t Size, unsigned Alignment) {
- // Delegate this call through the memory manager.
- return mpMemMgr->allocateGlobal(Size, Alignment);
-}
-
-
-// This should be called by the target when a new basic block is about to be
-// emitted. This way the MCE knows where the start of the block is, and can
-// implement getMachineBasicBlockAddress.
-void CodeEmitter::StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
- if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
- mMBBLocations.resize((MBB->getNumber() + 1) * 2);
- mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
- return;
-}
-
-
-// Return the address of the jump table with index @Index in the function
-// that last called initJumpTableInfo.
-uintptr_t CodeEmitter::getJumpTableEntryAddress(unsigned Index) const {
- const std::vector<llvm::MachineJumpTableEntry> &JT =
- mpJumpTable->getJumpTables();
-
- bccAssert((Index < JT.size()) && "Invalid jump table index!");
-
- unsigned int Offset = 0;
- unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
-
- for (unsigned i = 0; i < Index; i++)
- Offset += JT[i].MBBs.size();
- Offset *= EntrySize;
-
- return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
-}
-
-
-// Return the address of the specified MachineBasicBlock, only usable after
-// the label for the MBB has been emitted.
-uintptr_t CodeEmitter::getMachineBasicBlockAddress(
- llvm::MachineBasicBlock *MBB) const {
- bccAssert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
- mMBBLocations[MBB->getNumber()] &&
- "MBB not emitted!");
- return mMBBLocations[MBB->getNumber()];
-}
-
-
-void CodeEmitter::updateFunctionStub(const llvm::Function *F) {
- // Get the empty stub we generated earlier.
- void *Stub;
- std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
- if (I != PendingFunctions.end())
- Stub = mFunctionToLazyStubMap[F];
- else
- return;
-
- void *Addr = GetPointerToGlobalIfAvailable(F);
-
- bccAssert(Addr != Stub &&
- "Function must have non-stub address to be updated.");
-
- // Tell the target jit info to rewrite the stub at the specified address,
- // rather than creating a new one.
- llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
- startGVStub(Stub, SL.Size);
- mpTJI->emitFunctionStub(F, Addr, *this);
- finishGVStub();
-
-#if DEBUG_OLD_JIT_DISASSEMBLER
- Disassemble(DEBUG_OLD_JIT_DISASSEMBLER_FILE,
- mpTarget, mpTargetMachine, F->getName(),
- (unsigned char const *)Stub, SL.Size);
-#endif
-
- PendingFunctions.erase(I);
-}
-
-
-} // namespace bcc
diff --git a/lib/CodeGen/CodeEmitter.h b/lib/CodeGen/CodeEmitter.h
deleted file mode 100644
index fc6dab1..0000000
--- a/lib/CodeGen/CodeEmitter.h
+++ /dev/null
@@ -1,339 +0,0 @@
-//===-- CodeEmitter.h - CodeEmitter Class -----------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See external/llvm/LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the CodeEmitter class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef BCC_CODEEMITTER_H
-#define BCC_CODEEMITTER_H
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_assert.h>
-#include <bcc/bcc_cache.h>
-#include "ExecutionEngine/bcc_internal.h"
-
-#include "Config.h"
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineRelocation.h"
-#include "llvm/CodeGen/JITCodeEmitter.h"
-#include "llvm/Support/ValueHandle.h"
-
-#include <map>
-#include <vector>
-#include <set>
-
-#include <stdint.h>
-
-namespace llvm {
- class Constant;
- class GenericValue;
- class GlobalVariable;
- class GlobalValue;
- class Function;
- class MachineBasicBlock;
- class MachineFunction;
- class MachineJumpTableInfo;
- class MachineModuleInfo;
- class MCSymbol;
- class Target;
- class TargetData;
- class TargetJITInfo;
- class TargetMachine;
- class Type;
-}
-
-namespace bcc {
- class CodeMemoryManager;
- class ScriptCompiled;
-
- class CodeEmitter : public llvm::JITCodeEmitter {
- private:
- typedef llvm::DenseMap<const llvm::GlobalValue *, void *>
- GlobalAddressMapTy;
-
- typedef llvm::DenseMap<const llvm::Function *, void*>
- FunctionToLazyStubMapTy;
-
- typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void *>
- GlobalToIndirectSymMapTy;
-
- public:
- typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
-
-
- private:
- ScriptCompiled *mpResult;
-
- CodeMemoryManager *mpMemMgr;
-
- llvm::TargetMachine *mpTargetMachine;
-
- // The JITInfo for the target we are compiling to
- const llvm::Target *mpTarget;
-
- llvm::TargetJITInfo *mpTJI;
-
- const llvm::TargetData *mpTD;
-
-
- FuncInfo *mpCurEmitFunction;
-
- GlobalAddressMapTy mGlobalAddressMap;
-
- // This vector is a mapping from MBB ID's to their address. It is filled in
- // by the StartMachineBasicBlock callback and queried by the
- // getMachineBasicBlockAddress callback.
- std::vector<uintptr_t> mMBBLocations;
-
- // The constant pool for the current function.
- llvm::MachineConstantPool *mpConstantPool;
-
- // A pointer to the first entry in the constant pool.
- void *mpConstantPoolBase;
-
- // Addresses of individual constant pool entries.
- llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
-
- // The jump tables for the current function.
- llvm::MachineJumpTableInfo *mpJumpTable;
-
- // A pointer to the first entry in the jump table.
- void *mpJumpTableBase;
-
- // When outputting a function stub in the context of some other function, we
- // save BufferBegin/BufferEnd/CurBufferPtr here.
- uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
-
- // These are the relocations that the function needs, as emitted.
- std::vector<llvm::MachineRelocation> mRelocations;
-
-#if 0
- std::vector<oBCCRelocEntry> mCachingRelocations;
-#endif
-
- // This vector is a mapping from Label ID's to their address.
- llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
-
- // Machine module info for exception informations
- llvm::MachineModuleInfo *mpMMI;
-
-
- FunctionToLazyStubMapTy mFunctionToLazyStubMap;
-
- std::set<const llvm::Function*> PendingFunctions;
-
- GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
-
- std::map<void*, void*> ExternalFnToStubMap;
-
- public:
- // Resolver to undefined symbol in CodeEmitter
- BCCSymbolLookupFn mpSymbolLookupFn;
- void *mpSymbolLookupContext;
-
- // Will take the ownership of @MemMgr
- explicit CodeEmitter(ScriptCompiled *result, CodeMemoryManager *pMemMgr);
-
- virtual ~CodeEmitter();
-
- global_addresses_const_iterator global_address_begin() const {
- return mGlobalAddressMap.begin();
- }
-
- global_addresses_const_iterator global_address_end() const {
- return mGlobalAddressMap.end();
- }
-
-#if 0
- std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
- return mCachingRelocations;
- }
-#endif
-
- void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
- mpSymbolLookupFn = pFn;
- mpSymbolLookupContext = pContext;
- }
-
- void setTargetMachine(llvm::TargetMachine &TM);
-
- // This callback is invoked when the specified function is about to be code
- // generated. This initializes the BufferBegin/End/Ptr fields.
- virtual void startFunction(llvm::MachineFunction &F);
-
- // This callback is invoked when the specified function has finished code
- // generation. If a buffer overflow has occurred, this method returns true
- // (the callee is required to try again).
- virtual bool finishFunction(llvm::MachineFunction &F);
-
- // Allocates and fills storage for an indirect GlobalValue, and returns the
- // address.
- virtual void *allocIndirectGV(const llvm::GlobalValue *GV,
- const uint8_t *Buffer, size_t Size,
- unsigned Alignment);
-
- // Emits a label
- virtual void emitLabel(llvm::MCSymbol *Label) {
- mLabelLocations[Label] = getCurrentPCValue();
- }
-
- // Allocate memory for a global. Unlike allocateSpace, this method does not
- // allocate memory in the current output buffer, because a global may live
- // longer than the current function.
- virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment);
-
- // This should be called by the target when a new basic block is about to be
- // emitted. This way the MCE knows where the start of the block is, and can
- // implement getMachineBasicBlockAddress.
- virtual void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB);
-
- // Whenever a relocatable address is needed, it should be noted with this
- // interface.
- virtual void addRelocation(const llvm::MachineRelocation &MR) {
- mRelocations.push_back(MR);
- }
-
- // Return the address of the @Index entry in the constant pool that was
- // last emitted with the emitConstantPool method.
- virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
- bccAssert(Index < mpConstantPool->getConstants().size() &&
- "Invalid constant pool index!");
- return mConstPoolAddresses[Index];
- }
-
- // Return the address of the jump table with index @Index in the function
- // that last called initJumpTableInfo.
- virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const;
-
- // Return the address of the specified MachineBasicBlock, only usable after
- // the label for the MBB has been emitted.
- virtual uintptr_t getMachineBasicBlockAddress(
- llvm::MachineBasicBlock *MBB) const;
-
- // Return the address of the specified LabelID, only usable after the
- // LabelID has been emitted.
- virtual uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
- bccAssert(mLabelLocations.count(Label) && "Label not emitted!");
- return mLabelLocations.find(Label)->second;
- }
-
- // Specifies the MachineModuleInfo object. This is used for exception
- // handling purposes.
- virtual void setModuleInfo(llvm::MachineModuleInfo *Info) {
- mpMMI = Info;
- }
-
- void releaseUnnecessary();
-
- void reset();
-
- private:
- void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
- unsigned Alignment);
-
- void startGVStub(void *Buffer, unsigned StubSize);
-
- void finishGVStub();
-
- // Replace an existing mapping for GV with a new address. This updates both
- // maps as required. If Addr is null, the entry for the global is removed
- // from the mappings.
- void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr);
-
- // Tell the execution engine that the specified global is at the specified
- // location. This is used internally as functions are JIT'd and as global
- // variables are laid out in memory.
- void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
- void *&CurVal = mGlobalAddressMap[GV];
- assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!");
- CurVal = Addr;
- }
-
- // This returns the address of the specified global value if it is has
- // already been codegen'd, otherwise it returns null.
- void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
- GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
- return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
- }
-
- unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP);
-
- // This function converts a Constant* into a GenericValue. The interesting
- // part is if C is a ConstantExpr.
- void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result);
-
- // Stores the data in @Val of type @Ty at address @Addr.
- void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
- llvm::Type *Ty);
-
- // Recursive function to apply a @Constant value into the specified memory
- // location @Addr.
- void InitializeConstantToMemory(const llvm::Constant *C, void *Addr);
-
- void emitConstantPool(llvm::MachineConstantPool *MCP);
-
- void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI);
-
- void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI);
-
- void *GetPointerToGlobal(llvm::GlobalValue *V,
- void *Reference,
- bool MayNeedFarStub);
-
- // If the specified function has been code-gen'd, return a pointer to the
- // function. If not, compile it, or use a stub to implement lazy compilation
- // if available.
- void *GetPointerToFunctionOrStub(llvm::Function *F);
-
- void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
- return mFunctionToLazyStubMap.lookup(F);
- }
-
- void *GetLazyFunctionStub(llvm::Function *F);
-
- void updateFunctionStub(const llvm::Function *F);
-
- void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure);
-
- void *GetPointerToNamedSymbol(const std::string &Name,
- bool AbortOnFailure);
-
- // Return the address of the specified global variable, possibly emitting it
- // to memory if needed. This is used by the Emitter.
- void *GetOrEmitGlobalVariable(llvm::GlobalVariable *GV);
-
- // This method abstracts memory allocation of global variable so that the
- // JIT can allocate thread local variables depending on the target.
- void *GetMemoryForGV(llvm::GlobalVariable *GV);
-
- void EmitGlobalVariable(llvm::GlobalVariable *GV);
-
- void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference);
-
- // This is the equivalent of FunctionToLazyStubMap for external functions.
- //
- // TODO(llvm.org): Of course, external functions don't need a lazy stub.
- // It's actually here to make it more likely that far calls
- // succeed, but no single stub can guarantee that. I'll
- // remove this in a subsequent checkin when I actually fix
- // far calls.
-
- // Return a stub for the function at the specified address.
- void *GetExternalFunctionStub(void *FnAddr);
-
- };
-
-} // namespace bcc
-
-#endif // BCC_CODEEMITTER_H
diff --git a/lib/CodeGen/CodeMemoryManager.cpp b/lib/CodeGen/CodeMemoryManager.cpp
deleted file mode 100644
index 5f015cc..0000000
--- a/lib/CodeGen/CodeMemoryManager.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-//===-- CodeMemoryManager.cpp - CodeMemoryManager Class -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See external/llvm/LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the CodeMemoryManager class.
-//
-//===----------------------------------------------------------------------===//
-
-#define LOG_TAG "bcc"
-#include <bcc/bcc_assert.h>
-
-#include <cutils/log.h>
-
-#include "CodeMemoryManager.h"
-#include "ExecutionEngine/OldJIT/ContextManager.h"
-
-#include "llvm/Support/ErrorHandling.h"
-
-#include <sys/mman.h>
-
-#include <stddef.h>
-
-#include <map>
-#include <string>
-#include <utility>
-
-
-namespace bcc {
-
-
-const unsigned int MaxCodeSize = ContextManager::ContextCodeSize;
-const unsigned int MaxGOTSize = 1 * 1024;
-const unsigned int MaxGlobalVarSize = ContextManager::ContextDataSize;
-
-
-CodeMemoryManager::CodeMemoryManager()
- : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
-
- reset();
- std::string ErrMsg;
-
- mpCodeMem = ContextManager::get().allocateContext();
-
- if (!mpCodeMem) {
- ALOGE("Unable to allocate mpCodeMem\n");
- llvm::report_fatal_error("Failed to allocate memory for emitting "
- "codes\n" + ErrMsg);
- }
-
- // Set global variable pool
- mpGVMem = mpCodeMem + MaxCodeSize;
-
- return;
-}
-
-
-CodeMemoryManager::~CodeMemoryManager() {
- mpCodeMem = 0;
- mpGVMem = 0;
-}
-
-
-uint8_t *CodeMemoryManager::allocateSGMemory(uintptr_t Size,
- unsigned Alignment) {
-
- intptr_t FreeMemSize = getFreeCodeMemSize();
- if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
- // The code size excesses our limit
- return NULL;
-
- if (Alignment == 0)
- Alignment = 1;
-
- uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
- result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
-
- mCurSGMemIdx = result - getCodeMemBase();
-
- return result;
-}
-
-
-// setMemoryWritable - When code generation is in progress, the code pages
-// may need permissions changed.
-void CodeMemoryManager::setMemoryWritable() {
- mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
-}
-
-
-// When code generation is done and we're ready to start execution, the
-// code pages may need permissions changed.
-void CodeMemoryManager::setMemoryExecutable() {
- mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
-}
-
-
-// Setting this flag to true makes the memory manager garbage values over
-// freed memory. This is useful for testing and debugging, and is to be
-// turned on by default in debug mode.
-void CodeMemoryManager::setPoisonMemory(bool poison) {
- // no effect
-}
-
-
-// Global Offset Table Management
-
-// If the current table requires a Global Offset Table, this method is
-// invoked to allocate it. This method is required to set HasGOT to true.
-void CodeMemoryManager::AllocateGOT() {
- bccAssert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
- mpGOTBase = allocateSGMemory(MaxGOTSize);
- HasGOT = true;
-}
-
-
-// Main Allocation Functions
-
-// When we start JITing a function, the JIT calls this method to allocate a
-// block of free RWX memory, which returns a pointer to it. If the JIT wants
-// to request a block of memory of at least a certain size, it passes that
-// value as ActualSize, and this method returns a block with at least that
-// much space. If the JIT doesn't know ahead of time how much space it will
-// need to emit the function, it passes 0 for the ActualSize. In either
-// case, this method is required to pass back the size of the allocated
-// block through ActualSize. The JIT will be careful to not write more than
-// the returned ActualSize bytes of memory.
-uint8_t *CodeMemoryManager::startFunctionBody(const llvm::Function *F,
- uintptr_t &ActualSize) {
- intptr_t FreeMemSize = getFreeCodeMemSize();
- if ((FreeMemSize < 0) ||
- (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
- // The code size excesses our limit
- return NULL;
-
- ActualSize = getFreeCodeMemSize();
- return (getCodeMemBase() + mCurFuncMemIdx);
-}
-
-// This method is called when the JIT is done codegen'ing the specified
-// function. At this point we know the size of the JIT compiled function.
-// This passes in FunctionStart (which was returned by the startFunctionBody
-// method) and FunctionEnd which is a pointer to the actual end of the
-// function. This method should mark the space allocated and remember where
-// it is in case the client wants to deallocate it.
-void CodeMemoryManager::endFunctionBody(const llvm::Function *F,
- uint8_t *FunctionStart,
- uint8_t *FunctionEnd) {
- bccAssert(FunctionEnd > FunctionStart);
- bccAssert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
- "Mismatched function start/end!");
-
- // Advance the pointer
- intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
- bccAssert(FunctionCodeSize <= getFreeCodeMemSize() &&
- "Code size excess the limitation!");
- mCurFuncMemIdx += FunctionCodeSize;
-
- // Record there's a function in our memory start from @FunctionStart
- bccAssert(mFunctionMap.find(F) == mFunctionMap.end() &&
- "Function already emitted!");
- mFunctionMap.insert(
- std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
- F, std::make_pair(FunctionStart, FunctionEnd)));
-
- return;
-}
-
-// Allocate a (function code) memory block of the given size. This method
-// cannot be called between calls to startFunctionBody and endFunctionBody.
-uint8_t *CodeMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
- if (getFreeCodeMemSize() < Size) {
- // The code size excesses our limit
- return NULL;
- }
-
- if (Alignment == 0)
- Alignment = 1;
-
- uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
- result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
- ~(intptr_t) (Alignment - 1));
-
- mCurFuncMemIdx = (result + Size) - getCodeMemBase();
-
- return result;
-}
-
-// Allocate memory for a global variable.
-uint8_t *CodeMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
- if (getFreeGVMemSize() < Size) {
- // The code size excesses our limit
- ALOGE("No Global Memory");
- return NULL;
- }
-
- if (Alignment == 0)
- Alignment = 1;
-
- uint8_t *result = getGVMemBase() + mCurGVMemIdx;
- result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
- ~(intptr_t) (Alignment - 1));
-
- mCurGVMemIdx = (result + Size) - getGVMemBase();
-
- return result;
-}
-
-// Free the specified function body. The argument must be the return value
-// from a call to startFunctionBody() that hasn't been deallocated yet. This
-// is never called when the JIT is currently emitting a function.
-void CodeMemoryManager::deallocateFunctionBody(void *Body) {
- // linear search
- uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
- for (FunctionMapTy::iterator I = mFunctionMap.begin(),
- E = mFunctionMap.end(); I != E; I++) {
- if (I->second.first == Body) {
- FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
- FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
- break;
- }
- }
-
- bccAssert((FunctionStart == NULL) && "Memory is never allocated!");
-
- // free the memory
- intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
-
- bccAssert(SizeNeedMove >= 0 &&
- "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
- " be correctly calculated!");
-
- if (SizeNeedMove > 0) {
- // there's data behind deallocating function
- memmove(FunctionStart, FunctionEnd, SizeNeedMove);
- }
-
- mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
-}
-
-// Below are the methods we create
-void CodeMemoryManager::reset() {
- mpGOTBase = NULL;
- HasGOT = false;
-
- mCurFuncMemIdx = 0;
- mCurSGMemIdx = MaxCodeSize - 1;
- mCurGVMemIdx = 0;
-
- mFunctionMap.clear();
-}
-
-} // namespace bcc
diff --git a/lib/CodeGen/CodeMemoryManager.h b/lib/CodeGen/CodeMemoryManager.h
deleted file mode 100644
index ed003ec..0000000
--- a/lib/CodeGen/CodeMemoryManager.h
+++ /dev/null
@@ -1,246 +0,0 @@
-//===-- CodeMemoryManager.h - CodeMemoryManager Class -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See external/llvm/LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the CodeMemoryManager class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef BCC_CODEMEMORYMANAGER_H
-#define BCC_CODEMEMORYMANAGER_H
-
-#include "ExecutionEngine/Compiler.h"
-
-#include "llvm/ExecutionEngine/JITMemoryManager.h"
-
-#include <bcc/bcc_assert.h>
-
-#include <map>
-#include <utility>
-
-#include <stddef.h>
-#include <stdint.h>
-
-
-namespace llvm {
- // Forward Declaration
- class Function;
- class GlobalValue;
-};
-
-
-namespace bcc {
-
- //////////////////////////////////////////////////////////////////////////////
- // Memory manager for the code reside in memory
- //
- // The memory for our code emitter is very simple and is conforming to the
- // design decisions of Android RenderScript's Exection Environment:
- // The code, data, and symbol sizes are limited (currently 100KB.)
- //
- // It's very different from typical compiler, which has no limitation
- // on the code size. How does code emitter know the size of the code
- // it is about to emit? It does not know beforehand. We want to solve
- // this without complicating the code emitter too much.
- //
- // We solve this by pre-allocating a certain amount of memory,
- // and then start the code emission. Once the buffer overflows, the emitter
- // simply discards all the subsequent emission but still has a counter
- // on how many bytes have been emitted.
- //
- // So once the whole emission is done, if there's a buffer overflow,
- // it re-allocates the buffer with enough size (based on the
- // counter from previous emission) and re-emit again.
-
- extern const unsigned int MaxCodeSize;
- extern const unsigned int MaxGOTSize;
- extern const unsigned int MaxGlobalVarSize;
-
-
- class CodeMemoryManager : public llvm::JITMemoryManager {
- private:
- typedef std::map<const llvm::Function*,
- std::pair<void * /* start address */,
- void * /* end address */> > FunctionMapTy;
-
-
- private:
- //
- // Our memory layout is as follows:
- //
- // The direction of arrows (-> and <-) shows memory's growth direction
- // when more space is needed.
- //
- // @mpCodeMem:
- // +--------------------------------------------------------------+
- // | Function Memory ... -> <- ... Stub/GOT |
- // +--------------------------------------------------------------+
- // |<------------------ Total: @MaxCodeSize KiB ----------------->|
- //
- // Where size of GOT is @MaxGOTSize KiB.
- //
- // @mpGVMem:
- // +--------------------------------------------------------------+
- // | Global variable ... -> |
- // +--------------------------------------------------------------+
- // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
- //
- //
- // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
- // of function code's memory usage
- // @mCurSGMemIdx: The current index (starting from tail) of the last byte
- // of stub/GOT's memory usage
- // @mCurGVMemIdx: The current index (starting from tail) of the last byte
- // of global variable's memory usage
- //
- uintptr_t mCurFuncMemIdx;
- uintptr_t mCurSGMemIdx;
- uintptr_t mCurGVMemIdx;
- char *mpCodeMem;
- char *mpGVMem;
-
- // GOT Base
- uint8_t *mpGOTBase;
-
- FunctionMapTy mFunctionMap;
-
-
- public:
- CodeMemoryManager();
-
- virtual ~CodeMemoryManager();
-
- uint8_t *getCodeMemBase() const {
- return reinterpret_cast<uint8_t*>(mpCodeMem);
- }
-
- // setMemoryWritable - When code generation is in progress, the code pages
- // may need permissions changed.
- virtual void setMemoryWritable();
-
- // When code generation is done and we're ready to start execution, the
- // code pages may need permissions changed.
- virtual void setMemoryExecutable();
-
- // Setting this flag to true makes the memory manager garbage values over
- // freed memory. This is useful for testing and debugging, and is to be
- // turned on by default in debug mode.
- virtual void setPoisonMemory(bool poison);
-
-
- // Global Offset Table Management
-
- // If the current table requires a Global Offset Table, this method is
- // invoked to allocate it. This method is required to set HasGOT to true.
- virtual void AllocateGOT();
-
- // If this is managing a Global Offset Table, this method should return a
- // pointer to its base.
- virtual uint8_t *getGOTBase() const {
- return mpGOTBase;
- }
-
- // Main Allocation Functions
-
- // When we start JITing a function, the JIT calls this method to allocate a
- // block of free RWX memory, which returns a pointer to it. If the JIT wants
- // to request a block of memory of at least a certain size, it passes that
- // value as ActualSize, and this method returns a block with at least that
- // much space. If the JIT doesn't know ahead of time how much space it will
- // need to emit the function, it passes 0 for the ActualSize. In either
- // case, this method is required to pass back the size of the allocated
- // block through ActualSize. The JIT will be careful to not write more than
- // the returned ActualSize bytes of memory.
- virtual uint8_t *startFunctionBody(const llvm::Function *F,
- uintptr_t &ActualSize);
-
- // This method is called by the JIT to allocate space for a function stub
- // (used to handle limited branch displacements) while it is JIT compiling a
- // function. For example, if foo calls bar, and if bar either needs to be
- // lazily compiled or is a native function that exists too far away from the
- // call site to work, this method will be used to make a thunk for it. The
- // stub should be "close" to the current function body, but should not be
- // included in the 'actualsize' returned by startFunctionBody.
- virtual uint8_t *allocateStub(const llvm::GlobalValue *F,
- unsigned StubSize,
- unsigned Alignment) {
- return allocateSGMemory(StubSize, Alignment);
- }
-
- // This method is called when the JIT is done codegen'ing the specified
- // function. At this point we know the size of the JIT compiled function.
- // This passes in FunctionStart (which was returned by the startFunctionBody
- // method) and FunctionEnd which is a pointer to the actual end of the
- // function. This method should mark the space allocated and remember where
- // it is in case the client wants to deallocate it.
- virtual void endFunctionBody(const llvm::Function *F,
- uint8_t *FunctionStart,
- uint8_t *FunctionEnd);
-
- // Allocate a (function code) memory block of the given size. This method
- // cannot be called between calls to startFunctionBody and endFunctionBody.
- virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
-
- // Allocate memory for a global variable.
- virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
-
- // Free the specified function body. The argument must be the return value
- // from a call to startFunctionBody() that hasn't been deallocated yet. This
- // is never called when the JIT is currently emitting a function.
- virtual void deallocateFunctionBody(void *Body);
-
- // When we finished JITing the function, if exception handling is set, we
- // emit the exception table.
- virtual uint8_t *startExceptionTable(const llvm::Function *F,
- uintptr_t &ActualSize) {
- bccAssert(false &&
- "Exception is not allowed in our language specification");
- return NULL;
- }
-
- // This method is called when the JIT is done emitting the exception table.
- virtual void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t *FrameRegister) {
- bccAssert(false &&
- "Exception is not allowed in our language specification");
- }
-
- // Free the specified exception table's memory. The argument must be the
- // return value from a call to startExceptionTable() that hasn't been
- // deallocated yet. This is never called when the JIT is currently emitting
- // an exception table.
- virtual void deallocateExceptionTable(void *ET) {
- bccAssert(false &&
- "Exception is not allowed in our language specification");
- }
-
- // Below are the methods we create
- void reset();
-
-
- private:
- intptr_t getFreeCodeMemSize() const {
- return mCurSGMemIdx - mCurFuncMemIdx;
- }
-
- uint8_t *allocateSGMemory(uintptr_t Size,
- unsigned Alignment = 1 /* no alignment */);
-
- uintptr_t getFreeGVMemSize() const {
- return MaxGlobalVarSize - mCurGVMemIdx;
- }
-
- uint8_t *getGVMemBase() const {
- return reinterpret_cast<uint8_t*>(mpGVMem);
- }
-
- };
-
-} // namespace bcc
-
-#endif // BCC_CODEMEMORYMANAGER_H
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index 2e2a4fa..c015bcc 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -27,34 +27,15 @@
FileHandle.cpp \
GDBJIT.cpp \
GDBJITRegistrar.cpp \
+ MCCacheWriter.cpp \
+ MCCacheReader.cpp \
Runtime.c \
RuntimeStub.c \
Script.cpp \
- ScriptCompiled.cpp \
- SourceInfo.cpp
-
-ifeq ($(libbcc_USE_OLD_JIT),1)
-libbcc_executionengine_SRC_FILES += \
- OldJIT/ContextManager.cpp
-endif
-
-ifeq ($(libbcc_USE_CACHE),1)
-ifeq ($(libbcc_USE_OLD_JIT),1)
-libbcc_executionengine_SRC_FILES += \
- OldJIT/CacheReader.cpp \
- OldJIT/CacheWriter.cpp
-endif
-
-ifeq ($(libbcc_USE_MCJIT),1)
-libbcc_executionengine_SRC_FILES += \
- MCCacheWriter.cpp \
- MCCacheReader.cpp
-endif
-
-libbcc_executionengine_SRC_FILES += \
ScriptCached.cpp \
- Sha1Helper.cpp
-endif
+ ScriptCompiled.cpp \
+ Sha1Helper.cpp \
+ SourceInfo.cpp
#=====================================================================
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index e7bdd52..8a55e38 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -19,10 +19,6 @@
#include "Config.h"
#include <bcinfo/MetadataExtractor.h>
-#if USE_OLD_JIT
-#include "OldJIT/ContextManager.h"
-#endif
-
#if USE_DISASSEMBLER
#include "Disassembler/Disassembler.h"
#endif
@@ -34,9 +30,7 @@
#include "Sha1Helper.h"
#include "CompilerOption.h"
-#if USE_MCJIT
#include "librsloader.h"
-#endif
#include "Transforms/BCCTransforms.h"
@@ -210,12 +204,10 @@
// Register the scheduler
llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
-#if USE_CACHE
// Read in SHA1 checksum of libbcc and libRS.
readSHA1(sha1LibBCC_SHA1, sizeof(sha1LibBCC_SHA1), pathLibBCC_SHA1);
calcFileSHA1(sha1LibRS, pathLibRS);
-#endif
GlobalInitialized = true;
}
@@ -229,27 +221,9 @@
}
-#if USE_OLD_JIT
-CodeMemoryManager *Compiler::createCodeMemoryManager() {
- mCodeMemMgr.reset(new CodeMemoryManager());
- return mCodeMemMgr.get();
-}
-#endif
-
-
-#if USE_OLD_JIT
-CodeEmitter *Compiler::createCodeEmitter() {
- mCodeEmitter.reset(new CodeEmitter(mpResult, mCodeMemMgr.get()));
- return mCodeEmitter.get();
-}
-#endif
-
-
Compiler::Compiler(ScriptCompiled *result)
: mpResult(result),
-#if USE_MCJIT
mRSExecutable(NULL),
-#endif
mpSymbolLookupFn(NULL),
mpSymbolLookupContext(NULL),
mModule(NULL),
@@ -413,14 +387,6 @@
}
// Perform code generation
-#if USE_OLD_JIT
- if (runCodeGen(new llvm::TargetData(*TD), TM,
- ExportVarMetadata, ExportFuncMetadata) != 0) {
- goto on_bcc_compile_error;
- }
-#endif
-
-#if USE_MCJIT
if (runMCCodeGen(new llvm::TargetData(*TD), TM) != 0) {
goto on_bcc_compile_error;
}
@@ -468,7 +434,7 @@
}
}
-#if DEBUG_MCJIT_DISASSEMBLER
+#if DEBUG_MC_DISASSEMBLER
{
// Get MC codegen emitted function name list
size_t func_list_size = rsloaderGetFuncCount(mRSExecutable);
@@ -480,13 +446,12 @@
void *func = rsloaderGetSymbolAddress(mRSExecutable, func_list[i]);
if (func) {
size_t size = rsloaderGetSymbolSize(mRSExecutable, func_list[i]);
- Disassemble(DEBUG_MCJIT_DISASSEMBLER_FILE,
+ Disassemble(DEBUG_MC_DISASSEMBLER_FILE,
Target, TM, func_list[i], (unsigned char const *)func, size);
}
}
}
#endif
-#endif
on_bcc_compile_error:
// ALOGE("on_bcc_compiler_error");
@@ -507,133 +472,6 @@
}
-#if USE_OLD_JIT
-int Compiler::runCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
- llvm::NamedMDNode const *ExportVarMetadata,
- llvm::NamedMDNode const *ExportFuncMetadata) {
- // Create memory manager for creation of code emitter later.
- if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
- setError("Failed to startup memory management for further compilation");
- return 1;
- }
-
- mpResult->mContext = (char *) (mCodeMemMgr.get()->getCodeMemBase());
-
- // Create code emitter
- if (!mCodeEmitter.get()) {
- if (!createCodeEmitter()) {
- setError("Failed to create machine code emitter for compilation");
- return 1;
- }
- } else {
- // Reuse the code emitter
- mCodeEmitter->reset();
- }
-
- mCodeEmitter->setTargetMachine(*TM);
- mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
- mpSymbolLookupContext);
-
- // Create code-gen pass to run the code emitter
- llvm::OwningPtr<llvm::FunctionPassManager> CodeGenPasses(
- new llvm::FunctionPassManager(mModule));
-
- // Add TargetData to code generation pass manager
- CodeGenPasses->add(TD);
-
- // Add code emit passes
- if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
- *mCodeEmitter,
- CodeGenOptLevel)) {
- setError("The machine code emission is not supported on '" + Triple + "'");
- return 1;
- }
-
- // Run the code emitter on every non-declaration function in the module
- CodeGenPasses->doInitialization();
- for (llvm::Module::iterator
- I = mModule->begin(), E = mModule->end(); I != E; I++) {
- if (!I->isDeclaration()) {
- CodeGenPasses->run(*I);
- }
- }
-
- CodeGenPasses->doFinalization();
-
- // Copy the global address mapping from code emitter and remapping
- if (ExportVarMetadata) {
- ScriptCompiled::ExportVarList &varList = mpResult->mExportVars;
-
- for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
- llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
- if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
- llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
- if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
- llvm::StringRef ExportVarName =
- static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
-
- CodeEmitter::global_addresses_const_iterator I, E;
- for (I = mCodeEmitter->global_address_begin(),
- E = mCodeEmitter->global_address_end();
- I != E; I++) {
- if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
- continue;
- if (ExportVarName == I->first->getName()) {
- varList.push_back(I->second);
-#if DEBUG_BCC_REFLECT
- ALOGD("runCodeGen(): Exported VAR: %s @ %p\n", ExportVarName.str().c_str(), I->second);
-#endif
- break;
- }
- }
- if (I != mCodeEmitter->global_address_end())
- continue; // found
-
-#if DEBUG_BCC_REFLECT
- ALOGD("runCodeGen(): Exported VAR: %s @ %p\n",
- ExportVarName.str().c_str(), (void *)0);
-#endif
- }
- }
- // if reaching here, we know the global variable record in metadata is
- // not found. So we make an empty slot
- varList.push_back(NULL);
- }
-
- bccAssert((varList.size() == ExportVarMetadata->getNumOperands()) &&
- "Number of slots doesn't match the number of export variables!");
- }
-
- if (ExportFuncMetadata) {
- ScriptCompiled::ExportFuncList &funcList = mpResult->mExportFuncs;
-
- for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
- llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
- if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
- llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
- if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
- llvm::StringRef ExportFuncName =
- static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
- funcList.push_back(mpResult->lookup(ExportFuncName.str().c_str()));
-#if DEBUG_BCC_REFLECT
- ALOGD("runCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(),
- funcList.back());
-#endif
- }
- }
- }
- }
-
- // Tell code emitter now can release the memory using during the JIT since
- // we have done the code emission
- mCodeEmitter->releaseUnnecessary();
-
- return 0;
-}
-#endif // USE_OLD_JIT
-
-
-#if USE_MCJIT
int Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM) {
// Decorate mEmittedELFExecutable with formatted ostream
llvm::raw_svector_ostream OutSVOS(mEmittedELFExecutable);
@@ -658,7 +496,6 @@
OutSVOS.flush();
return 0;
}
-#endif // USE_MCJIT
int Compiler::runInternalPasses(std::vector<std::string>& Names,
std::vector<uint32_t>& Signatures) {
@@ -804,14 +641,11 @@
}
-#if USE_MCJIT
void *Compiler::getSymbolAddress(char const *name) {
return rsloaderGetSymbolAddress(mRSExecutable, name);
}
-#endif
-#if USE_MCJIT
void *Compiler::resolveSymbolAdapter(void *context, char const *name) {
Compiler *self = reinterpret_cast<Compiler *>(context);
@@ -828,13 +662,10 @@
ALOGE("Unable to resolve symbol: %s\n", name);
return NULL;
}
-#endif
Compiler::~Compiler() {
-#if USE_MCJIT
rsloaderDisposeExec(mRSExecutable);
-#endif
// llvm::llvm_shutdown();
}
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index eebe550..863cda6 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -19,12 +19,9 @@
#include <bcc/bcc.h>
-#include "CodeGen/CodeEmitter.h"
-#include "CodeGen/CodeMemoryManager.h"
+#include <Config.h>
-#if USE_MCJIT
#include "librsloader.h"
-#endif
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
@@ -85,21 +82,11 @@
std::string mError;
-#if USE_OLD_JIT
- // The memory manager for code emitter
- llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
-
- // The CodeEmitter
- llvm::OwningPtr<CodeEmitter> mCodeEmitter;
-#endif
-
-#if USE_MCJIT
- // Compilation buffer for MCJIT
+ // Compilation buffer for MC
llvm::SmallVector<char, 1024> mEmittedELFExecutable;
// Loaded and relocated executable
RSExecRef mRSExecutable;
-#endif
BCCSymbolLookupFn mpSymbolLookupFn;
void *mpSymbolLookupContext;
@@ -126,19 +113,11 @@
mpSymbolLookupContext = pContext;
}
-#if USE_OLD_JIT
- CodeMemoryManager *createCodeMemoryManager();
-
- CodeEmitter *createCodeEmitter();
-#endif
-
-#if USE_MCJIT
void *getSymbolAddress(char const *name);
const llvm::SmallVector<char, 1024> &getELF() const {
return mEmittedELFExecutable;
}
-#endif
int readModule(llvm::Module *module) {
mModule = module;
@@ -167,9 +146,8 @@
int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM);
-#if USE_MCJIT
static void *resolveSymbolAdapter(void *context, char const *name);
-#endif
+
int runInternalPasses(std::vector<std::string>& Names,
std::vector<uint32_t>& Signatures);
diff --git a/lib/ExecutionEngine/MCCacheReader.cpp b/lib/ExecutionEngine/MCCacheReader.cpp
index 5beff88..6005536 100644
--- a/lib/ExecutionEngine/MCCacheReader.cpp
+++ b/lib/ExecutionEngine/MCCacheReader.cpp
@@ -39,8 +39,6 @@
using namespace std;
-
-#if USE_MCJIT
namespace bcc {
MCCacheReader::~MCCacheReader() {
@@ -148,15 +146,15 @@
bool MCCacheReader::checkHeader() {
- if (memcmp(mpHeader->magic, OBCC_MAGIC, 4) != 0) {
+ if (memcmp(mpHeader->magic, MCO_MAGIC, 4) != 0) {
ALOGE("Bad magic word\n");
return false;
}
- if (memcmp(mpHeader->version, OBCC_VERSION, 4) != 0) {
+ if (memcmp(mpHeader->version, MCO_VERSION, 4) != 0) {
mpHeader->version[4 - 1] = '\0'; // ensure c-style string terminated
ALOGI("Cache file format version mismatch: now %s cached %s\n",
- OBCC_VERSION, mpHeader->version);
+ MCO_VERSION, mpHeader->version);
return false;
}
return true;
@@ -242,7 +240,7 @@
bool MCCacheReader::readStringPool() {
- CACHE_READER_READ_SECTION(OBCC_StringPool,
+ CACHE_READER_READ_SECTION(MCO_StringPool,
mpResult->mpStringPoolRaw, str_pool);
char *str_base = reinterpret_cast<char *>(str_pool_raw);
@@ -258,7 +256,7 @@
bool MCCacheReader::checkStringPool() {
- OBCC_StringPool *poolR = mpResult->mpStringPoolRaw;
+ MCO_StringPool *poolR = mpResult->mpStringPoolRaw;
vector<char const *> &pool = mpResult->mStringPool;
// Ensure that every c-style string is ended with '\0'
@@ -274,7 +272,7 @@
bool MCCacheReader::readDependencyTable() {
- CACHE_READER_READ_SECTION(OBCC_DependencyTable, mpCachedDependTable,
+ CACHE_READER_READ_SECTION(MCO_DependencyTable, mpCachedDependTable,
depend_tab);
return true;
}
@@ -297,7 +295,7 @@
uint32_t depType = dep->second.first;
unsigned char const *depSHA1 = dep->second.second;
- OBCC_Dependency *depCached =&mpCachedDependTable->table[i];
+ MCO_Dependency *depCached =&mpCachedDependTable->table[i];
char const *depCachedName = strPool[depCached->res_name_strp_index];
uint32_t depCachedType = depCached->res_type;
unsigned char const *depCachedSHA1 = depCached->sha1;
@@ -337,10 +335,10 @@
}
bool MCCacheReader::readVarNameList() {
- CACHE_READER_READ_SECTION(OBCC_String_Ptr, mpVarNameList, export_var_name_list);
+ CACHE_READER_READ_SECTION(MCO_String_Ptr, mpVarNameList, export_var_name_list);
vector<char const *> const &strPool = mpResult->mStringPool;
- mpResult->mpExportVars = (OBCC_ExportVarList*)
+ mpResult->mpExportVars = (MCO_ExportVarList*)
malloc(sizeof(size_t) +
sizeof(void*) * export_var_name_list_raw->count);
if (!mpResult->mpExportVars) {
@@ -352,7 +350,7 @@
for (size_t i = 0; i < export_var_name_list_raw->count; ++i) {
mpResult->mpExportVars->cached_addr_list[i] =
rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_var_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MCJIT_REFLECT
+#if DEBUG_MC_REFLECT
ALOGD("Get symbol address: %s -> %p",
strPool[export_var_name_list_raw->strp_indexs[i]], mpResult->mpExportVars->cached_addr_list[i]);
#endif
@@ -361,10 +359,10 @@
}
bool MCCacheReader::readFuncNameList() {
- CACHE_READER_READ_SECTION(OBCC_String_Ptr, mpFuncNameList, export_func_name_list);
+ CACHE_READER_READ_SECTION(MCO_String_Ptr, mpFuncNameList, export_func_name_list);
vector<char const *> const &strPool = mpResult->mStringPool;
- mpResult->mpExportFuncs = (OBCC_ExportFuncList*)
+ mpResult->mpExportFuncs = (MCO_ExportFuncList*)
malloc(sizeof(size_t) +
sizeof(void*) * export_func_name_list_raw->count);
if (!mpResult->mpExportFuncs) {
@@ -376,7 +374,7 @@
for (size_t i = 0; i < export_func_name_list_raw->count; ++i) {
mpResult->mpExportFuncs->cached_addr_list[i] =
rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_func_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MCJIT_REFLECT
+#if DEBUG_MC_REFLECT
ALOGD("Get function address: %s -> %p",
strPool[export_func_name_list_raw->strp_indexs[i]], mpResult->mpExportFuncs->cached_addr_list[i]);
#endif
@@ -385,10 +383,10 @@
}
bool MCCacheReader::readForEachNameList() {
- CACHE_READER_READ_SECTION(OBCC_String_Ptr, mpForEachNameList, export_foreach_name_list);
+ CACHE_READER_READ_SECTION(MCO_String_Ptr, mpForEachNameList, export_foreach_name_list);
vector<char const *> const &strPool = mpResult->mStringPool;
- mpResult->mpExportForEach = (OBCC_ExportForEachList*)
+ mpResult->mpExportForEach = (MCO_ExportForEachList*)
malloc(sizeof(size_t) +
sizeof(void*) * export_foreach_name_list_raw->count);
if (!mpResult->mpExportForEach) {
@@ -400,7 +398,7 @@
for (size_t i = 0; i < export_foreach_name_list_raw->count; ++i) {
mpResult->mpExportForEach->cached_addr_list[i] =
rsloaderGetSymbolAddress(mpResult->mRSExecutable, strPool[export_foreach_name_list_raw->strp_indexs[i]]);
-#if DEBUG_MCJIT_REFLECT
+#if DEBUG_MC_REFLECT
ALOGE("Get foreach function address: %s -> %p",
strPool[export_foreach_name_list_raw->strp_indexs[i]], mpResult->mpExportForEach->cached_addr_list[i]);
#endif
@@ -409,13 +407,13 @@
}
bool MCCacheReader::readPragmaList() {
- CACHE_READER_READ_SECTION(OBCC_PragmaList, mpPragmaList, pragma_list);
+ CACHE_READER_READ_SECTION(MCO_PragmaList, mpPragmaList, pragma_list);
vector<char const *> const &strPool = mpResult->mStringPool;
ScriptCached::PragmaList &pragmas = mpResult->mPragmas;
for (size_t i = 0; i < pragma_list_raw->count; ++i) {
- OBCC_Pragma *pragma = &pragma_list_raw->list[i];
+ MCO_Pragma *pragma = &pragma_list_raw->list[i];
pragmas.push_back(make_pair(strPool[pragma->key_strp_index],
strPool[pragma->value_strp_index]));
}
@@ -425,7 +423,7 @@
bool MCCacheReader::readObjectSlotList() {
- CACHE_READER_READ_SECTION(OBCC_ObjectSlotList,
+ CACHE_READER_READ_SECTION(MCO_ObjectSlotList,
mpResult->mpObjectSlotList, object_slot_list);
return true;
}
@@ -484,4 +482,3 @@
}
} // namespace bcc
-#endif
diff --git a/lib/ExecutionEngine/MCCacheReader.h b/lib/ExecutionEngine/MCCacheReader.h
index 1e59111..df4aca3 100644
--- a/lib/ExecutionEngine/MCCacheReader.h
+++ b/lib/ExecutionEngine/MCCacheReader.h
@@ -40,13 +40,13 @@
off_t mInfoFileSize;
MCO_Header *mpHeader;
- OBCC_DependencyTable *mpCachedDependTable;
- OBCC_PragmaList *mpPragmaList;
- OBCC_FuncTable *mpFuncTable;
+ MCO_DependencyTable *mpCachedDependTable;
+ MCO_PragmaList *mpPragmaList;
+ MCO_FuncTable *mpFuncTable;
- OBCC_String_Ptr *mpVarNameList;
- OBCC_String_Ptr *mpFuncNameList;
- OBCC_String_Ptr *mpForEachNameList;
+ MCO_String_Ptr *mpVarNameList;
+ MCO_String_Ptr *mpFuncNameList;
+ MCO_String_Ptr *mpForEachNameList;
llvm::OwningPtr<ScriptCached> mpResult;
@@ -68,7 +68,7 @@
~MCCacheReader();
- void addDependency(OBCC_ResourceType resType,
+ void addDependency(MCO_ResourceType resType,
std::string const &resName,
unsigned char const *sha1) {
mDependencies.insert(std::make_pair(resName,
diff --git a/lib/ExecutionEngine/MCCacheWriter.cpp b/lib/ExecutionEngine/MCCacheWriter.cpp
index cca724e..b0bf117 100644
--- a/lib/ExecutionEngine/MCCacheWriter.cpp
+++ b/lib/ExecutionEngine/MCCacheWriter.cpp
@@ -31,7 +31,6 @@
using namespace std;
-#if USE_MCJIT
namespace bcc {
MCCacheWriter::~MCCacheWriter() {
@@ -88,8 +87,8 @@
memset(header, '\0', sizeof(MCO_Header));
// Magic word and version
- memcpy(header->magic, OBCC_MAGIC, 4);
- memcpy(header->version, OBCC_VERSION, 4);
+ memcpy(header->magic, MCO_MAGIC, 4);
+ memcpy(header->version, MCO_VERSION, 4);
// Machine Integer Type
uint32_t number = 0x00000001;
@@ -107,10 +106,10 @@
bool MCCacheWriter::prepareDependencyTable() {
- size_t tableSize = sizeof(OBCC_DependencyTable) +
- sizeof(OBCC_Dependency) * mDependencies.size();
+ size_t tableSize = sizeof(MCO_DependencyTable) +
+ sizeof(MCO_Dependency) * mDependencies.size();
- OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
+ MCO_DependencyTable *tab = (MCO_DependencyTable *)malloc(tableSize);
if (!tab) {
ALOGE("Unable to allocate for dependency table section.\n");
@@ -125,7 +124,7 @@
size_t i = 0;
for (map<string, pair<uint32_t, unsigned char const *> >::iterator
I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
- OBCC_Dependency *dep = &tab->table[i];
+ MCO_Dependency *dep = &tab->table[i];
dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
dep->res_type = I->second.first;
@@ -138,10 +137,10 @@
bool MCCacheWriter::preparePragmaList() {
size_t pragmaCount = mpOwner->getPragmaCount();
- size_t listSize = sizeof(OBCC_PragmaList) +
- sizeof(OBCC_Pragma) * pragmaCount;
+ size_t listSize = sizeof(MCO_PragmaList) +
+ sizeof(MCO_Pragma) * pragmaCount;
- OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
+ MCO_PragmaList *list = (MCO_PragmaList *)malloc(listSize);
if (!list) {
ALOGE("Unable to allocate for pragma list\n");
@@ -164,7 +163,7 @@
size_t keyLen = strlen(key);
size_t valueLen = strlen(value);
- OBCC_Pragma *pragma = &list->list[i];
+ MCO_Pragma *pragma = &list->list[i];
pragma->key_strp_index = addString(key, keyLen);
pragma->value_strp_index = addString(value, valueLen);
}
@@ -174,8 +173,8 @@
bool MCCacheWriter::prepareStringPool() {
// Calculate string pool size
- size_t size = sizeof(OBCC_StringPool) +
- sizeof(OBCC_String) * mStringPool.size();
+ size_t size = sizeof(MCO_StringPool) +
+ sizeof(MCO_String) * mStringPool.size();
off_t strOffset = size;
@@ -184,7 +183,7 @@
}
// Create string pool
- OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
+ MCO_StringPool *pool = (MCO_StringPool *)malloc(size);
if (!pool) {
ALOGE("Unable to allocate string pool.\n");
@@ -199,7 +198,7 @@
char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
for (size_t i = 0; i < mStringPool.size(); ++i) {
- OBCC_String *str = &pool->list[i];
+ MCO_String *str = &pool->list[i];
str->length = mStringPool[i].second;
str->offset = strOffset;
@@ -217,9 +216,9 @@
bool MCCacheWriter::prepareExportVarNameList() {
size_t varCount = mpOwner->getExportVarCount();
- size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * varCount;
+ size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * varCount;
- OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
+ MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
if (!list) {
ALOGE("Unable to allocate for export variable name list\n");
@@ -241,9 +240,9 @@
bool MCCacheWriter::prepareExportFuncNameList() {
size_t funcCount = mpOwner->getExportFuncCount();
- size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * funcCount;
+ size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * funcCount;
- OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
+ MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
if (!list) {
ALOGE("Unable to allocate for export function name list\n");
@@ -265,9 +264,9 @@
bool MCCacheWriter::prepareExportForEachNameList() {
size_t forEachCount = mpOwner->getExportForEachCount();
- size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * forEachCount;
+ size_t listSize = sizeof(MCO_String_Ptr) + sizeof(size_t) * forEachCount;
- OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
+ MCO_String_Ptr *list = (MCO_String_Ptr*)malloc(listSize);
if (!list) {
ALOGE("Unable to allocate for export forEach name list\n");
@@ -290,10 +289,10 @@
bool MCCacheWriter::prepareObjectSlotList() {
size_t objectSlotCount = mpOwner->getObjectSlotCount();
- size_t listSize = sizeof(OBCC_ObjectSlotList) +
+ size_t listSize = sizeof(MCO_ObjectSlotList) +
sizeof(uint32_t) * objectSlotCount;
- OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
+ MCO_ObjectSlotList *list = (MCO_ObjectSlotList *)malloc(listSize);
if (!list) {
ALOGE("Unable to allocate for object slot list\n");
@@ -387,4 +386,3 @@
}
} // namespace bcc
-#endif
diff --git a/lib/ExecutionEngine/MCCacheWriter.h b/lib/ExecutionEngine/MCCacheWriter.h
index 58f6ef5..b2bcb12 100644
--- a/lib/ExecutionEngine/MCCacheWriter.h
+++ b/lib/ExecutionEngine/MCCacheWriter.h
@@ -41,14 +41,14 @@
std::pair<uint32_t, unsigned char const *> > mDependencies;
MCO_Header *mpHeaderSection;
- OBCC_StringPool *mpStringPoolSection;
- OBCC_DependencyTable *mpDependencyTableSection;
- OBCC_PragmaList *mpPragmaListSection;
- OBCC_ObjectSlotList *mpObjectSlotSection;
+ MCO_StringPool *mpStringPoolSection;
+ MCO_DependencyTable *mpDependencyTableSection;
+ MCO_PragmaList *mpPragmaListSection;
+ MCO_ObjectSlotList *mpObjectSlotSection;
- OBCC_String_Ptr *mpExportVarNameListSection;
- OBCC_String_Ptr *mpExportFuncNameListSection;
- OBCC_String_Ptr *mpExportForEachNameListSection;
+ MCO_String_Ptr *mpExportVarNameListSection;
+ MCO_String_Ptr *mpExportFuncNameListSection;
+ MCO_String_Ptr *mpExportForEachNameListSection;
std::vector<std::string> varNameList;
std::vector<std::string> funcNameList;
@@ -66,7 +66,7 @@
bool writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
Script *S, uint32_t libRS_threadable);
- void addDependency(OBCC_ResourceType resType,
+ void addDependency(MCO_ResourceType resType,
std::string const &resName,
unsigned char const *sha1) {
mDependencies.insert(std::make_pair(resName,
diff --git a/lib/ExecutionEngine/OldJIT/CacheReader.cpp b/lib/ExecutionEngine/OldJIT/CacheReader.cpp
deleted file mode 100644
index 8eceb5f..0000000
--- a/lib/ExecutionEngine/OldJIT/CacheReader.cpp
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "CacheReader.h"
-
-#include "ContextManager.h"
-#include "DebugHelper.h"
-#include "FileHandle.h"
-#include "ScriptCached.h"
-
-#include <bcc/bcc_cache.h>
-
-#include <llvm/ADT/OwningPtr.h>
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <utility>
-#include <vector>
-
-#include <new>
-
-#include <stdlib.h>
-#include <string.h>
-
-using namespace std;
-
-
-namespace bcc {
-
-CacheReader::~CacheReader() {
- if (mpHeader) { free(mpHeader); }
- if (mpCachedDependTable) { free(mpCachedDependTable); }
- if (mpPragmaList) { free(mpPragmaList); }
- if (mpFuncTable) { free(mpFuncTable); }
-}
-
-ScriptCached *CacheReader::readCacheFile(FileHandle *objFile,
- FileHandle *infoFile,
- Script *S) {
- // Check file handle
- if (!objFile || objFile->getFD() < 0 ||
- !infoFile || infoFile->getFD() < 0) {
- return NULL;
- }
-
- mObjFile = objFile;
- mInfoFile = infoFile;
-
- // Allocate ScriptCached object
- mpResult.reset(new (nothrow) ScriptCached(S));
-
- if (!mpResult) {
- ALOGE("Unable to allocate ScriptCached object.\n");
- return NULL;
- }
-
- bool result = checkFileSize()
- && readHeader()
- && checkHeader()
- && checkMachineIntType()
- && checkSectionOffsetAndSize()
- && readStringPool()
- && checkStringPool()
- && readDependencyTable()
- && checkDependency()
- && readExportVarList()
- && readExportFuncList()
- && readPragmaList()
- && readFuncTable()
- && readObjectSlotList()
- && readContext()
- && checkContext()
- //&& readRelocationTable()
- //&& relocate()
- ;
-
- return result ? mpResult.take() : NULL;
-}
-
-
-bool CacheReader::checkFileSize() {
- struct stat stfile;
-
- if (fstat(mInfoFile->getFD(), &stfile) < 0) {
- ALOGE("Unable to stat metadata information file.\n");
- return false;
- }
-
- mInfoFileSize = stfile.st_size;
-
- if (mInfoFileSize < (off_t)sizeof(OBCC_Header)) {
- ALOGE("Metadata information file is too small to be correct.\n");
- return false;
- }
-
- if (fstat(mObjFile->getFD(), &stfile) < 0) {
- ALOGE("Unable to stat executable file.\n");
- return false;
- }
-
- if (stfile.st_size < (off_t)ContextManager::ContextSize) {
- ALOGE("Executable file is too small to be correct.\n");
- return false;
- }
-
- return true;
-}
-
-
-bool CacheReader::readHeader() {
- if (mInfoFile->seek(0, SEEK_SET) != 0) {
- ALOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
- return false;
- }
-
- mpHeader = (OBCC_Header *)malloc(sizeof(OBCC_Header));
- if (!mpHeader) {
- ALOGE("Unable to allocate for cache header.\n");
- return false;
- }
-
- if (mInfoFile->read((char *)mpHeader, sizeof(OBCC_Header)) !=
- (ssize_t)sizeof(OBCC_Header)) {
- ALOGE("Unable to read cache header.\n");
- return false;
- }
-
- // Dirty hack for libRS.
- // TODO(all): This should be removed in the future.
- if (mpHeader->libRS_threadable) {
- mpResult->mLibRSThreadable = true;
- }
-
- return true;
-}
-
-
-bool CacheReader::checkHeader() {
- if (memcmp(mpHeader->magic, OBCC_MAGIC, 4) != 0) {
- ALOGE("Bad magic word\n");
- return false;
- }
-
- if (memcmp(mpHeader->version, OBCC_VERSION, 4) != 0) {
- mpHeader->version[4 - 1] = '\0'; // ensure c-style string terminated
- ALOGI("Cache file format version mismatch: now %s cached %s\n",
- OBCC_VERSION, mpHeader->version);
- return false;
- }
- return true;
-}
-
-
-bool CacheReader::checkMachineIntType() {
- uint32_t number = 0x00000001;
-
- bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
- if ((isLittleEndian && mpHeader->endianness != 'e') ||
- (!isLittleEndian && mpHeader->endianness != 'E')) {
- ALOGE("Machine endianness mismatch.\n");
- return false;
- }
-
- if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
- (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
- (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
- ALOGE("Machine integer size mismatch.\n");
- return false;
- }
-
- return true;
-}
-
-
-bool CacheReader::checkSectionOffsetAndSize() {
-#define CHECK_SECTION_OFFSET(NAME) \
- do { \
- off_t offset = mpHeader-> NAME##_offset; \
- off_t size = (off_t)mpHeader-> NAME##_size; \
- \
- if (mInfoFileSize < offset || mInfoFileSize < offset + size) { \
- ALOGE(#NAME " section overflow.\n"); \
- return false; \
- } \
- \
- if (offset % sizeof(int) != 0) { \
- ALOGE(#NAME " offset must aligned to %d.\n", (int)sizeof(int)); \
- return false; \
- } \
- \
- if (size < static_cast<off_t>(sizeof(size_t))) { \
- ALOGE(#NAME " size is too small to be correct.\n"); \
- return false; \
- } \
- } while (0)
-
- CHECK_SECTION_OFFSET(str_pool);
- CHECK_SECTION_OFFSET(depend_tab);
- //CHECK_SECTION_OFFSET(reloc_tab);
- CHECK_SECTION_OFFSET(export_var_list);
- CHECK_SECTION_OFFSET(export_func_list);
- CHECK_SECTION_OFFSET(pragma_list);
-
-#undef CHECK_SECTION_OFFSET
-
- // TODO(logan): Move this to some where else.
- long pagesize = sysconf(_SC_PAGESIZE);
- if ((uintptr_t)mpHeader->context_cached_addr % pagesize != 0) {
- ALOGE("cached address is not aligned to pagesize.\n");
- return false;
- }
-
- return true;
-}
-
-
-#define CACHE_READER_READ_SECTION(TYPE, AUTO_MANAGED_HOLDER, NAME) \
- TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size); \
- \
- if (!NAME##_raw) { \
- ALOGE("Unable to allocate for " #NAME "\n"); \
- return false; \
- } \
- \
- /* We have to ensure that some one will deallocate NAME##_raw */ \
- AUTO_MANAGED_HOLDER = NAME##_raw; \
- \
- if (mInfoFile->seek(mpHeader->NAME##_offset, SEEK_SET) == -1) { \
- ALOGE("Unable to seek to " #NAME " section\n"); \
- return false; \
- } \
- \
- if (mInfoFile->read(reinterpret_cast<char *>(NAME##_raw), \
- mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
- { \
- ALOGE("Unable to read " #NAME ".\n"); \
- return false; \
- }
-
-
-bool CacheReader::readStringPool() {
- CACHE_READER_READ_SECTION(OBCC_StringPool,
- mpResult->mpStringPoolRaw, str_pool);
-
- char *str_base = reinterpret_cast<char *>(str_pool_raw);
-
- vector<char const *> &pool = mpResult->mStringPool;
- for (size_t i = 0; i < str_pool_raw->count; ++i) {
- char *str = str_base + str_pool_raw->list[i].offset;
- pool.push_back(str);
- }
-
- return true;
-}
-
-
-bool CacheReader::checkStringPool() {
- OBCC_StringPool *poolR = mpResult->mpStringPoolRaw;
- vector<char const *> &pool = mpResult->mStringPool;
-
- // Ensure that every c-style string is ended with '\0'
- for (size_t i = 0; i < poolR->count; ++i) {
- if (pool[i][poolR->list[i].length] != '\0') {
- ALOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
- return false;
- }
- }
-
- return true;
-}
-
-
-bool CacheReader::readDependencyTable() {
- CACHE_READER_READ_SECTION(OBCC_DependencyTable, mpCachedDependTable,
- depend_tab);
- return true;
-}
-
-
-bool CacheReader::checkDependency() {
- if (mDependencies.size() != mpCachedDependTable->count) {
- ALOGE("Dependencies count mismatch. (%lu vs %lu)\n",
- (unsigned long)mDependencies.size(),
- (unsigned long)mpCachedDependTable->count);
- return false;
- }
-
- vector<char const *> &strPool = mpResult->mStringPool;
- map<string, pair<uint32_t, unsigned char const *> >::iterator dep;
-
- dep = mDependencies.begin();
- for (size_t i = 0; i < mpCachedDependTable->count; ++i, ++dep) {
- string const &depName = dep->first;
- uint32_t depType = dep->second.first;
- unsigned char const *depSHA1 = dep->second.second;
-
- OBCC_Dependency *depCached =&mpCachedDependTable->table[i];
- char const *depCachedName = strPool[depCached->res_name_strp_index];
- uint32_t depCachedType = depCached->res_type;
- unsigned char const *depCachedSHA1 = depCached->sha1;
-
- if (depName != depCachedName) {
- ALOGE("Cache dependency name mismatch:\n");
- ALOGE(" given: %s\n", depName.c_str());
- ALOGE(" cached: %s\n", depCachedName);
-
- return false;
- }
-
- if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
- ALOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
-
-#define PRINT_SHA1(PREFIX, X, POSTFIX) \
- ALOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
- X[0], X[1], X[2], X[3], X[4], X[5], X[6], X[7], X[8], X[9], \
- X[10],X[11],X[12],X[13],X[14],X[15],X[16],X[17],X[18],X[19]);
-
- PRINT_SHA1(" given: ", depSHA1, "\n");
- PRINT_SHA1(" cached: ", depCachedSHA1, "\n");
-
-#undef PRINT_SHA1
-
- return false;
- }
-
- if (depType != depCachedType) {
- ALOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
- return false;
- }
- }
-
- return true;
-}
-
-bool CacheReader::readExportVarList() {
- CACHE_READER_READ_SECTION(OBCC_ExportVarList,
- mpResult->mpExportVars, export_var_list);
- return true;
-}
-
-
-bool CacheReader::readExportFuncList() {
- CACHE_READER_READ_SECTION(OBCC_ExportFuncList,
- mpResult->mpExportFuncs, export_func_list);
- return true;
-}
-
-
-bool CacheReader::readPragmaList() {
- CACHE_READER_READ_SECTION(OBCC_PragmaList, mpPragmaList, pragma_list);
-
- vector<char const *> const &strPool = mpResult->mStringPool;
- ScriptCached::PragmaList &pragmas = mpResult->mPragmas;
-
- for (size_t i = 0; i < pragma_list_raw->count; ++i) {
- OBCC_Pragma *pragma = &pragma_list_raw->list[i];
- pragmas.push_back(make_pair(strPool[pragma->key_strp_index],
- strPool[pragma->value_strp_index]));
- }
-
- return true;
-}
-
-
-bool CacheReader::readObjectSlotList() {
- CACHE_READER_READ_SECTION(OBCC_ObjectSlotList,
- mpResult->mpObjectSlotList, object_slot_list);
- return true;
-}
-
-
-bool CacheReader::readFuncTable() {
- CACHE_READER_READ_SECTION(OBCC_FuncTable, mpFuncTable, func_table);
-
- vector<char const *> &strPool = mpResult->mStringPool;
- ScriptCached::FuncTable &table = mpResult->mFunctions;
- for (size_t i = 0; i < func_table_raw->count; ++i) {
- OBCC_FuncInfo *func = &func_table_raw->table[i];
- table.insert(make_pair(strPool[func->name_strp_index],
- make_pair(func->cached_addr, func->size)));
- }
-
- return true;
-}
-
-#undef CACHE_READER_READ_SECTION
-
-
-bool CacheReader::readContext() {
- mpResult->mContext =
- ContextManager::get().allocateContext(mpHeader->context_cached_addr,
- mObjFile->getFD(), 0);
-
- if (!mpResult->mContext) {
- // Unable to allocate at cached address. Give up.
- mIsContextSlotNotAvail = true;
- return false;
-
- // TODO(logan): If relocation is fixed, we should try to allocate the
- // code in different location, and relocate the context.
- }
-
- return true;
-}
-
-
-bool CacheReader::checkContext() {
- uint32_t sum = mpHeader->context_parity_checksum;
- uint32_t *ptr = reinterpret_cast<uint32_t *>(mpResult->mContext);
-
- for (size_t i = 0; i < ContextManager::ContextSize / sizeof(uint32_t); ++i) {
- sum ^= *ptr++;
- }
-
- if (sum != 0) {
- ALOGE("Checksum check failed\n");
- return false;
- }
-
- ALOGI("Passed checksum even parity verification.\n");
- return true;
-}
-
-
-bool CacheReader::readRelocationTable() {
- // TODO(logan): Not finished.
- return true;
-}
-
-
-bool CacheReader::relocate() {
- // TODO(logan): Not finished.
- return true;
-}
-
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/OldJIT/CacheReader.h b/lib/ExecutionEngine/OldJIT/CacheReader.h
deleted file mode 100644
index a208ed6..0000000
--- a/lib/ExecutionEngine/OldJIT/CacheReader.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_CACHEREADER_H
-#define BCC_CACHEREADER_H
-
-#include "ScriptCached.h"
-
-#include <llvm/ADT/OwningPtr.h>
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include <stddef.h>
-#include <stdint.h>
-
-struct OBCC_Header;
-
-namespace bcc {
- class FileHandle;
- class Script;
-
- class CacheReader {
- private:
- FileHandle *mObjFile;
- FileHandle *mInfoFile;
- off_t mInfoFileSize;
-
- OBCC_Header *mpHeader;
- OBCC_DependencyTable *mpCachedDependTable;
- OBCC_PragmaList *mpPragmaList;
- OBCC_FuncTable *mpFuncTable;
-
- llvm::OwningPtr<ScriptCached> mpResult;
-
- std::map<std::string,
- std::pair<uint32_t, unsigned char const *> > mDependencies;
-
- bool mIsContextSlotNotAvail;
-
- public:
- CacheReader()
- : mObjFile(NULL), mInfoFile(NULL), mInfoFileSize(0), mpHeader(NULL),
- mpCachedDependTable(NULL), mpPragmaList(NULL), mpFuncTable(NULL),
- mIsContextSlotNotAvail(false) {
- }
-
- ~CacheReader();
-
- void addDependency(OBCC_ResourceType resType,
- std::string const &resName,
- unsigned char const *sha1) {
- mDependencies.insert(std::make_pair(resName,
- std::make_pair((uint32_t)resType, sha1)));
- }
-
- ScriptCached *readCacheFile(FileHandle *objFile,
- FileHandle *infoFile,
- Script *s);
-
- bool isContextSlotNotAvail() const {
- return mIsContextSlotNotAvail;
- }
-
- private:
- bool readHeader();
- bool readStringPool();
- bool readDependencyTable();
- bool readExportVarList();
- bool readExportFuncList();
- bool readPragmaList();
- bool readFuncTable();
- bool readObjectSlotList();
- bool readContext();
- bool readRelocationTable();
-
- bool checkFileSize();
- bool checkHeader();
- bool checkMachineIntType();
- bool checkSectionOffsetAndSize();
- bool checkStringPool();
- bool checkDependency();
- bool checkContext();
-
- bool relocate();
- };
-
-} // namespace bcc
-
-#endif // BCC_CACHEREADER_H
diff --git a/lib/ExecutionEngine/OldJIT/CacheWriter.cpp b/lib/ExecutionEngine/OldJIT/CacheWriter.cpp
deleted file mode 100644
index 36bf281..0000000
--- a/lib/ExecutionEngine/OldJIT/CacheWriter.cpp
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "CacheWriter.h"
-
-#include "ContextManager.h"
-#include "DebugHelper.h"
-#include "FileHandle.h"
-#include "Script.h"
-
-#include <map>
-#include <string>
-#include <vector>
-#include <utility>
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-using namespace std;
-
-namespace bcc {
-
-CacheWriter::~CacheWriter() {
-#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
-
- CHECK_AND_FREE(mpHeaderSection);
- CHECK_AND_FREE(mpStringPoolSection);
- CHECK_AND_FREE(mpDependencyTableSection);
- //CHECK_AND_FREE(mpRelocationTableSection);
- CHECK_AND_FREE(mpExportVarListSection);
- CHECK_AND_FREE(mpExportFuncListSection);
- CHECK_AND_FREE(mpPragmaListSection);
- CHECK_AND_FREE(mpFuncTableSection);
- CHECK_AND_FREE(mpObjectSlotSection);
-
-#undef CHECK_AND_FREE
-}
-
-bool CacheWriter::writeCacheFile(FileHandle *objFile,
- FileHandle *infoFile,
- Script *S,
- uint32_t libRS_threadable) {
- if (!objFile || objFile->getFD() < 0 ||
- !infoFile || infoFile->getFD() < 0) {
- return false;
- }
-
- mObjFile = objFile;
- mInfoFile = infoFile;
- mpOwner = S;
-
- bool result = prepareHeader(libRS_threadable)
- && prepareDependencyTable()
- && prepareFuncTable()
- && preparePragmaList()
- //&& prepareRelocationTable()
- && prepareStringPool()
- && prepareExportVarList()
- && prepareExportFuncList()
- && prepareObjectSlotList()
- && calcSectionOffset()
- && calcContextChecksum()
- && writeAll()
- ;
-
- return result;
-}
-
-
-bool CacheWriter::prepareHeader(uint32_t libRS_threadable) {
- OBCC_Header *header = (OBCC_Header *)malloc(sizeof(OBCC_Header));
-
- if (!header) {
- ALOGE("Unable to allocate for header.\n");
- return false;
- }
-
- mpHeaderSection = header;
-
- // Initialize
- memset(header, '\0', sizeof(OBCC_Header));
-
- // Magic word and version
- memcpy(header->magic, OBCC_MAGIC, 4);
- memcpy(header->version, OBCC_VERSION, 4);
-
- // Machine Integer Type
- uint32_t number = 0x00000001;
- header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
- header->sizeof_off_t = sizeof(off_t);
- header->sizeof_size_t = sizeof(size_t);
- header->sizeof_ptr_t = sizeof(void *);
-
- // Context
- header->context_cached_addr = mpOwner->getContext();
-
- // libRS is threadable dirty hack
- // TODO: This should be removed in the future
- header->libRS_threadable = libRS_threadable;
-
- return true;
-}
-
-
-bool CacheWriter::prepareDependencyTable() {
- size_t tableSize = sizeof(OBCC_DependencyTable) +
- sizeof(OBCC_Dependency) * mDependencies.size();
-
- OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
-
- if (!tab) {
- ALOGE("Unable to allocate for dependency table section.\n");
- return false;
- }
-
- mpDependencyTableSection = tab;
- mpHeaderSection->depend_tab_size = tableSize;
-
- tab->count = mDependencies.size();
-
- size_t i = 0;
- for (map<string, pair<uint32_t, unsigned char const *> >::iterator
- I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
- OBCC_Dependency *dep = &tab->table[i];
-
- dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
- dep->res_type = I->second.first;
- memcpy(dep->sha1, I->second.second, 20);
- }
-
- return true;
-}
-
-
-bool CacheWriter::prepareFuncTable() {
- size_t funcCount = mpOwner->getFuncCount();
-
- size_t tableSize = sizeof(OBCC_FuncTable) +
- sizeof(OBCC_FuncInfo) * funcCount;
-
- OBCC_FuncTable *tab = (OBCC_FuncTable *)malloc(tableSize);
-
- if (!tab) {
- ALOGE("Unable to allocate for function table section.\n");
- return false;
- }
-
- mpFuncTableSection = tab;
- mpHeaderSection->func_table_size = tableSize;
-
- tab->count = static_cast<size_t>(funcCount);
-
- // Get the function informations
- vector<FuncInfo> funcInfoList(funcCount);
- mpOwner->getFuncInfoList(funcCount, &*funcInfoList.begin());
-
- for (size_t i = 0; i < funcCount; ++i) {
- FuncInfo *info = &funcInfoList[i];
- OBCC_FuncInfo *outputInfo = &tab->table[i];
-
- outputInfo->name_strp_index = addString(info->name, strlen(info->name));
- outputInfo->cached_addr = info->addr;
- outputInfo->size = info->size;
- }
-
- return true;
-}
-
-
-bool CacheWriter::preparePragmaList() {
- size_t pragmaCount = mpOwner->getPragmaCount();
-
- size_t listSize = sizeof(OBCC_PragmaList) +
- sizeof(OBCC_Pragma) * pragmaCount;
-
- OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for pragma list\n");
- return false;
- }
-
- mpPragmaListSection = list;
- mpHeaderSection->pragma_list_size = listSize;
-
- list->count = pragmaCount;
-
- vector<char const *> keyList(pragmaCount);
- vector<char const *> valueList(pragmaCount);
- mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
-
- for (size_t i = 0; i < pragmaCount; ++i) {
- char const *key = keyList[i];
- char const *value = valueList[i];
-
- size_t keyLen = strlen(key);
- size_t valueLen = strlen(value);
-
- OBCC_Pragma *pragma = &list->list[i];
- pragma->key_strp_index = addString(key, keyLen);
- pragma->value_strp_index = addString(value, valueLen);
- }
-
- return true;
-}
-
-
-bool CacheWriter::prepareRelocationTable() {
- // TODO(logan): Implement relocation table cache write.
- return false;
-}
-
-
-bool CacheWriter::prepareStringPool() {
- // Calculate string pool size
- size_t size = sizeof(OBCC_StringPool) +
- sizeof(OBCC_String) * mStringPool.size();
-
- off_t strOffset = size;
-
- for (size_t i = 0; i < mStringPool.size(); ++i) {
- size += mStringPool[i].second + 1;
- }
-
- // Create string pool
- OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
-
- if (!pool) {
- ALOGE("Unable to allocate string pool.\n");
- return false;
- }
-
- mpStringPoolSection = pool;
- mpHeaderSection->str_pool_size = size;
-
- pool->count = mStringPool.size();
-
- char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
-
- for (size_t i = 0; i < mStringPool.size(); ++i) {
- OBCC_String *str = &pool->list[i];
-
- str->length = mStringPool[i].second;
- str->offset = strOffset;
- memcpy(strPtr, mStringPool[i].first, str->length);
-
- strPtr += str->length;
- *strPtr++ = '\0';
-
- strOffset += str->length + 1;
- }
-
- return true;
-}
-
-
-bool CacheWriter::prepareExportVarList() {
- size_t varCount = mpOwner->getExportVarCount();
- size_t listSize = sizeof(OBCC_ExportVarList) + sizeof(void *) * varCount;
-
- OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for export variable list\n");
- return false;
- }
-
- mpExportVarListSection = list;
- mpHeaderSection->export_var_list_size = listSize;
-
- list->count = static_cast<size_t>(varCount);
-
- mpOwner->getExportVarList(varCount, list->cached_addr_list);
- return true;
-}
-
-
-bool CacheWriter::prepareExportFuncList() {
- size_t funcCount = mpOwner->getExportFuncCount();
- size_t listSize = sizeof(OBCC_ExportFuncList) + sizeof(void *) * funcCount;
-
- OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for export function list\n");
- return false;
- }
-
- mpExportFuncListSection = list;
- mpHeaderSection->export_func_list_size = listSize;
-
- list->count = static_cast<size_t>(funcCount);
-
- mpOwner->getExportFuncList(funcCount, list->cached_addr_list);
- return true;
-}
-
-
-bool CacheWriter::prepareObjectSlotList() {
- size_t objectSlotCount = mpOwner->getObjectSlotCount();
-
- size_t listSize = sizeof(OBCC_ObjectSlotList) +
- sizeof(uint32_t) * objectSlotCount;
-
- OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
-
- if (!list) {
- ALOGE("Unable to allocate for object slot list\n");
- return false;
- }
-
- mpObjectSlotSection = list;
- mpHeaderSection->object_slot_list_size = listSize;
-
- list->count = objectSlotCount;
-
- mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
- return true;
-}
-
-
-bool CacheWriter::calcSectionOffset() {
- size_t offset = sizeof(OBCC_Header);
-
-#define OFFSET_INCREASE(NAME) \
- do { \
- /* Align to a word */ \
- size_t rem = offset % sizeof(int); \
- if (rem > 0) { \
- offset += sizeof(int) - rem; \
- } \
- \
- /* Save the offset and increase it */ \
- mpHeaderSection->NAME##_offset = offset; \
- offset += mpHeaderSection->NAME##_size; \
- } while (0)
-
- OFFSET_INCREASE(str_pool);
- OFFSET_INCREASE(depend_tab);
- //OFFSET_INCREASE(reloc_tab);
- OFFSET_INCREASE(export_var_list);
- OFFSET_INCREASE(export_func_list);
- OFFSET_INCREASE(pragma_list);
- OFFSET_INCREASE(func_table);
- OFFSET_INCREASE(object_slot_list);
-
-#undef OFFSET_INCREASE
- return true;
-}
-
-
-bool CacheWriter::calcContextChecksum() {
- uint32_t sum = 0;
- uint32_t *ptr = reinterpret_cast<uint32_t *>(mpOwner->getContext());
-
- for (size_t i = 0; i < ContextManager::ContextSize / sizeof(uint32_t); ++i) {
- sum ^= *ptr++;
- }
-
- mpHeaderSection->context_parity_checksum = sum;
- return true;
-}
-
-
-bool CacheWriter::writeAll() {
-#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION) \
- do { \
- if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) { \
- ALOGE("Unable to seek to " #NAME " section for writing.\n"); \
- return false; \
- } \
- \
- if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) != \
- static_cast<ssize_t>(SIZE)) { \
- ALOGE("Unable to write " #NAME " section to cache file.\n"); \
- return false; \
- } \
- } while (0)
-
-#define WRITE_SECTION_SIMPLE(NAME, SECTION) \
- WRITE_SECTION(NAME, \
- mpHeaderSection->NAME##_offset, \
- mpHeaderSection->NAME##_size, \
- SECTION)
-
- WRITE_SECTION(header, 0, sizeof(OBCC_Header), mpHeaderSection);
-
- WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
- WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
- //WRITE_SECTION_SIMPLE(reloc_tab, mpRelocationTableSection);
- WRITE_SECTION_SIMPLE(export_var_list, mpExportVarListSection);
- WRITE_SECTION_SIMPLE(export_func_list, mpExportFuncListSection);
- WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
- WRITE_SECTION_SIMPLE(func_table, mpFuncTableSection);
- WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
-
-#undef WRITE_SECTION_SIMPLE
-#undef WRITE_SECTION
-
-
- // Write Context to Executable File
- char const *context = (char const *)mpOwner->getContext();
- size_t context_size = ContextManager::ContextSize;
- if (mObjFile->write(context, context_size) != (ssize_t)context_size) {
- ALOGE("Unable to write context image to executable file\n");
- return false;
- }
-
- return true;
-}
-
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/OldJIT/CacheWriter.h b/lib/ExecutionEngine/OldJIT/CacheWriter.h
deleted file mode 100644
index d492d4a..0000000
--- a/lib/ExecutionEngine/OldJIT/CacheWriter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_CACHEWRITER_H
-#define BCC_CACHEWRITER_H
-
-#include <bcc/bcc_cache.h>
-
-#include "FileHandle.h"
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace bcc {
- class Script;
-
- class CacheWriter {
- private:
- Script *mpOwner;
-
- FileHandle *mObjFile;
- FileHandle *mInfoFile;
-
- std::vector<std::pair<char const *, size_t> > mStringPool;
-
- std::map<std::string,
- std::pair<uint32_t, unsigned char const *> > mDependencies;
-
- OBCC_Header *mpHeaderSection;
- OBCC_StringPool *mpStringPoolSection;
- OBCC_DependencyTable *mpDependencyTableSection;
- //OBCC_RelocationTable *mpRelocationTableSection;
- OBCC_ExportVarList *mpExportVarListSection;
- OBCC_ExportFuncList *mpExportFuncListSection;
- OBCC_PragmaList *mpPragmaListSection;
- OBCC_FuncTable *mpFuncTableSection;
- OBCC_ObjectSlotList *mpObjectSlotSection;
-
- public:
- CacheWriter()
- : mpHeaderSection(NULL), mpStringPoolSection(NULL),
- mpDependencyTableSection(NULL), mpExportVarListSection(NULL),
- mpExportFuncListSection(NULL), mpPragmaListSection(NULL),
- mpFuncTableSection(NULL), mpObjectSlotSection(NULL) {
- }
-
- ~CacheWriter();
-
- bool writeCacheFile(FileHandle *objFile,
- FileHandle *infoFile,
- Script *S,
- uint32_t libRS_threadable);
-
- void addDependency(OBCC_ResourceType resType,
- std::string const &resName,
- unsigned char const *sha1) {
- mDependencies.insert(std::make_pair(resName,
- std::make_pair((uint32_t)resType, sha1)));
- }
-
- private:
- bool prepareHeader(uint32_t libRS_threadable);
- bool prepareStringPool();
- bool prepareDependencyTable();
- bool prepareRelocationTable();
- bool prepareExportVarList();
- bool prepareExportFuncList();
- bool preparePragmaList();
- bool prepareFuncTable();
- bool prepareObjectSlotList();
-
- bool writeAll();
-
- bool calcSectionOffset();
- bool calcContextChecksum();
-
- size_t addString(char const *str, size_t size) {
- mStringPool.push_back(std::make_pair(str, size));
- return mStringPool.size() - 1;
- }
-
- };
-
-} // namespace bcc
-
-#endif // BCC_CACHEWRITER_H
diff --git a/lib/ExecutionEngine/OldJIT/ContextManager.cpp b/lib/ExecutionEngine/OldJIT/ContextManager.cpp
deleted file mode 100644
index 5dca382..0000000
--- a/lib/ExecutionEngine/OldJIT/ContextManager.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * copyright 2010, the android open source project
- *
- * licensed under the apache license, version 2.0 (the "license");
- * you may not use this file except in compliance with the license.
- * you may obtain a copy of the license at
- *
- * http://www.apache.org/licenses/license-2.0
- *
- * unless required by applicable law or agreed to in writing, software
- * distributed under the license is distributed on an "as is" basis,
- * without warranties or conditions of any kind, either express or implied.
- * see the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-#include "ContextManager.h"
-
-#include "DebugHelper.h"
-
-#include <llvm/Support/Mutex.h>
-#include <llvm/Support/MutexGuard.h>
-
-#include <errno.h>
-#include <sys/mman.h>
-#include <utils/threads.h>
-
-#include <stddef.h>
-#include <string.h>
-
-
-namespace bcc {
-
-// Starting address for context slots
-char * const ContextManager::ContextFixedAddr = BCC_CONTEXT_FIXED_ADDR_;
-
-// ContextManager singleton object
-ContextManager ContextManager::TheContextManager;
-
-
-ContextManager::ContextManager() {
- // Initialize context slot occupation table to false
- for (size_t i = 0; i < ContextSlotCount; ++i) {
- mContextSlotOccupied[i] = false;
- }
-}
-
-char *ContextManager::allocateContext() {
- {
- // Acquire mContextSlotOccupiedLock
- llvm::MutexGuard Locked(mContextSlotOccupiedLock);
-
- // Try to allocate context on the managed context slot.
- for (size_t i = 0; i < ContextSlotCount; ++i) {
- if (mContextSlotOccupied[i]) {
- continue;
- }
-
- void *addr = ContextFixedAddr + ContextSize * i;
- void *result = mmap(addr, ContextSize,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANON, -1, 0);
-
- if (result == addr) {
- ALOGI("Allocate bcc context. addr=%p\n", result);
- mContextSlotOccupied[i] = true;
- return static_cast<char *>(result);
- }
-
- if (result && result != MAP_FAILED) {
- ALOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
- munmap(result, ContextSize);
- }
-
- ALOGE("Unable to allocate. addr=%p. Retry ...\n", addr);
- }
- // Release mContextSlotOccupiedLock
- }
-
- // No slot available, allocate at arbitary address.
- void *result = mmap(0, ContextSize, PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANON, -1, 0);
-
- if (!result || result == MAP_FAILED) {
- ALOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
- return NULL;
- }
-
- ALOGI("Allocate bcc context. addr=%p\n", result);
- return static_cast<char *>(result);
-}
-
-
-char *ContextManager::allocateContext(char *addr,
- int imageFd, off_t imageOffset) {
- // This function should only allocate context when address is an context
- // slot address. And the image offset is aligned to the pagesize.
-
- if (imageFd < 0) {
- ALOGE("Invalid file descriptor for bcc context image\n");
- return NULL;
- }
-
- unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
-
- if (imageOffset % pagesize > 0) {
- ALOGE("BCC context image offset is not aligned to page size\n");
- return NULL;
- }
-
- ssize_t slot = getSlotIndexFromAddress(addr);
- if (slot < 0) {
- ALOGE("Suggested address is not a bcc context slot address\n");
- return NULL;
- }
-
- llvm::MutexGuard Locked(mContextSlotOccupiedLock);
- if (mContextSlotOccupied[slot]) {
- ALOGW("Suggested bcc context slot has been occupied.\n");
- return NULL;
- }
-
- // ALOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
- void *result = mmap(addr, ContextSize,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE, imageFd, imageOffset);
-
- if (!result || result == MAP_FAILED) {
- ALOGE("Unable to allocate. addr=%p\n", addr);
- return NULL;
- }
-
- if (result != addr) {
- ALOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
- munmap(result, ContextSize);
- return NULL;
- }
-
- ALOGI("Allocate bcc context. addr=%p\n", addr);
- mContextSlotOccupied[slot] = true;
- return static_cast<char *>(result);
-}
-
-
-void ContextManager::deallocateContext(char *addr) {
- if (!addr) {
- return;
- }
-
- llvm::MutexGuard Locked(mContextSlotOccupiedLock);
-
- ALOGI("Deallocate bcc context. addr=%p\n", addr);
-
- // Unmap
- if (munmap(addr, ContextSize) < 0) {
- ALOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
- return;
- }
-
- // If the address is one of the context slot, then mark such slot
- // freely available as well.
- ssize_t slot = getSlotIndexFromAddress(addr);
- if (slot >= 0) {
- // Give the context slot back.
- mContextSlotOccupied[slot] = false;
- }
-}
-
-
-bool ContextManager::isManagingContext(char *addr) const {
- ssize_t slot = getSlotIndexFromAddress(addr);
-
- if (slot < 0) {
- return false;
- }
-
- llvm::MutexGuard Locked(mContextSlotOccupiedLock);
- return mContextSlotOccupied[slot];
-}
-
-
-ssize_t ContextManager::getSlotIndexFromAddress(char *addr) {
- if (addr >= ContextFixedAddr) {
- size_t offset = (size_t)(addr - ContextFixedAddr);
- if (offset % ContextSize == 0) {
- size_t slot = offset / ContextSize;
- if (slot < ContextSlotCount) {
- return slot;
- }
- }
- }
- return -1;
-}
-
-
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/OldJIT/ContextManager.h b/lib/ExecutionEngine/OldJIT/ContextManager.h
deleted file mode 100644
index f23c4a1..0000000
--- a/lib/ExecutionEngine/OldJIT/ContextManager.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * copyright 2010, the android open source project
- *
- * licensed under the apache license, version 2.0 (the "license");
- * you may not use this file except in compliance with the license.
- * you may obtain a copy of the license at
- *
- * http://www.apache.org/licenses/license-2.0
- *
- * unless required by applicable law or agreed to in writing, software
- * distributed under the license is distributed on an "as is" basis,
- * without warranties or conditions of any kind, either express or implied.
- * see the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-#ifndef BCC_CONTEXTMANAGER_H
-#define BCC_CONTEXTMANAGER_H
-
-#include <Config.h>
-
-#include <llvm/Support/Mutex.h>
-
-#include <unistd.h>
-#include <stddef.h>
-
-
-namespace bcc {
-
- class ContextManager {
- public:
- // Starting address of context slot address space
- static char * const ContextFixedAddr;
-
- // Number of the context slots
- static size_t const ContextSlotCount = BCC_CONTEXT_SLOT_COUNT_;
-
- // Context size
- static size_t const ContextCodeSize = BCC_CONTEXT_CODE_SIZE_;
- static size_t const ContextDataSize = BCC_CONTEXT_DATA_SIZE_;
- static size_t const ContextSize = ContextCodeSize + ContextDataSize;
-
- private:
- // Context manager singleton
- static ContextManager TheContextManager;
-
- private:
- // Mutex lock for context slot occupation table
- mutable llvm::sys::Mutex mContextSlotOccupiedLock;
-
- // Context slot occupation table
- bool mContextSlotOccupied[ContextSlotCount];
-
- ContextManager();
-
- public:
- static ContextManager &get() {
- return TheContextManager;
- }
-
- char *allocateContext();
- char *allocateContext(char *addr, int imageFd, off_t imageOffset);
- void deallocateContext(char *addr);
-
- bool isManagingContext(char *addr) const;
-
- private:
- static ssize_t getSlotIndexFromAddress(char *addr);
-
- };
-
-} // namespace bcc
-
-#endif // BCC_CONTEXTMANAGER_H
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 4b0b406..445d075 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -18,19 +18,10 @@
#include "Config.h"
-#if USE_OLD_JIT
-#include "OldJIT/CacheReader.h"
-#include "OldJIT/CacheWriter.h"
-#endif
-
#include "MCCacheReader.h"
#include "MCCacheWriter.h"
#include "CompilerOption.h"
-#if USE_OLD_JIT
-#include "OldJIT/ContextManager.h"
-#endif
-
#include "DebugHelper.h"
#include "FileHandle.h"
#include "GDBJITRegistrar.h"
@@ -66,11 +57,9 @@
delete mCompiled;
break;
-#if USE_CACHE
case ScriptStatus::Cached:
delete mCached;
break;
-#endif
default:
break;
@@ -230,10 +219,7 @@
return 1;
}
- int status = -1;
-#if USE_CACHE
- status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
-#endif
+ int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
if (status != 0) {
CompilerOption option;
@@ -259,7 +245,6 @@
return status;
}
-#if USE_CACHE
int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
bool checkOnly) {
if ((cacheDir == NULL) || (cacheName == NULL)) {
@@ -294,9 +279,6 @@
return 1;
}
-#if USE_OLD_JIT
- CacheReader reader;
-#elif USE_MCJIT
MCCacheReader reader;
// Register symbol lookup function
@@ -304,7 +286,6 @@
reader.registerSymbolCallback(mpExtSymbolLookupFn,
mpExtSymbolLookupFnContext);
}
-#endif
// Dependencies
reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
@@ -338,7 +319,6 @@
return 0;
}
-#endif
int Script::internalCompile(const CompilerOption &option) {
// Create the ScriptCompiled object
@@ -406,19 +386,13 @@
(getCompilerErrorMessage() == NULL))
return 1;
-#if USE_CACHE
// Note: If we re-compile the script because the cached context slot not
// available, then we don't have to write the cache.
// Note: If the address of the context is not in the context slot, then
// we don't have to cache it.
- if (
-#if USE_OLD_JIT
- !mIsContextSlotNotAvail &&
- ContextManager::get().isManagingContext(getContext()) &&
-#endif
- isCacheable()) {
+ if (isCacheable()) {
std::string objPath = getCachedObjectPath();
std::string infoPath = getCacheInfoPath();
@@ -428,9 +402,7 @@
// to modify its contents. (The same script may be running concurrently in
// the same process or a different process!)
::unlink(objPath.c_str());
-#if !USE_OLD_JIT && USE_MCJIT
::unlink(infoPath.c_str());
-#endif
FileHandle objFile;
FileHandle infoFile;
@@ -438,11 +410,7 @@
if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
-#if USE_OLD_JIT
- CacheWriter writer;
-#elif USE_MCJIT
MCCacheWriter writer;
-#endif
#ifdef TARGET_BUILD
// Dependencies
@@ -484,7 +452,6 @@
}
}
}
-#endif // USE_CACHE
return 0;
}
@@ -506,11 +473,9 @@
return mCompiled->lookup(name);
}
-#if USE_CACHE
case ScriptStatus::Cached: {
return mCached->lookup(name);
}
-#endif
default: {
mErrorCode = BCC_INVALID_OPERATION;
@@ -526,11 +491,9 @@
return mCompiled->getExportVarCount();
}
-#if USE_CACHE
case ScriptStatus::Cached: {
return mCached->getExportVarCount();
}
-#endif
default: {
return 0;
@@ -545,11 +508,9 @@
return mCompiled->getExportFuncCount();
}
-#if USE_CACHE
case ScriptStatus::Cached: {
return mCached->getExportFuncCount();
}
-#endif
default: {
return 0;
@@ -564,11 +525,9 @@
return mCompiled->getExportForEachCount();
}
-#if USE_CACHE
case ScriptStatus::Cached: {
return mCached->getExportForEachCount();
}
-#endif
default: {
return 0;
@@ -583,11 +542,9 @@
return mCompiled->getPragmaCount();
}
-#if USE_CACHE
case ScriptStatus::Cached: {
return mCached->getPragmaCount();
}
-#endif
default: {
return 0;
@@ -602,11 +559,9 @@
return mCompiled->getFuncCount();
}
-#if USE_CACHE
case ScriptStatus::Cached: {
return mCached->getFuncCount();
}
-#endif
default: {
return 0;
@@ -621,11 +576,9 @@
return mCompiled->getObjectSlotCount();
}
-#if USE_CACHE
case ScriptStatus::Cached: {
return mCached->getObjectSlotCount();
}
-#endif
default: {
return 0;
@@ -641,9 +594,7 @@
m##STATUS->getExportVarList(varListSize, varList); \
break;
-#if USE_CACHE
DELEGATE(Cached);
-#endif
DELEGATE(Compiled);
#undef DELEGATE
@@ -674,9 +625,7 @@
m##STATUS->getExportFuncList(funcListSize, funcList); \
break;
-#if USE_CACHE
DELEGATE(Cached);
-#endif
DELEGATE(Compiled);
#undef DELEGATE
@@ -706,9 +655,7 @@
m##STATUS->getExportForEachList(funcListSize, funcList); \
break;
-#if USE_CACHE
DELEGATE(Cached);
-#endif
DELEGATE(Compiled);
#undef DELEGATE
@@ -740,9 +687,7 @@
m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
break;
-#if USE_CACHE
DELEGATE(Cached);
-#endif
DELEGATE(Compiled);
#undef DELEGATE
@@ -762,9 +707,7 @@
m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
break;
-#if USE_CACHE
DELEGATE(Cached);
-#endif
DELEGATE(Compiled);
#undef DELEGATE
@@ -784,9 +727,7 @@
m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
break;
-#if USE_CACHE
DELEGATE(Cached);
-#endif
DELEGATE(Compiled);
#undef DELEGATE
@@ -798,29 +739,6 @@
}
-#if USE_OLD_JIT
-char *Script::getContext() {
- switch (mStatus) {
-
-#if USE_CACHE
- case ScriptStatus::Cached: {
- return mCached->getContext();
- }
-#endif
-
- case ScriptStatus::Compiled: {
- return mCompiled->getContext();
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- return NULL;
- }
- }
-}
-#endif
-
-
int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
mpExtSymbolLookupFn = pFn;
mpExtSymbolLookupFnContext = pContext;
@@ -834,7 +752,6 @@
}
bool Script::isCacheable() const {
-#if USE_CACHE
if (getBooleanProp("debug.bcc.nocache")) {
// Android system environment property: Disables the cache mechanism by
// setting "debug.bcc.nocache". So we will not load the cache file any
@@ -849,22 +766,18 @@
}
return true;
-#else
- return false;
-#endif
}
-#if USE_MCJIT
size_t Script::getELFSize() const {
switch (mStatus) {
case ScriptStatus::Compiled: {
return mCompiled->getELFSize();
}
-#if USE_CACHE
+
case ScriptStatus::Cached: {
return mCached->getELFSize();
}
-#endif
+
default: {
return 0;
}
@@ -876,16 +789,15 @@
case ScriptStatus::Compiled: {
return mCompiled->getELF();
}
-#if USE_CACHE
+
case ScriptStatus::Cached: {
return mCached->getELF();
}
-#endif
+
default: {
return NULL;
}
}
}
-#endif
} // namespace bcc
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index b05fc07..16a453c 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -44,9 +44,7 @@
enum StatusType {
Unknown,
Compiled,
-#if USE_CACHE
- Cached,
-#endif
+ Cached
};
}
@@ -71,31 +69,19 @@
union {
ScriptCompiled *mCompiled;
-#if USE_CACHE
ScriptCached *mCached;
-#endif
};
-#if USE_CACHE
std::string mCacheDir;
std::string mCacheName;
inline std::string getCachedObjectPath() const {
-#if USE_OLD_JIT
- return std::string(mCacheDir + mCacheName + ".jit-image");
-#elif USE_MCJIT
return std::string(mCacheDir + mCacheName + ".o");
-#endif
}
inline std::string getCacheInfoPath() const {
-#if USE_OLD_JIT
- return getCachedObjectPath().append(".oBCC");
-#elif USE_MCJIT
return getCachedObjectPath().append(".info");
-#endif
}
-#endif
bool mIsContextSlotNotAvail;
@@ -217,10 +203,6 @@
int registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext);
-#if USE_OLD_JIT
- char *getContext();
-#endif
-
bool isCacheable() const;
void setError(int error) {
@@ -236,14 +218,13 @@
}
private:
-#if USE_CACHE
//
// It returns 0 if there's a cache hit.
//
// Side effect: it will set mCacheDir, mCacheName.
int internalLoadCache(char const *cacheDir, char const *cacheName,
bool checkOnly);
-#endif
+
int internalCompile(const CompilerOption&);
};
diff --git a/lib/ExecutionEngine/ScriptCached.cpp b/lib/ExecutionEngine/ScriptCached.cpp
index 30fc3fd..bbfac2b 100644
--- a/lib/ExecutionEngine/ScriptCached.cpp
+++ b/lib/ExecutionEngine/ScriptCached.cpp
@@ -18,12 +18,6 @@
#include "ScriptCached.h"
-#include <bcc/bcc_cache.h>
-
-#if USE_OLD_JIT
-#include "OldJIT/ContextManager.h"
-#endif
-
#include "DebugHelper.h"
#include <stdlib.h>
@@ -31,13 +25,6 @@
namespace bcc {
ScriptCached::~ScriptCached() {
- // Deallocate the bcc script context
-#if USE_OLD_JIT
- if (mContext) {
- ContextManager::get().deallocateContext(mContext);
- }
-#endif
-
// Deallocate string pool, exported var list, exported func list
if (mpStringPoolRaw) { free(mpStringPoolRaw); }
if (mpExportVars) { free(mpExportVars); }
@@ -127,11 +114,7 @@
void *ScriptCached::lookup(const char *name) {
-#if USE_MCJIT
return rsloaderGetSymbolAddress(mRSExecutable, name);
-#endif
- FuncTable::const_iterator I = mFunctions.find(name);
- return (I == mFunctions.end()) ? NULL : I->second.first;
}
void ScriptCached::getFuncInfoList(size_t funcInfoListSize,
diff --git a/lib/ExecutionEngine/ScriptCached.h b/lib/ExecutionEngine/ScriptCached.h
index f18cb88..e24a714 100644
--- a/lib/ExecutionEngine/ScriptCached.h
+++ b/lib/ExecutionEngine/ScriptCached.h
@@ -20,13 +20,10 @@
#include "Config.h"
#include <bcc/bcc.h>
-#include <bcc/bcc_cache.h>
#include <bcc/bcc_mccache.h>
#include "bcc_internal.h"
-#if USE_MCJIT
#include "librsloader.h"
-#endif
#include <llvm/ADT/SmallVector.h>
@@ -59,24 +56,18 @@
private:
Script *mpOwner;
- OBCC_ExportVarList *mpExportVars;
- OBCC_ExportFuncList *mpExportFuncs;
- OBCC_ExportForEachList *mpExportForEach;
+ MCO_ExportVarList *mpExportVars;
+ MCO_ExportFuncList *mpExportFuncs;
+ MCO_ExportForEachList *mpExportForEach;
PragmaList mPragmas;
- OBCC_ObjectSlotList *mpObjectSlotList;
+ MCO_ObjectSlotList *mpObjectSlotList;
FuncTable mFunctions;
-#if USE_OLD_JIT
- char *mContext;
-#endif
-
-#if USE_MCJIT
RSExecRef mRSExecutable;
llvm::SmallVector<char, 1024> mCachedELFExecutable;
-#endif
- OBCC_StringPool *mpStringPoolRaw;
+ MCO_StringPool *mpStringPoolRaw;
std::vector<char const *> mStringPool;
bool mLibRSThreadable;
@@ -88,9 +79,6 @@
mpExportFuncs(NULL),
mpExportForEach(NULL),
mpObjectSlotList(NULL),
-#if USE_OLD_JIT
- mContext(NULL),
-#endif
mpStringPoolRaw(NULL),
mLibRSThreadable(false) {
}
@@ -139,13 +127,6 @@
void getObjectSlotList(size_t objectSlotListSize,
uint32_t *objectSlotList);
-#if USE_OLD_JIT
- char *getContext() {
- return mContext;
- }
-#endif
-
-#if USE_MCJIT
const char *getELF() const {
return &*mCachedELFExecutable.begin();
}
@@ -153,7 +134,7 @@
size_t getELFSize() const {
return mCachedELFExecutable.size();
}
-#endif
+
// Dirty hack for libRS.
// TODO(all): This should be removed in the future.
bool isLibRSThreadable() const {
diff --git a/lib/ExecutionEngine/ScriptCompiled.cpp b/lib/ExecutionEngine/ScriptCompiled.cpp
index 47f2bb4..4f2bb1b 100644
--- a/lib/ExecutionEngine/ScriptCompiled.cpp
+++ b/lib/ExecutionEngine/ScriptCompiled.cpp
@@ -17,28 +17,11 @@
#include "ScriptCompiled.h"
#include "bcc_internal.h"
-#if USE_OLD_JIT
-#include "OldJIT/ContextManager.h"
-#endif
#include "DebugHelper.h"
namespace bcc {
ScriptCompiled::~ScriptCompiled() {
-#if USE_OLD_JIT
- // Deallocate the BCC context
- if (mContext) {
- ContextManager::get().deallocateContext(mContext);
- }
-
- // Delete the emitted function information
- for (FuncInfoMap::iterator I = mEmittedFunctions.begin(),
- E = mEmittedFunctions.end(); I != E; I++) {
- if (I->second != NULL) {
- delete I->second;
- }
- }
-#endif
}
void ScriptCompiled::getExportVarList(size_t varListSize, void **varList) {
@@ -126,16 +109,7 @@
void *ScriptCompiled::lookup(const char *name) {
-#if USE_OLD_JIT
- FuncInfoMap::const_iterator I = mEmittedFunctions.find(name);
- return (I == mEmittedFunctions.end()) ? NULL : I->second->addr;
-#endif
-
-#if USE_MCJIT
return mCompiler.getSymbolAddress(name);
-#endif
-
- return NULL;
}
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index 4498f1a..d945024 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -65,16 +65,9 @@
FuncInfoMap mEmittedFunctions;
-#if USE_OLD_JIT
- char *mContext; // Context of BCC script (code and data)
-#endif
-
public:
ScriptCompiled(Script *owner)
: mpOwner(owner), mCompiler(this)
-#if USE_OLD_JIT
- , mContext(NULL)
-#endif
{
}
@@ -149,13 +142,6 @@
return mpOwner->getUserDefinedExternalSymbols();
}
-#if USE_OLD_JIT
- char *getContext() {
- return mContext;
- }
-#endif
-
-#if USE_MCJIT
const char *getELF() const {
return &*mCompiler.getELF().begin();
}
@@ -163,7 +149,6 @@
size_t getELFSize() const {
return mCompiler.getELF().size();
}
-#endif
void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
mCompiler.registerSymbolCallback(pFn, pContext);
diff --git a/lib/ExecutionEngine/SourceInfo.cpp b/lib/ExecutionEngine/SourceInfo.cpp
index 25c53e8..c069462 100644
--- a/lib/ExecutionEngine/SourceInfo.cpp
+++ b/lib/ExecutionEngine/SourceInfo.cpp
@@ -16,23 +16,14 @@
#include "SourceInfo.h"
-#if USE_CACHE
-#if USE_OLD_JIT
-#include "OldJIT/CacheReader.h"
-#include "OldJIT/CacheWriter.h"
-#endif
-#if USE_MCJIT
#include "MCCacheWriter.h"
#include "MCCacheReader.h"
-#endif
-#endif
#include "DebugHelper.h"
#include "ScriptCompiled.h"
#include "Sha1Helper.h"
#include <bcc/bcc.h>
-#include <bcc/bcc_cache.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Module.h>
@@ -64,7 +55,6 @@
result->buffer.bitcodeSize = bitcodeSize;
result->flags = flags;
-#if USE_CACHE
if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) {
result->flags |= BCC_SKIP_DEP_SHA1;
@@ -78,7 +68,6 @@
} else {
calcSHA1(result->sha1, bitcode, bitcodeSize);
}
-#endif
return result;
}
@@ -96,13 +85,11 @@
result->file.path = path;
result->flags = flags;
-#if USE_CACHE
memset(result->sha1, '\0', 20);
if (!(result->flags & BCC_SKIP_DEP_SHA1)) {
calcFileSHA1(result->sha1, path);
}
-#endif
return result;
}
@@ -120,7 +107,6 @@
result->module = module;
result->flags = flags;
-#if USE_CACHE
if (! (flags & BCC_SKIP_DEP_SHA1)) {
result->flags |= BCC_SKIP_DEP_SHA1;
@@ -130,7 +116,6 @@
}
memset(result->sha1, '\0', 20);
-#endif
return result;
}
@@ -196,7 +181,6 @@
}
}
-#if USE_CACHE
template <typename T> void SourceInfo::introDependency(T &checker) {
if (flags & BCC_SKIP_DEP_SHA1) {
return;
@@ -216,16 +200,8 @@
}
}
-#if USE_OLD_JIT
-template void SourceInfo::introDependency<CacheReader>(CacheReader &);
-template void SourceInfo::introDependency<CacheWriter>(CacheWriter &);
-#endif
-
-#if USE_MCJIT
template void SourceInfo::introDependency<MCCacheWriter>(MCCacheWriter &);
template void SourceInfo::introDependency<MCCacheReader>(MCCacheReader &);
-#endif
-#endif // USE_CACHE
} // namespace bcc
diff --git a/lib/ExecutionEngine/SourceInfo.h b/lib/ExecutionEngine/SourceInfo.h
index 9026f1c..080d3b4 100644
--- a/lib/ExecutionEngine/SourceInfo.h
+++ b/lib/ExecutionEngine/SourceInfo.h
@@ -61,9 +61,7 @@
unsigned long flags;
-#if USE_CACHE
unsigned char sha1[20];
-#endif
private:
SourceInfo() : module(NULL), shared_context(false) { }
@@ -91,9 +89,7 @@
// Share with the given context if it's provided.
int prepareModule(llvm::LLVMContext *context = NULL);
-#if USE_CACHE
template <typename T> void introDependency(T &checker);
-#endif
~SourceInfo();
};
diff --git a/libbcc-config.mk b/libbcc-config.mk
index dc3ab33..37cc848 100644
--- a/libbcc-config.mk
+++ b/libbcc-config.mk
@@ -28,33 +28,19 @@
# Configurations
#=====================================================================
-libbcc_USE_OLD_JIT := 0
-libbcc_USE_MCJIT := 1
-
-libbcc_USE_CACHE := 1
-
-libbcc_DEBUG_OLD_JIT_DISASSEMBLER := 0
-libbcc_DEBUG_MCJIT_DISASSEMBLER := 0
+libbcc_DEBUG_MC_DISASSEMBLER := 0
libbcc_USE_LOGGER := 1
libbcc_USE_FUNC_LOGGER := 0
libbcc_DEBUG_BCC_REFLECT := 0
-libbcc_DEBUG_MCJIT_REFLECT := 0
+libbcc_DEBUG_MC_REFLECT := 0
#=====================================================================
# Automatic Configurations
#=====================================================================
-ifeq ($(libbcc_USE_OLD_JIT),0)
-libbcc_DEBUG_OLD_JIT_DISASSEMBLER := 0
-endif
-
-ifeq ($(libbcc_USE_MCJIT),0)
-libbcc_DEBUG_MCJIT_DISASSEMBLER := 0
-endif
-
-ifeq ($(libbcc_DEBUG_OLD_JIT_DISASSEMBLER)$(libbcc_DEBUG_MCJIT_DISASSEMBLER),00)
+ifeq ($(libbcc_DEBUG_MC_DISASSEMBLER),0)
libbcc_USE_DISASSEMBLER := 0
else
libbcc_USE_DISASSEMBLER := 1