blob: ae5c0c1c3d55c91aa3a20c244cc4aa1555840711 [file] [log] [blame]
Stephen Hines932bc6e2011-07-27 16:26:26 -07001/*
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"
Logan Chienc7d67a72011-12-16 17:06:49 +080020#include "BitReader_3_0/BitReader_3_0.h"
Stephen Hines932bc6e2011-07-27 16:26:26 -070021
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 *
Logan Chienc7d67a72011-12-16 17:06:49 +080040 * 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
Stephen Hines932bc6e2011-07-27 16:26:26 -070051 */
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 */
Logan Chienc7d67a72011-12-16 17:06:49 +080060static const unsigned int kMinimumUntranslatedVersion = 16;
61static const unsigned int kMinimumCompatibleVersion_LLVM_3_0 = 14;
62static const unsigned int kMinimumCompatibleVersion_LLVM_2_7 = 11;
Stephen Hines932bc6e2011-07-27 16:26:26 -070063
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.
Logan Chienc7d67a72011-12-16 17:06:49 +0800115 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
Stephen Hines932bc6e2011-07-27 16:26:26 -0700126 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