SourceInfo.cpp revision 4adbcb275454d7cc179a541ff07f37474f31b522
1/* 2 * Copyright 2010, 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 "SourceInfo.h" 18 19#if USE_CACHE 20#if USE_OLD_JIT 21#include "OldJIT/CacheReader.h" 22#include "OldJIT/CacheWriter.h" 23#endif 24#if USE_MCJIT 25#include "MCCacheWriter.h" 26#include "MCCacheReader.h" 27#endif 28#endif 29 30#include "DebugHelper.h" 31#include "ScriptCompiled.h" 32#include "Sha1Helper.h" 33 34#include <bcc/bcc.h> 35#include <bcc/bcc_cache.h> 36 37#include <llvm/Bitcode/ReaderWriter.h> 38#include <llvm/Module.h> 39#include <llvm/LLVMContext.h> 40#include <llvm/ADT/OwningPtr.h> 41#include <llvm/ADT/StringRef.h> 42#include <llvm/Support/MemoryBuffer.h> 43#include <llvm/Support/system_error.h> 44 45#include <stddef.h> 46#include <string.h> 47 48namespace bcc { 49 50 51SourceInfo *SourceInfo::createFromBuffer(char const *resName, 52 char const *bitcode, 53 size_t bitcodeSize, 54 unsigned long flags) { 55 SourceInfo *result = new SourceInfo(); 56 57 if (!result) { 58 return NULL; 59 } 60 61 result->type = SourceKind::Buffer; 62 result->buffer.resName = resName; 63 result->buffer.bitcode = bitcode; 64 result->buffer.bitcodeSize = bitcodeSize; 65 result->flags = flags; 66 67#if USE_CACHE 68 if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) { 69 result->flags |= BCC_SKIP_DEP_SHA1; 70 71 ALOGW("It is required to give resName for sha1 dependency check.\n"); 72 ALOGW("Sha1sum dependency check will be skipped.\n"); 73 ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n"); 74 } 75 76 if (result->flags & BCC_SKIP_DEP_SHA1) { 77 memset(result->sha1, '\0', 20); 78 } else { 79 calcSHA1(result->sha1, bitcode, bitcodeSize); 80 } 81#endif 82 83 return result; 84} 85 86 87SourceInfo *SourceInfo::createFromFile(char const *path, 88 unsigned long flags) { 89 SourceInfo *result = new SourceInfo(); 90 91 if (!result) { 92 return NULL; 93 } 94 95 result->type = SourceKind::File; 96 result->file.path = path; 97 result->flags = flags; 98 99#if USE_CACHE 100 memset(result->sha1, '\0', 20); 101 102 if (!(result->flags & BCC_SKIP_DEP_SHA1)) { 103 calcFileSHA1(result->sha1, path); 104 } 105#endif 106 107 return result; 108} 109 110 111SourceInfo *SourceInfo::createFromModule(llvm::Module *module, 112 unsigned long flags) { 113 SourceInfo *result = new SourceInfo(); 114 115 if (!result) { 116 return NULL; 117 } 118 119 result->type = SourceKind::Module; 120 result->module = module; 121 result->flags = flags; 122 123#if USE_CACHE 124 if (! (flags & BCC_SKIP_DEP_SHA1)) { 125 result->flags |= BCC_SKIP_DEP_SHA1; 126 127 ALOGW("Unable to calculate sha1sum for llvm::Module.\n"); 128 ALOGW("Sha1sum dependency check will be skipped.\n"); 129 ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n"); 130 } 131 132 memset(result->sha1, '\0', 20); 133#endif 134 135 return result; 136} 137 138 139int SourceInfo::prepareModule(llvm::LLVMContext *context) { 140 if (module) 141 return 0; 142 143 llvm::OwningPtr<llvm::MemoryBuffer> mem; 144 std::string errmsg; 145 146 switch (type) { 147 case SourceKind::Buffer: 148 { 149 mem.reset(llvm::MemoryBuffer::getMemBuffer( 150 llvm::StringRef(buffer.bitcode, buffer.bitcodeSize))); 151 152 if (!mem.get()) { 153 ALOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n", 154 buffer.bitcode, (unsigned long)buffer.bitcodeSize); 155 return 1; 156 } 157 } 158 break; 159 160 case SourceKind::File: 161 { 162 if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, mem)) { 163 ALOGE("Unable to MemoryBuffer::getFile(path=%s, %s)\n", 164 file.path, ec.message().c_str()); 165 return 1; 166 } 167 } 168 break; 169 170 default: 171 return 0; 172 break; 173 } 174 175 if (context) 176 shared_context = true; 177 else 178 context = new llvm::LLVMContext(); 179 180 module = llvm::ParseBitcodeFile(mem.get(), *context, &errmsg); 181 if (module == NULL) { 182 ALOGE("Unable to ParseBitcodeFile: %s\n", errmsg.c_str()); 183 if (!shared_context) 184 delete context; 185 } 186 187 return (module == NULL); 188} 189 190SourceInfo::~SourceInfo() { 191 if (module != NULL) { 192 llvm::LLVMContext *context = &module->getContext(); 193 delete module; 194 if (!shared_context) 195 delete context; 196 } 197} 198 199#if USE_CACHE 200template <typename T> void SourceInfo::introDependency(T &checker) { 201 if (flags & BCC_SKIP_DEP_SHA1) { 202 return; 203 } 204 205 switch (type) { 206 case SourceKind::Buffer: 207 checker.addDependency(BCC_APK_RESOURCE, buffer.resName, sha1); 208 break; 209 210 case SourceKind::File: 211 checker.addDependency(BCC_FILE_RESOURCE, file.path, sha1); 212 break; 213 214 default: 215 break; 216 } 217} 218 219#if USE_OLD_JIT 220template void SourceInfo::introDependency<CacheReader>(CacheReader &); 221template void SourceInfo::introDependency<CacheWriter>(CacheWriter &); 222#endif 223 224#if USE_MCJIT 225template void SourceInfo::introDependency<MCCacheWriter>(MCCacheWriter &); 226template void SourceInfo::introDependency<MCCacheReader>(MCCacheReader &); 227#endif 228#endif // USE_CACHE 229 230 231} // namespace bcc 232