BitcodeTranslator.cpp revision c7d67a701663191bcdab2416c11b69fae16d49fb
1/* 2 * Copyright 2011, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "bcinfo/BitcodeTranslator.h" 18 19#include "BitReader_2_7/BitReader_2_7.h" 20#include "BitReader_3_0/BitReader_3_0.h" 21 22#define LOG_TAG "bcinfo" 23#include <cutils/log.h> 24 25#include "llvm/ADT/OwningPtr.h" 26#include "llvm/Bitcode/BitstreamWriter.h" 27#include "llvm/Bitcode/ReaderWriter.h" 28#include "llvm/LLVMContext.h" 29#include "llvm/Module.h" 30#include "llvm/Support/MemoryBuffer.h" 31 32#include <cstdlib> 33 34namespace bcinfo { 35 36/** 37 * Define minimum and maximum target API versions. These correspond to the 38 * same API levels used by the standard Android SDK. 39 * 40 * LLVM 2.7 41 * 11 - Honeycomb 42 * 12 - Honeycomb MR1 43 * 13 - Honeycomb MR2 44 * 45 * LLVM 3.0 46 * 14 - Ice Cream Sandwich 47 * 15 - Ice Cream Sandwich MR1 48 * 49 * LLVM 3.1 50 * 16 - Ice Cream Sandwich MR2 51 */ 52static const unsigned int kMinimumAPIVersion = 11; 53static const unsigned int kMaximumAPIVersion = BCINFO_API_VERSION; 54static const unsigned int kCurrentAPIVersion = 10000; 55 56/** 57 * The minimum version which does not require translation (i.e. is already 58 * compatible with LLVM's default bitcode reader). 59 */ 60static const unsigned int kMinimumUntranslatedVersion = 16; 61static const unsigned int kMinimumCompatibleVersion_LLVM_3_0 = 14; 62static const unsigned int kMinimumCompatibleVersion_LLVM_2_7 = 11; 63 64 65BitcodeTranslator::BitcodeTranslator(const char *bitcode, size_t bitcodeSize, 66 unsigned int version) 67 : mBitcode(bitcode), mBitcodeSize(bitcodeSize), mTranslatedBitcode(NULL), 68 mTranslatedBitcodeSize(0), mVersion(version) { 69 return; 70} 71 72 73BitcodeTranslator::~BitcodeTranslator() { 74 if (mVersion < kMinimumUntranslatedVersion) { 75 // We didn't actually do a translation in the alternate case, so deleting 76 // the bitcode would be improper. 77 delete [] mTranslatedBitcode; 78 } 79 mTranslatedBitcode = NULL; 80 return; 81} 82 83 84bool BitcodeTranslator::translate() { 85 if (!mBitcode || !mBitcodeSize) { 86 LOGE("Invalid/empty bitcode"); 87 return false; 88 } 89 90 if ((mVersion != kCurrentAPIVersion) && 91 ((mVersion < kMinimumAPIVersion) || 92 (mVersion > kMaximumAPIVersion))) { 93 LOGE("Invalid API version: %u is out of range ('%u' - '%u')", mVersion, 94 kMinimumAPIVersion, kMaximumAPIVersion); 95 return false; 96 } 97 98 // We currently don't need to transcode any API version higher than 14 or 99 // the current API version (i.e. 10000) 100 if (mVersion >= kMinimumUntranslatedVersion) { 101 mTranslatedBitcode = mBitcode; 102 mTranslatedBitcodeSize = mBitcodeSize; 103 return true; 104 } 105 106 // Do the actual transcoding by invoking a 2.7-era bitcode reader that can 107 // then write the bitcode back out in a more modern (acceptable) version. 108 llvm::OwningPtr<llvm::LLVMContext> mContext(new llvm::LLVMContext()); 109 llvm::OwningPtr<llvm::MemoryBuffer> MEM( 110 llvm::MemoryBuffer::getMemBuffer( 111 llvm::StringRef(mBitcode, mBitcodeSize))); 112 std::string error; 113 114 // Module ownership is handled by the context, so we don't need to free it. 115 llvm::Module *module = NULL; 116 117 if (mVersion >= kMinimumCompatibleVersion_LLVM_3_0) { 118 module = llvm_3_0::ParseBitcodeFile(MEM.get(), *mContext, &error); 119 } else if (mVersion >= kMinimumCompatibleVersion_LLVM_2_7) { 120 module = llvm_2_7::ParseBitcodeFile(MEM.get(), *mContext, &error); 121 } else { 122 LOGE("No compatible bitcode reader for API version %d", mVersion); 123 return false; 124 } 125 126 if (!module) { 127 LOGE("Could not parse bitcode file"); 128 LOGE("%s", error.c_str()); 129 return false; 130 } 131 132 std::vector<unsigned char> Buffer; 133 llvm::BitstreamWriter Stream(Buffer); 134 Buffer.reserve(mBitcodeSize); 135 llvm::WriteBitcodeToStream(module, Stream); 136 137 char *c = new char[Buffer.size()]; 138 memcpy(c, &Buffer.front(), Buffer.size()); 139 140 mTranslatedBitcode = c; 141 mTranslatedBitcodeSize = Buffer.size(); 142 143 return true; 144} 145 146} // namespace bcinfo 147 148