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 21 #define LOG_TAG "bcinfo" 22 #include <cutils/log.h> 23 24 #include "llvm/ADT/OwningPtr.h" 25 #include "llvm/Bitcode/BitstreamWriter.h" 26 #include "llvm/Bitcode/ReaderWriter.h" 27 #include "llvm/LLVMContext.h" 28 #include "llvm/Module.h" 29 #include "llvm/Support/MemoryBuffer.h" 30 31 #include <cstdlib> 32 33 namespace bcinfo { 34 35 /** 36 * Define minimum and maximum target API versions. These correspond to the 37 * same API levels used by the standard Android SDK. 38 * 39 * 11 - Honeycomb 40 * 12 - Honeycomb MR1 41 * 13 - Honeycomb MR2 42 * 14 - Ice Cream Sandwich 43 */ 44 static const unsigned int kMinimumAPIVersion = 11; 45 static const unsigned int kMaximumAPIVersion = BCINFO_API_VERSION; 46 static const unsigned int kCurrentAPIVersion = 10000; 47 48 /** 49 * The minimum version which does not require translation (i.e. is already 50 * compatible with LLVM's default bitcode reader). 51 */ 52 static const unsigned int kMinimumUntranslatedVersion = 14; 53 54 55 BitcodeTranslator::BitcodeTranslator(const char *bitcode, size_t bitcodeSize, 56 unsigned int version) 57 : mBitcode(bitcode), mBitcodeSize(bitcodeSize), mTranslatedBitcode(NULL), 58 mTranslatedBitcodeSize(0), mVersion(version) { 59 return; 60 } 61 62 63 BitcodeTranslator::~BitcodeTranslator() { 64 if (mVersion < kMinimumUntranslatedVersion) { 65 // We didn't actually do a translation in the alternate case, so deleting 66 // the bitcode would be improper. 67 delete [] mTranslatedBitcode; 68 } 69 mTranslatedBitcode = NULL; 70 return; 71 } 72 73 74 bool BitcodeTranslator::translate() { 75 if (!mBitcode || !mBitcodeSize) { 76 LOGE("Invalid/empty bitcode"); 77 return false; 78 } 79 80 if ((mVersion != kCurrentAPIVersion) && 81 ((mVersion < kMinimumAPIVersion) || 82 (mVersion > kMaximumAPIVersion))) { 83 LOGE("Invalid API version: %u is out of range ('%u' - '%u')", mVersion, 84 kMinimumAPIVersion, kMaximumAPIVersion); 85 return false; 86 } 87 88 // We currently don't need to transcode any API version higher than 14 or 89 // the current API version (i.e. 10000) 90 if (mVersion >= kMinimumUntranslatedVersion) { 91 mTranslatedBitcode = mBitcode; 92 mTranslatedBitcodeSize = mBitcodeSize; 93 return true; 94 } 95 96 // Do the actual transcoding by invoking a 2.7-era bitcode reader that can 97 // then write the bitcode back out in a more modern (acceptable) version. 98 llvm::OwningPtr<llvm::LLVMContext> mContext(new llvm::LLVMContext()); 99 llvm::OwningPtr<llvm::MemoryBuffer> MEM( 100 llvm::MemoryBuffer::getMemBuffer( 101 llvm::StringRef(mBitcode, mBitcodeSize))); 102 std::string error; 103 104 // Module ownership is handled by the context, so we don't need to free it. 105 llvm::Module *module = 106 llvm_2_7::ParseBitcodeFile(MEM.get(), *mContext, &error); 107 if (!module) { 108 LOGE("Could not parse bitcode file"); 109 LOGE("%s", error.c_str()); 110 return false; 111 } 112 113 std::vector<unsigned char> Buffer; 114 llvm::BitstreamWriter Stream(Buffer); 115 Buffer.reserve(mBitcodeSize); 116 llvm::WriteBitcodeToStream(module, Stream); 117 118 char *c = new char[Buffer.size()]; 119 memcpy(c, &Buffer.front(), Buffer.size()); 120 121 mTranslatedBitcode = c; 122 mTranslatedBitcodeSize = Buffer.size(); 123 124 return true; 125 } 126 127 } // namespace bcinfo 128 129