blob: fcd92a3d5b7e91885eb922fcecc7347f6e2f9924 [file] [log] [blame]
Logan1f028c02010-11-27 01:02:48 +08001/*
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#define LOG_TAG "bcc"
18#include <cutils/log.h>
19
Logan1f028c02010-11-27 01:02:48 +080020#if defined(__arm__)
21# define DEFAULT_ARM_CODEGEN
22# define PROVIDE_ARM_CODEGEN
23#elif defined(__i386__)
24# define DEFAULT_X86_CODEGEN
25# define PROVIDE_X86_CODEGEN
26#elif defined(__x86_64__)
27# define DEFAULT_X64_CODEGEN
28# define PROVIDE_X64_CODEGEN
29#endif
30
31#if defined(FORCE_ARM_CODEGEN)
32# define DEFAULT_ARM_CODEGEN
33# undef DEFAULT_X86_CODEGEN
34# undef DEFAULT_X64_CODEGEN
35# define PROVIDE_ARM_CODEGEN
36# undef PROVIDE_X86_CODEGEN
37# undef PROVIDE_X64_CODEGEN
38#elif defined(FORCE_X86_CODEGEN)
39# undef DEFAULT_ARM_CODEGEN
40# define DEFAULT_X86_CODEGEN
41# undef DEFAULT_X64_CODEGEN
42# undef PROVIDE_ARM_CODEGEN
43# define PROVIDE_X86_CODEGEN
44# undef PROVIDE_X64_CODEGEN
45#elif defined(FORCE_X64_CODEGEN)
46# undef DEFAULT_ARM_CODEGEN
47# undef DEFAULT_X86_CODEGEN
48# define DEFAULT_X64_CODEGEN
49# undef PROVIDE_ARM_CODEGEN
50# undef PROVIDE_X86_CODEGEN
51# define PROVIDE_X64_CODEGEN
52#endif
53
54#if defined(DEFAULT_ARM_CODEGEN)
Logandf23afa2010-11-27 11:04:54 +080055# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Logan1f028c02010-11-27 01:02:48 +080056#elif defined(DEFAULT_X86_CODEGEN)
Logandf23afa2010-11-27 11:04:54 +080057# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Logan1f028c02010-11-27 01:02:48 +080058#elif defined(DEFAULT_X64_CODEGEN)
Logandf23afa2010-11-27 11:04:54 +080059# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Logan1f028c02010-11-27 01:02:48 +080060#endif
61
62#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
63# define ARM_USE_VFP
64#endif
65
Loganc4395232010-11-27 18:54:17 +080066#include "Compiler.h"
Logan1f028c02010-11-27 01:02:48 +080067
Loganeb3d12b2010-12-16 06:20:18 +080068#include "ContextManager.h"
69
Logandf23afa2010-11-27 11:04:54 +080070#include "llvm/ADT/StringRef.h"
Logan1f028c02010-11-27 01:02:48 +080071
Logandf23afa2010-11-27 11:04:54 +080072#include "llvm/Analysis/Passes.h"
Logan1f028c02010-11-27 01:02:48 +080073
Logan1f028c02010-11-27 01:02:48 +080074#include "llvm/Bitcode/ReaderWriter.h"
75
Logan1f028c02010-11-27 01:02:48 +080076#include "llvm/CodeGen/Passes.h"
Logan1f028c02010-11-27 01:02:48 +080077#include "llvm/CodeGen/RegAllocRegistry.h"
78#include "llvm/CodeGen/SchedulerRegistry.h"
Logan1f028c02010-11-27 01:02:48 +080079
Logandf23afa2010-11-27 11:04:54 +080080#include "llvm/Transforms/IPO.h"
81#include "llvm/Transforms/Scalar.h"
82
83#include "llvm/Target/SubtargetFeature.h"
84#include "llvm/Target/TargetData.h"
85#include "llvm/Target/TargetMachine.h"
86#include "llvm/Target/TargetOptions.h"
87#include "llvm/Target/TargetRegistry.h"
88#include "llvm/Target/TargetSelect.h"
89
90#include "llvm/Support/ErrorHandling.h"
91#include "llvm/Support/MemoryBuffer.h"
92
93#include "llvm/GlobalValue.h"
94#include "llvm/Linker.h"
95#include "llvm/LLVMContext.h"
96#include "llvm/Metadata.h"
97#include "llvm/Module.h"
98#include "llvm/PassManager.h"
99#include "llvm/Value.h"
100
101#include <errno.h>
102#include <sys/file.h>
Logandf23afa2010-11-27 11:04:54 +0800103#include <sys/stat.h>
104#include <sys/types.h>
105#include <unistd.h>
106
Shih-wei Liao2417cef2010-12-16 05:51:40 -0800107#include <cutils/properties.h>
108
Logandf23afa2010-11-27 11:04:54 +0800109#include <string>
110#include <vector>
Logan1f028c02010-11-27 01:02:48 +0800111
Logandf23afa2010-11-27 11:04:54 +0800112namespace {
Logan1f028c02010-11-27 01:02:48 +0800113
114#define TEMP_FAILURE_RETRY1(exp) ({ \
115 typeof (exp) _rc; \
116 do { \
117 _rc = (exp); \
118 } while (_rc == -1 && errno == EINTR); \
119 _rc; })
120
121
Logandf23afa2010-11-27 11:04:54 +0800122int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg) {
Logan1f028c02010-11-27 01:02:48 +0800123 while (count != 0) {
124 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
125 if (actual < 0) {
126 int err = errno;
127 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
128 return err;
129 } else if (actual != (ssize_t) count) {
130 LOGD("%s: partial write (will retry): (%d of %zd)\n",
131 logMsg, (int) actual, count);
132 buf = (const void*) (((const uint8_t*) buf) + actual);
133 }
134 count -= actual;
135 }
136
137 return 0;
138}
139
Logan9d94f162010-12-07 12:39:25 +0800140inline uint32_t statModifyTime(char const *filepath) {
141 struct stat st;
142
143 if (stat(filepath, &st) < 0) {
144 LOGE("Unable to stat \'%s\', with reason: %s\n", filepath, strerror(errno));
145 return 0;
146 }
147
148 return static_cast<uint32_t>(st.st_mtime);
149}
150
151static char const libRSPath[] = "/system/lib/libRS.so";
152
153static char const libBccPath[] = "/system/lib/libbcc.so";
154
Logandf23afa2010-11-27 11:04:54 +0800155} // namespace anonymous
156
Logan1f028c02010-11-27 01:02:48 +0800157
158namespace bcc {
159
160//////////////////////////////////////////////////////////////////////////////
161// BCC Compiler Static Variables
162//////////////////////////////////////////////////////////////////////////////
163
164bool Compiler::GlobalInitialized = false;
Shih-wei Liao931501a2010-12-16 04:43:04 -0800165const char *Compiler::resNames[64];
166int Compiler::resNamesMmaped[64];
Logan1f028c02010-11-27 01:02:48 +0800167
Logan1f028c02010-11-27 01:02:48 +0800168// Code generation optimization level for the compiler
169llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
170
171std::string Compiler::Triple;
172
173std::string Compiler::CPU;
174
175std::vector<std::string> Compiler::Features;
176
177// The named of metadata node that pragma resides (should be synced with
178// slang.cpp)
179const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
180
181// The named of metadata node that export variable name resides (should be
182// synced with slang_rs_metadata.h)
183const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
184
185// The named of metadata node that export function name resides (should be
186// synced with slang_rs_metadata.h)
187const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
188
189
190//////////////////////////////////////////////////////////////////////////////
191// Compiler
192//////////////////////////////////////////////////////////////////////////////
193
194void Compiler::GlobalInitialization() {
195 if (GlobalInitialized)
196 return;
197
198 // if (!llvm::llvm_is_multithreaded())
199 // llvm::llvm_start_multithreaded();
200
201 // Set Triple, CPU and Features here
202 Triple = TARGET_TRIPLE_STRING;
203
204 // TODO(sliao): NEON for JIT
205 // Features.push_back("+neon");
206 // Features.push_back("+vmlx");
207 // Features.push_back("+neonfp");
208 Features.push_back("+vfp3");
209 Features.push_back("+d16");
210
211#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
212 LLVMInitializeARMTargetInfo();
213 LLVMInitializeARMTarget();
214#if defined(USE_DISASSEMBLER)
215 LLVMInitializeARMDisassembler();
216 LLVMInitializeARMAsmPrinter();
217#endif
218#endif
219
220#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
221 LLVMInitializeX86TargetInfo();
222 LLVMInitializeX86Target();
223#if defined(USE_DISASSEMBLER)
224 LLVMInitializeX86Disassembler();
225 LLVMInitializeX86AsmPrinter();
226#endif
227#endif
228
229#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
230 LLVMInitializeX86TargetInfo();
231 LLVMInitializeX86Target();
232#if defined(USE_DISASSEMBLER)
233 LLVMInitializeX86Disassembler();
234 LLVMInitializeX86AsmPrinter();
235#endif
236#endif
237
238 // -O0: llvm::CodeGenOpt::None
239 // -O1: llvm::CodeGenOpt::Less
240 // -O2: llvm::CodeGenOpt::Default
241 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liao72f67a62010-12-14 13:36:15 -0800242 CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
Logan1f028c02010-11-27 01:02:48 +0800243
244 // Below are the global settings to LLVM
245
246 // Disable frame pointer elimination optimization
247 llvm::NoFramePointerElim = false;
248
249 // Use hardfloat ABI
250 //
251 // TODO(all): Need to detect the CPU capability and decide whether to use
252 // softfp. To use softfp, change following 2 lines to
253 //
254 // llvm::FloatABIType = llvm::FloatABI::Soft;
255 // llvm::UseSoftFloat = true;
256 //
Shih-wei Liaoe728cb82010-12-15 15:20:47 -0800257 llvm::FloatABIType = llvm::FloatABI::Soft;
Logan1f028c02010-11-27 01:02:48 +0800258 llvm::UseSoftFloat = false;
259
260 // BCC needs all unknown symbols resolved at JIT/compilation time.
261 // So we don't need any dynamic relocation model.
262 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
263
264#if defined(DEFAULT_X64_CODEGEN)
265 // Data address in X86_64 architecture may reside in a far-away place
266 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
267#else
268 // This is set for the linker (specify how large of the virtual addresses
269 // we can access for all unknown symbols.)
270 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
271#endif
272
273 // Register the scheduler
274 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
275
276 // Register allocation policy:
277 // createFastRegisterAllocator: fast but bad quality
278 // createLinearScanRegisterAllocator: not so fast but good quality
279 llvm::RegisterRegAlloc::setDefault
280 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
281 llvm::createFastRegisterAllocator :
282 llvm::createLinearScanRegisterAllocator);
283
284 GlobalInitialized = true;
285}
286
287
288void Compiler::LLVMErrorHandler(void *UserData, const std::string &Message) {
289 std::string *Error = static_cast<std::string*>(UserData);
290 Error->assign(Message);
291 LOGE("%s", Message.c_str());
292 exit(1);
293}
294
295
296CodeMemoryManager *Compiler::createCodeMemoryManager() {
297 mCodeMemMgr.reset(new CodeMemoryManager());
298 return mCodeMemMgr.get();
299}
300
301
302CodeEmitter *Compiler::createCodeEmitter() {
303 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
304 return mCodeEmitter.get();
305}
306
307
308Compiler::Compiler()
Shih-wei Liao931501a2010-12-16 04:43:04 -0800309 : mResId(-1),
310 mUseCache(false),
Logan1f028c02010-11-27 01:02:48 +0800311 mCacheNew(false),
312 mCacheFd(-1),
Loganb9b04162010-12-20 16:36:57 +0800313 mSourceModTime(0),
314 mSourceCRC32(0),
Logan1f028c02010-11-27 01:02:48 +0800315 mCacheMapAddr(NULL),
316 mCacheHdr(NULL),
317 mCacheSize(0),
318 mCacheDiff(0),
319 mCodeDataAddr(NULL),
320 mpSymbolLookupFn(NULL),
321 mpSymbolLookupContext(NULL),
322 mContext(NULL),
323 mModule(NULL),
324 mHasLinked(false) /* Turn off linker */ {
325 llvm::remove_fatal_error_handler();
326 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
327 mContext = new llvm::LLVMContext();
328 return;
329}
330
331
Shih-wei Liao2417cef2010-12-16 05:51:40 -0800332static bool getProp(const char *str) {
333 char buf[PROPERTY_VALUE_MAX];
334 property_get(str, buf, "0");
335 return 0 != strcmp(buf, "0");
336}
337
338
Logan1f028c02010-11-27 01:02:48 +0800339int Compiler::readBC(const char *bitcode,
340 size_t bitcodeSize,
Loganb9b04162010-12-20 16:36:57 +0800341 long bitcodeFileModTime,
342 long bitcodeFileCRC32,
Shih-wei Liaoe6a18512010-12-09 12:38:10 -0800343 const BCCchar *resName,
344 const BCCchar *cacheDir) {
Logan1f028c02010-11-27 01:02:48 +0800345 GlobalInitialization();
346
Shih-wei Liao931501a2010-12-16 04:43:04 -0800347 int i = 0;
348 for ( ; i < 64; i++) {
349 if (!Compiler::resNames[i]) {
350 // First encounter of resName
351 //
352 resNames[i] = strdup(resName);
353 resNamesMmaped[i] = 1;
354 break;
355 }
356
357 if (!strcmp(resName, Compiler::resNames[i])) { // Cache hit
358
359 // Cache hit and some Script instance is still using this cache
360 if (Compiler::resNamesMmaped[i]) {
361 resName = NULL; // Force the turn-off of caching
362 }
363 Compiler::resNamesMmaped[i]++;
364
365 break;
366 }
367 }
368
369 if (i == 64) {
370 LOGE("resNames[] full");
371 resName = NULL; // Force the turn-off of caching
372 } else {
373 mResId = i;
374 }
375
Jason Sams8e695a92010-12-17 13:46:38 -0800376 this->props.mNoCache = !getProp("debug.bcc.cache");
Shih-wei Liao2417cef2010-12-16 05:51:40 -0800377 if (this->props.mNoCache) {
378 resName = NULL;
379 }
380
Loganb9b04162010-12-20 16:36:57 +0800381 // Assign bitcodeFileModTime to mSourceModTime, and bitcodeFileCRC32 to
382 // mSourceCRC32, so that the checkHeaderAndDependencies can use them.
383 mSourceModTime = bitcodeFileModTime;
384 mSourceCRC32 = bitcodeFileCRC32;
385
Logan1f028c02010-11-27 01:02:48 +0800386 if (resName) {
387 // Turn on mUseCache mode iff
388 // 1. Has resName
389 // and, assuming USE_RELOCATE is false:
390 // 2. Later running code doesn't violate the following condition:
391 // mCodeDataAddr (set in loadCacheFile()) ==
392 // mCacheHdr->cachedCodeDataAddr
393 //
394 // BTW, this condition is achievable only when in the earlier
395 // cache-generating run,
396 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
397 // which means the mmap'ed is in the reserved area,
398 //
399 // Note: Upon violation, mUseCache will be set back to false.
400 mUseCache = true;
401
Shih-wei Liaoe6a18512010-12-09 12:38:10 -0800402 mCacheFd = openCacheFile(resName, cacheDir, true /* createIfMissing */);
Logan1f028c02010-11-27 01:02:48 +0800403 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
Logan139dc3c2010-12-03 01:32:05 +0800404 return -mCacheFd - 1;
Logan1f028c02010-11-27 01:02:48 +0800405 }
406 }
407
408 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
409
410 if (bitcode == NULL || bitcodeSize <= 0)
411 return 0;
412
413 // Package input to object MemoryBuffer
414 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
415 llvm::StringRef(bitcode, bitcodeSize)));
416
417 if (MEM.get() == NULL) {
418 setError("Error reading input program bitcode into memory");
419 return hasError();
420 }
421
422 // Read the input Bitcode as a Module
423 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
424 MEM.reset();
425 return hasError();
426}
427
428
429int Compiler::linkBC(const char *bitcode, size_t bitcodeSize) {
430 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
431
432 if (bitcode == NULL || bitcodeSize <= 0)
433 return 0;
434
435 if (mModule == NULL) {
436 setError("No module presents for linking");
437 return hasError();
438 }
439
440 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
441 llvm::StringRef(bitcode, bitcodeSize)));
442
443 if (MEM.get() == NULL) {
444 setError("Error reading input library bitcode into memory");
445 return hasError();
446 }
447
448 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
449 *mContext,
450 &mError));
451 if (Lib.get() == NULL)
452 return hasError();
453
454 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
455 return hasError();
456
457 // Everything for linking should be settled down here with no error occurs
458 mHasLinked = true;
459 return hasError();
460}
461
462
463// interface for bccLoadBinary()
464int Compiler::loadCacheFile() {
465 // Check File Descriptor
466 if (mCacheFd < 0) {
467 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
468 goto giveup;
469 }
470
471 // Check File Size
472 struct stat statCacheFd;
473 if (fstat(mCacheFd, &statCacheFd) < 0) {
474 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
475 goto giveup;
476 }
477
478 mCacheSize = statCacheFd.st_size;
479
480 if (mCacheSize < sizeof(oBCCHeader) ||
481 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
482 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
483 goto giveup;
484 }
485
486 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
487 LOGE("Unable to seek to 0: %s\n", strerror(errno));
488 goto giveup;
489 }
490
491 // Part 1. Deal with the non-codedata section first
492 {
493 // Read cached file and perform quick integrity check
494
495 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
496 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
497 (unsigned int)mCacheSize,
498 (unsigned long long int)heuristicCodeOffset);
499
500 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
501 if (!mCacheMapAddr) {
502 flock(mCacheFd, LOCK_UN);
503 LOGE("allocation failed.\n");
504 goto bail;
505 }
506
507 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
508 heuristicCodeOffset));
509 if (nread != (size_t)heuristicCodeOffset) {
510 LOGE("read(mCacheFd) failed\n");
511 goto bail;
512 }
513
514 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
515 // Sanity check
516 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
517 LOGE("assertion failed: heuristic code offset is not correct.\n");
518 goto bail;
519 }
520 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
521 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
522 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
523 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
524 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
525
526 // Verify the Cache File
527 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
528 LOGE("bad magic word\n");
529 goto bail;
530 }
531
532 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
533 LOGE("bad oBCC version 0x%08x\n",
534 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
535 goto bail;
536 }
537
538 if (mCacheSize < mCacheHdr->relocOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800539 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
Logan1f028c02010-11-27 01:02:48 +0800540 LOGE("relocate table overflow\n");
541 goto bail;
542 }
543
544 if (mCacheSize < mCacheHdr->exportVarsOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800545 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
Logan1f028c02010-11-27 01:02:48 +0800546 LOGE("export variables table overflow\n");
547 goto bail;
548 }
549
550 if (mCacheSize < mCacheHdr->exportFuncsOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800551 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
Logan1f028c02010-11-27 01:02:48 +0800552 LOGE("export functions table overflow\n");
553 goto bail;
554 }
555
556 if (mCacheSize < mCacheHdr->exportPragmasOffset +
Logan7cc1baf2010-11-28 23:46:11 +0800557 mCacheHdr->exportPragmasSize) {
Logan1f028c02010-11-27 01:02:48 +0800558 LOGE("export pragmas table overflow\n");
559 goto bail;
560 }
561
562 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
563 LOGE("code cache overflow\n");
564 goto bail;
565 }
566
567 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
568 LOGE("data (global variable) cache overflow\n");
569 goto bail;
570 }
571
572 long pagesize = sysconf(_SC_PAGESIZE);
573 if (mCacheHdr->codeOffset % pagesize != 0) {
574 LOGE("code offset must aligned to pagesize\n");
575 goto bail;
576 }
577 }
578
579 // Part 2. Deal with the codedata section
580 {
581 long pagesize = sysconf(_SC_PAGESIZE);
582
583 if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
Loganeb3d12b2010-12-16 06:20:18 +0800584 char *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
Logan1f028c02010-11-27 01:02:48 +0800585
Shih-wei Liao931501a2010-12-16 04:43:04 -0800586 // Try to allocate context (i.e., mmap) at cached address directly.
Loganeb3d12b2010-12-16 06:20:18 +0800587 mCodeDataAddr = allocateContext(addr, mCacheFd, mCacheHdr->codeOffset);
Shih-wei Liao931501a2010-12-16 04:43:04 -0800588 // LOGI("mCodeDataAddr=%x", mCodeDataAddr);
Logan1f028c02010-11-27 01:02:48 +0800589
Loganeb3d12b2010-12-16 06:20:18 +0800590 if (!mCodeDataAddr) {
591 // Unable to allocate at cached address. Give up.
592 flock(mCacheFd, LOCK_UN);
593 goto bail;
594 }
Logan1f028c02010-11-27 01:02:48 +0800595
Shih-wei Liao931501a2010-12-16 04:43:04 -0800596 // Above: Already checked some cache-hit conditions:
597 // mCodeDataAddr && mCodeDataAddr != MAP_FAILED
598 // Next: Check cache-hit conditions when USE_RELOCATE == false:
599 // mCodeDataAddr == addr
600 // (When USE_RELOCATE == true, we still don't need to relocate
601 // if mCodeDataAddr == addr. But if mCodeDataAddr != addr,
602 // that means "addr" is taken by previous mmap and we need
603 // to relocate the cache file content to mcodeDataAddr.)
604
605#if !USE_RELOCATE
606 if (mCodeDataAddr != addr) {
607 flock(mCacheFd, LOCK_UN);
608 goto bail;
609 }
610#else // USE_RELOCATE == true
611
612#endif // End of #if #else !USE_RELOCATE
613
Loganeb3d12b2010-12-16 06:20:18 +0800614 // Check the checksum of code and data
615 {
616 uint32_t sum = mCacheHdr->checksum;
617 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
Logan1f028c02010-11-27 01:02:48 +0800618
Loganeb3d12b2010-12-16 06:20:18 +0800619 for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
620 sum ^= *ptr++;
Logan1f028c02010-11-27 01:02:48 +0800621 }
Loganeb3d12b2010-12-16 06:20:18 +0800622
623 if (sum != 0) {
624 LOGE("Checksum check failed\n");
625 goto bail;
626 }
627
628 LOGI("Passed checksum even parity verification.\n");
629 }
Logan1f028c02010-11-27 01:02:48 +0800630
Loganeb3d12b2010-12-16 06:20:18 +0800631 flock(mCacheFd, LOCK_UN);
632 return 0; // loadCacheFile succeed!
Shih-wei Liao931501a2010-12-16 04:43:04 -0800633 } // End of "if(mCacheHdr->cachedCodeDataAddr % pagesize == 0)"
634 } // End of Part 2. Deal with the codedata section
635
636// Execution will reach here only if (mCacheHdr->cachedCodeDataAddr % pagesize != 0)
Logan1f028c02010-11-27 01:02:48 +0800637
638#if !USE_RELOCATE
Shih-wei Liao931501a2010-12-16 04:43:04 -0800639 // Note: If Android.mk set USE_RELOCATE to false, we are not allowed to
640 // relocate to the new mCodeDataAddr. That is, we got no
641 // choice but give up this cache-hit case: go ahead and recompile the code
Logan1f028c02010-11-27 01:02:48 +0800642
643 flock(mCacheFd, LOCK_UN);
644 goto bail;
Shih-wei Liao931501a2010-12-16 04:43:04 -0800645
Logan1f028c02010-11-27 01:02:48 +0800646#else
647
648 // Note: Currently, relocation code is not working. Give up now.
649 flock(mCacheFd, LOCK_UN);
650 goto bail;
651
Shih-wei Liao931501a2010-12-16 04:43:04 -0800652 // The following code is not working. Don't use them.
653 // Rewrite them asap.
Logan1f028c02010-11-27 01:02:48 +0800654#if 0
655 {
656 // Try to allocate at arbitary address. And perform relocation.
657 mCacheMapAddr = (char *) mmap(0,
658 mCacheSize,
659 PROT_READ | PROT_EXEC | PROT_WRITE,
660 MAP_PRIVATE,
661 mCacheFd,
662 0);
663
664 if (mCacheMapAddr == MAP_FAILED) {
665 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
666 flock(mCacheFd, LOCK_UN);
667 goto giveup;
668 }
669
670 flock(mCacheFd, LOCK_UN);
671 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
672
673 // Relocate
674 mCacheDiff = mCodeDataAddr -
675 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
676
677 if (mCacheDiff) { // To relocate
678 if (mCacheHdr->rootAddr) {
679 mCacheHdr->rootAddr += mCacheDiff;
680 }
681
682 if (mCacheHdr->initAddr) {
683 mCacheHdr->initAddr += mCacheDiff;
684 }
685
686 oBCCRelocEntry *cachedRelocTable =
687 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
688 mCacheHdr->relocOffset);
689
690 std::vector<llvm::MachineRelocation> relocations;
691
692 // Read in the relocs
693 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
694 oBCCRelocEntry *entry = &cachedRelocTable[i];
695
696 llvm::MachineRelocation reloc =
697 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
698 (unsigned)entry->relocType, 0, 0);
699
700 reloc.setResultPointer(
701 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
702
703 relocations.push_back(reloc);
704 }
705
706 // Rewrite machine code using llvm::TargetJITInfo relocate
707 {
708 llvm::TargetMachine *TM = NULL;
709 const llvm::Target *Target;
710 std::string FeaturesStr;
711
712 // Create TargetMachine
713 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
714 if (hasError())
715 goto bail;
716
717 if (!CPU.empty() || !Features.empty()) {
718 llvm::SubtargetFeatures F;
719 F.setCPU(CPU);
720 for (std::vector<std::string>::const_iterator I = Features.begin(),
721 E = Features.end(); I != E; I++)
722 F.AddFeature(*I);
723 FeaturesStr = F.getString();
724 }
725
726 TM = Target->createTargetMachine(Triple, FeaturesStr);
727 if (TM == NULL) {
728 setError("Failed to create target machine implementation for the"
729 " specified triple '" + Triple + "'");
730 goto bail;
731 }
732
733 TM->getJITInfo()->relocate(mCodeDataAddr,
734 &relocations[0], relocations.size(),
735 (unsigned char *)mCodeDataAddr+MaxCodeSize);
736
737 if (mCodeEmitter.get()) {
738 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
739 reinterpret_cast<uint8_t*>(mCodeDataAddr),
740 2 * 1024 /*MaxCodeSize*/,
741 false);
742 }
743
744 delete TM;
745 }
746 } // End of if (mCacheDiff)
747
748 return 0; // Success!
749 }
Shih-wei Liao931501a2010-12-16 04:43:04 -0800750#endif // End of #if 0
751
752#endif // End of #if #else USE_RELOCATE
Logan1f028c02010-11-27 01:02:48 +0800753
754bail:
755 if (mCacheMapAddr) {
756 free(mCacheMapAddr);
757 }
758
Loganeb3d12b2010-12-16 06:20:18 +0800759 if (mCodeDataAddr) {
760 deallocateContext(mCodeDataAddr);
Logan1f028c02010-11-27 01:02:48 +0800761 }
762
763 mCacheMapAddr = NULL;
764 mCacheHdr = NULL;
765 mCodeDataAddr = NULL;
766
767giveup:
768 return 1;
769}
770
771// interace for bccCompileBC()
772int Compiler::compile() {
773 llvm::TargetData *TD = NULL;
774
775 llvm::TargetMachine *TM = NULL;
776 const llvm::Target *Target;
777 std::string FeaturesStr;
778
779 llvm::FunctionPassManager *CodeGenPasses = NULL;
780
781 const llvm::NamedMDNode *PragmaMetadata;
782 const llvm::NamedMDNode *ExportVarMetadata;
783 const llvm::NamedMDNode *ExportFuncMetadata;
784
785 if (mModule == NULL) // No module was loaded
786 return 0;
787
788 // Create TargetMachine
789 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
790 if (hasError())
791 goto on_bcc_compile_error;
792
793 if (!CPU.empty() || !Features.empty()) {
794 llvm::SubtargetFeatures F;
795 F.setCPU(CPU);
Logana4994f52010-11-27 14:06:02 +0800796
797 for (std::vector<std::string>::const_iterator
798 I = Features.begin(), E = Features.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +0800799 F.AddFeature(*I);
Logana4994f52010-11-27 14:06:02 +0800800 }
801
Logan1f028c02010-11-27 01:02:48 +0800802 FeaturesStr = F.getString();
803 }
804
805 TM = Target->createTargetMachine(Triple, FeaturesStr);
806 if (TM == NULL) {
807 setError("Failed to create target machine implementation for the"
808 " specified triple '" + Triple + "'");
809 goto on_bcc_compile_error;
810 }
811
812 // Create memory manager for creation of code emitter later.
813 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
814 setError("Failed to startup memory management for further compilation");
815 goto on_bcc_compile_error;
816 }
817 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
818
819 // Create code emitter
820 if (!mCodeEmitter.get()) {
821 if (!createCodeEmitter()) {
822 setError("Failed to create machine code emitter to complete"
823 " the compilation");
824 goto on_bcc_compile_error;
825 }
826 } else {
827 // Reuse the code emitter
828 mCodeEmitter->reset();
829 }
830
831 mCodeEmitter->setTargetMachine(*TM);
832 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
833 mpSymbolLookupContext);
834
835 // Get target data from Module
836 TD = new llvm::TargetData(mModule);
837
838 // Load named metadata
839 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
840 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
841 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
842
843 // Create LTO passes and run them on the mModule
844 if (mHasLinked) {
845 llvm::TimePassesIsEnabled = true; // TODO(all)
846 llvm::PassManager LTOPasses;
847 LTOPasses.add(new llvm::TargetData(*TD));
848
849 std::vector<const char*> ExportSymbols;
850
851 // A workaround for getting export variable and function name. Will refine
852 // it soon.
853 if (ExportVarMetadata) {
854 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
855 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
856 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
857 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
858 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
859 llvm::StringRef ExportVarName =
860 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
861 ExportSymbols.push_back(ExportVarName.data());
862 }
863 }
864 }
865 }
866
867 if (ExportFuncMetadata) {
868 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
869 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
870 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
871 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
872 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
873 llvm::StringRef ExportFuncName =
874 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
875 ExportSymbols.push_back(ExportFuncName.data());
876 }
877 }
878 }
879 }
880 // root() and init() are born to be exported
881 ExportSymbols.push_back("root");
882 ExportSymbols.push_back("init");
883
884 // We now create passes list performing LTO. These are copied from
885 // (including comments) llvm::createStandardLTOPasses().
886
887 // Internalize all other symbols not listed in ExportSymbols
888 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
889
890 // Propagate constants at call sites into the functions they call. This
891 // opens opportunities for globalopt (and inlining) by substituting
892 // function pointers passed as arguments to direct uses of functions.
893 LTOPasses.add(llvm::createIPSCCPPass());
894
895 // Now that we internalized some globals, see if we can hack on them!
896 LTOPasses.add(llvm::createGlobalOptimizerPass());
897
898 // Linking modules together can lead to duplicated global constants, only
899 // keep one copy of each constant...
900 LTOPasses.add(llvm::createConstantMergePass());
901
902 // Remove unused arguments from functions...
903 LTOPasses.add(llvm::createDeadArgEliminationPass());
904
905 // Reduce the code after globalopt and ipsccp. Both can open up
906 // significant simplification opportunities, and both can propagate
907 // functions through function pointers. When this happens, we often have
908 // to resolve varargs calls, etc, so let instcombine do this.
909 LTOPasses.add(llvm::createInstructionCombiningPass());
910
911 // Inline small functions
912 LTOPasses.add(llvm::createFunctionInliningPass());
913
914 // Remove dead EH info.
915 LTOPasses.add(llvm::createPruneEHPass());
916
917 // Internalize the globals again after inlining
918 LTOPasses.add(llvm::createGlobalOptimizerPass());
919
920 // Remove dead functions.
921 LTOPasses.add(llvm::createGlobalDCEPass());
922
923 // If we didn't decide to inline a function, check to see if we can
924 // transform it to pass arguments by value instead of by reference.
925 LTOPasses.add(llvm::createArgumentPromotionPass());
926
927 // The IPO passes may leave cruft around. Clean up after them.
928 LTOPasses.add(llvm::createInstructionCombiningPass());
929 LTOPasses.add(llvm::createJumpThreadingPass());
930
931 // Break up allocas
932 LTOPasses.add(llvm::createScalarReplAggregatesPass());
933
934 // Run a few AA driven optimizations here and now, to cleanup the code.
935 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
936 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
937
938 // Hoist loop invariants.
939 LTOPasses.add(llvm::createLICMPass());
940
941 // Remove redundancies.
942 LTOPasses.add(llvm::createGVNPass());
943
944 // Remove dead memcpys.
945 LTOPasses.add(llvm::createMemCpyOptPass());
946
947 // Nuke dead stores.
948 LTOPasses.add(llvm::createDeadStoreEliminationPass());
949
950 // Cleanup and simplify the code after the scalar optimizations.
951 LTOPasses.add(llvm::createInstructionCombiningPass());
952
953 LTOPasses.add(llvm::createJumpThreadingPass());
954
955 // Delete basic blocks, which optimization passes may have killed.
956 LTOPasses.add(llvm::createCFGSimplificationPass());
957
958 // Now that we have optimized the program, discard unreachable functions.
959 LTOPasses.add(llvm::createGlobalDCEPass());
960
961 LTOPasses.run(*mModule);
962 }
963
964 // Create code-gen pass to run the code emitter
965 CodeGenPasses = new llvm::FunctionPassManager(mModule);
966 CodeGenPasses->add(TD); // Will take the ownership of TD
967
968 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
969 *mCodeEmitter,
970 CodeGenOptLevel)) {
971 setError("The machine code emission is not supported by BCC on target '"
972 + Triple + "'");
973 goto on_bcc_compile_error;
974 }
975
976 // Run the pass (the code emitter) on every non-declaration function in the
977 // module
978 CodeGenPasses->doInitialization();
979 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
980 I != E; I++) {
981 if (!I->isDeclaration()) {
982 CodeGenPasses->run(*I);
983 }
984 }
985
986 CodeGenPasses->doFinalization();
987
988 // Copy the global address mapping from code emitter and remapping
989 if (ExportVarMetadata) {
990 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
991 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
992 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
993 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
994 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
995 llvm::StringRef ExportVarName =
996 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
997
998 CodeEmitter::global_addresses_const_iterator I, E;
999 for (I = mCodeEmitter->global_address_begin(),
1000 E = mCodeEmitter->global_address_end();
1001 I != E; I++) {
1002 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
1003 continue;
1004 if (ExportVarName == I->first->getName()) {
1005 mExportVars.push_back(I->second);
1006 break;
1007 }
1008 }
1009 if (I != mCodeEmitter->global_address_end())
1010 continue; // found
1011 }
1012 }
1013 // if reaching here, we know the global variable record in metadata is
1014 // not found. So we make an empty slot
1015 mExportVars.push_back(NULL);
1016 }
1017 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
1018 "Number of slots doesn't match the number of export variables!");
1019 }
1020
1021 if (ExportFuncMetadata) {
1022 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
1023 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
1024 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
1025 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
1026 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
1027 llvm::StringRef ExportFuncName =
1028 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
1029 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
1030 }
1031 }
1032 }
1033 }
1034
1035 // Tell code emitter now can release the memory using during the JIT since
1036 // we have done the code emission
1037 mCodeEmitter->releaseUnnecessary();
1038
1039 // Finally, read pragma information from the metadata node of the @Module if
1040 // any.
1041 if (PragmaMetadata)
1042 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
1043 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
1044 if (Pragma != NULL &&
1045 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
1046 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
1047 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
1048
1049 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
1050 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
1051 llvm::StringRef PragmaName =
1052 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
1053 llvm::StringRef PragmaValue =
1054 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
1055
1056 mPragmas.push_back(
1057 std::make_pair(std::string(PragmaName.data(),
1058 PragmaName.size()),
1059 std::string(PragmaValue.data(),
1060 PragmaValue.size())));
1061 }
1062 }
1063 }
1064
1065on_bcc_compile_error:
1066 // LOGE("on_bcc_compiler_error");
1067 if (CodeGenPasses) {
1068 delete CodeGenPasses;
1069 } else if (TD) {
1070 delete TD;
1071 }
1072 if (TM)
1073 delete TM;
1074
1075 if (mError.empty()) {
1076 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
1077 genCacheFile();
Shih-wei Liao931501a2010-12-16 04:43:04 -08001078 // LOGI("DONE generating cache file");
Logan1f028c02010-11-27 01:02:48 +08001079 flock(mCacheFd, LOCK_UN);
1080 }
1081
1082 return false;
1083 }
1084
1085 // LOGE(getErrorMessage());
1086 return true;
1087}
1088
1089
1090// interface for bccGetScriptLabel()
1091void *Compiler::lookup(const char *name) {
1092 void *addr = NULL;
1093 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1094 if (!strcmp(name, "root")) {
1095 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
1096 } else if (!strcmp(name, "init")) {
1097 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
1098 }
1099 return addr;
1100 }
1101
1102 if (mCodeEmitter.get())
1103 // Find function pointer
1104 addr = mCodeEmitter->lookup(name);
1105 return addr;
1106}
1107
1108
1109// Interface for bccGetExportVars()
1110void Compiler::getExportVars(BCCsizei *actualVarCount,
1111 BCCsizei maxVarCount,
1112 BCCvoid **vars) {
1113 int varCount;
1114
1115 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1116 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
1117 if (actualVarCount)
1118 *actualVarCount = varCount;
1119 if (varCount > maxVarCount)
1120 varCount = maxVarCount;
1121 if (vars) {
1122 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
1123 mCacheHdr->exportVarsOffset);
1124
1125 for (int i = 0; i < varCount; i++) {
Logan7cc1baf2010-11-28 23:46:11 +08001126 *vars = (BCCvoid *)((char *)(*cachedVars) + mCacheDiff);
1127 vars++;
Logan1f028c02010-11-27 01:02:48 +08001128 cachedVars++;
1129 }
1130 }
1131 return;
1132 }
1133
1134 varCount = mExportVars.size();
1135 if (actualVarCount)
1136 *actualVarCount = varCount;
1137 if (varCount > maxVarCount)
1138 varCount = maxVarCount;
1139 if (vars) {
Logana4994f52010-11-27 14:06:02 +08001140 for (ExportVarList::const_iterator
1141 I = mExportVars.begin(), E = mExportVars.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +08001142 *vars++ = *I;
1143 }
1144 }
Logan1f028c02010-11-27 01:02:48 +08001145}
1146
1147
1148// Interface for bccGetExportFuncs()
1149void Compiler::getExportFuncs(BCCsizei *actualFuncCount,
1150 BCCsizei maxFuncCount,
1151 BCCvoid **funcs) {
1152 int funcCount;
1153
1154 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
1155 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
1156 if (actualFuncCount)
1157 *actualFuncCount = funcCount;
1158 if (funcCount > maxFuncCount)
1159 funcCount = maxFuncCount;
1160 if (funcs) {
1161 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
1162 mCacheHdr->exportFuncsOffset);
1163
1164 for (int i = 0; i < funcCount; i++) {
Logan7cc1baf2010-11-28 23:46:11 +08001165 *funcs = (BCCvoid *)((char *)(*cachedFuncs) + mCacheDiff);
1166 funcs++;
Logan1f028c02010-11-27 01:02:48 +08001167 cachedFuncs++;
1168 }
1169 }
1170 return;
1171 }
1172
1173 funcCount = mExportFuncs.size();
1174 if (actualFuncCount)
1175 *actualFuncCount = funcCount;
1176 if (funcCount > maxFuncCount)
1177 funcCount = maxFuncCount;
1178 if (funcs) {
Logan7cc1baf2010-11-28 23:46:11 +08001179 for (ExportFuncList::const_iterator
1180 I = mExportFuncs.begin(), E = mExportFuncs.end(); I != E; I++) {
Logan1f028c02010-11-27 01:02:48 +08001181 *funcs++ = *I;
1182 }
1183 }
Logan1f028c02010-11-27 01:02:48 +08001184}
1185
1186
1187// Interface for bccGetPragmas()
1188void Compiler::getPragmas(BCCsizei *actualStringCount,
1189 BCCsizei maxStringCount,
1190 BCCchar **strings) {
1191 int stringCount;
Logan7cc1baf2010-11-28 23:46:11 +08001192
Logan1f028c02010-11-27 01:02:48 +08001193 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Logan7cc1baf2010-11-28 23:46:11 +08001194 stringCount = static_cast<int>(mCacheHdr->exportPragmasCount) * 2;
1195
Logan1f028c02010-11-27 01:02:48 +08001196 if (actualStringCount)
Logan7cc1baf2010-11-28 23:46:11 +08001197 *actualStringCount = stringCount;
1198
1199 if (stringCount > maxStringCount)
1200 stringCount = maxStringCount;
1201
1202 if (strings) {
1203 char *pragmaTab = mCacheMapAddr + mCacheHdr->exportPragmasOffset;
1204
1205 oBCCPragmaEntry *cachedPragmaEntries = (oBCCPragmaEntry *)pragmaTab;
1206
1207 for (int i = 0; stringCount >= 2; stringCount -= 2, i++) {
1208 *strings++ = pragmaTab + cachedPragmaEntries[i].pragmaNameOffset;
1209 *strings++ = pragmaTab + cachedPragmaEntries[i].pragmaValueOffset;
1210 }
1211 }
1212
Logan1f028c02010-11-27 01:02:48 +08001213 return;
1214 }
1215
1216 stringCount = mPragmas.size() * 2;
1217
1218 if (actualStringCount)
1219 *actualStringCount = stringCount;
1220 if (stringCount > maxStringCount)
1221 stringCount = maxStringCount;
1222 if (strings) {
Logan7cc1baf2010-11-28 23:46:11 +08001223 size_t i = 0;
Logan1f028c02010-11-27 01:02:48 +08001224 for (PragmaList::const_iterator it = mPragmas.begin();
Logan7cc1baf2010-11-28 23:46:11 +08001225 stringCount >= 2; stringCount -= 2, it++, ++i) {
Logan1f028c02010-11-27 01:02:48 +08001226 *strings++ = const_cast<BCCchar*>(it->first.c_str());
1227 *strings++ = const_cast<BCCchar*>(it->second.c_str());
1228 }
1229 }
1230
1231 return;
1232}
1233
1234
1235// Interface for bccGetFunctions()
1236void Compiler::getFunctions(BCCsizei *actualFunctionCount,
1237 BCCsizei maxFunctionCount,
1238 BCCchar **functions) {
1239 if (mCodeEmitter.get())
1240 mCodeEmitter->getFunctionNames(actualFunctionCount,
1241 maxFunctionCount,
1242 functions);
1243 else
1244 *actualFunctionCount = 0;
1245
1246 return;
1247}
1248
1249
1250// Interface for bccGetFunctionBinary()
1251void Compiler::getFunctionBinary(BCCchar *function,
1252 BCCvoid **base,
1253 BCCsizei *length) {
1254 if (mCodeEmitter.get()) {
1255 mCodeEmitter->getFunctionBinary(function, base, length);
1256 } else {
1257 *base = NULL;
1258 *length = 0;
1259 }
1260 return;
1261}
1262
1263
1264Compiler::~Compiler() {
Shih-wei Liao931501a2010-12-16 04:43:04 -08001265 if (mResId >= 0) {
1266 Compiler::resNamesMmaped[mResId]--;
1267 }
1268
Logan1f028c02010-11-27 01:02:48 +08001269 if (!mCodeMemMgr.get()) {
1270 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
1271 // managed by CodeMemoryManager.
1272
Loganeb3d12b2010-12-16 06:20:18 +08001273 if (mCodeDataAddr) {
1274 deallocateContext(mCodeDataAddr);
Logan1f028c02010-11-27 01:02:48 +08001275 }
1276
1277 if (mCacheMapAddr) {
1278 free(mCacheMapAddr);
1279 }
1280
1281 mCodeDataAddr = 0;
1282 mCacheMapAddr = 0;
1283 }
1284
1285 delete mModule;
Logan1f028c02010-11-27 01:02:48 +08001286 delete mContext;
Logana4994f52010-11-27 14:06:02 +08001287
1288 // llvm::llvm_shutdown();
Logan1f028c02010-11-27 01:02:48 +08001289}
1290
1291
1292// Design of caching EXE:
1293// ======================
1294// 1. Each process will have virtual address available starting at 0x7e00000.
1295// E.g., Books and Youtube all have its own 0x7e00000. Next, we should
1296// minimize the chance of needing to do relocation INSIDE an app too.
1297//
1298// 2. Each process will have ONE class static variable called BccCodeAddr.
1299// I.e., even though the Compiler class will have multiple Compiler objects,
1300// e.g, one object for carousel.rs and the other for pageturn.rs,
1301// both Compiler objects will share 1 static variable called BccCodeAddr.
1302//
1303// Key observation: Every app (process) initiates, say 3, scripts (which
1304// correspond to 3 Compiler objects) in the same order, usually.
1305//
1306// So, we should mmap to, e.g., 0x7e00000, 0x7e40000, 0x7e80000 for the 3
1307// scripts, respectively. Each time, BccCodeAddr should be updated after
1308// JITTing a script. BTW, in ~Compiler(), BccCodeAddr should NOT be
1309// decremented back by CodeDataSize. I.e., for 3 scripts: A, B, C,
1310// even if it's A -> B -> ~B -> C -> ~C -> B -> C ... no relocation will
1311// ever be needed.)
1312//
1313// If we are lucky, then we don't need relocation ever, since next time the
1314// application gets run, the 3 scripts are likely created in the SAME order.
1315//
1316//
1317// End-to-end algorithm on when to caching and when to JIT:
1318// ========================================================
1319// Prologue:
1320// ---------
1321// Assertion: bccReadBC() is always called and is before bccCompileBC(),
1322// bccLoadBinary(), ...
1323//
1324// Key variable definitions: Normally,
1325// Compiler::BccCodeAddr: non-zero if (USE_CACHE)
1326// | (Stricter, because currently relocation doesn't work. So mUseCache only
1327// | when BccCodeAddr is nonzero.)
1328// V
1329// mUseCache: In addition to (USE_CACHE), resName is non-zero
1330// Note: mUseCache will be set to false later on whenever we find that caching
1331// won't work. E.g., when mCodeDataAddr != mCacheHdr->cachedCodeDataAddr.
1332// This is because currently relocation doesn't work.
1333// | (Stricter, initially)
1334// V
1335// mCacheFd: In addition, >= 0 if openCacheFile() returns >= 0
1336// | (Stricter)
1337// V
1338// mCacheNew: In addition, mCacheFd's size is 0, so need to call genCacheFile()
1339// at the end of compile()
1340//
1341//
1342// Main algorithm:
1343// ---------------
1344// #if !USE_RELOCATE
1345// Case 1. ReadBC() doesn't detect a cache file:
1346// compile(), which calls genCacheFile() at the end.
1347// Note: mCacheNew will guard the invocation of genCacheFile()
1348// Case 2. ReadBC() find a cache file
1349// loadCacheFile(). But if loadCacheFile() failed, should go to Case 1.
1350// #endif
1351
1352// Note: loadCacheFile() and genCacheFile() go hand in hand
1353void Compiler::genCacheFile() {
1354 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
1355 LOGE("Unable to seek to 0: %s\n", strerror(errno));
1356 return;
1357 }
1358
1359 bool codeOffsetNeedPadding = false;
1360
1361 uint32_t offset = sizeof(oBCCHeader);
1362
1363 // BCC Cache File Header
1364 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
1365
1366 if (!hdr) {
1367 LOGE("Unable to allocate oBCCHeader.\n");
1368 return;
1369 }
1370
1371 // Magic Words
1372 memcpy(hdr->magic, OBCC_MAGIC, 4);
1373 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
1374
1375 // Timestamp
Loganb9b04162010-12-20 16:36:57 +08001376 hdr->sourceWhen = mSourceModTime;
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001377 hdr->rslibWhen = 0; // TODO(sliao)
Logan9d94f162010-12-07 12:39:25 +08001378 hdr->libRSWhen = statModifyTime(libRSPath);
1379 hdr->libbccWhen = statModifyTime(libBccPath);
Logan1f028c02010-11-27 01:02:48 +08001380
Loganb9b04162010-12-20 16:36:57 +08001381 // Source Bitcode File CRC32
1382 hdr->sourceCRC32 = mSourceCRC32;
1383
Logan1f028c02010-11-27 01:02:48 +08001384 // Current Memory Address (Saved for Recalculation)
1385 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
1386 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
1387 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
1388
Loganb9b04162010-12-20 16:36:57 +08001389 // Check libRS isThreadable
1390 if (!mCodeEmitter) {
1391 hdr->libRSThreadable = 0;
1392 } else {
1393 hdr->libRSThreadable =
1394 (uint32_t) mCodeEmitter->mpSymbolLookupFn(mpSymbolLookupContext,
1395 "__isThreadable");
1396 }
1397
Logan1f028c02010-11-27 01:02:48 +08001398 // Relocation Table Offset and Entry Count
1399 hdr->relocOffset = sizeof(oBCCHeader);
1400 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
1401
Logan7cc1baf2010-11-28 23:46:11 +08001402 offset += hdr->relocCount * sizeof(oBCCRelocEntry);
Logan1f028c02010-11-27 01:02:48 +08001403
1404 // Export Variable Table Offset and Entry Count
1405 hdr->exportVarsOffset = offset;
1406 hdr->exportVarsCount = mExportVars.size();
1407
1408 offset += hdr->exportVarsCount * sizeof(uint32_t);
1409
1410 // Export Function Table Offset and Entry Count
1411 hdr->exportFuncsOffset = offset;
1412 hdr->exportFuncsCount = mExportFuncs.size();
1413
1414 offset += hdr->exportFuncsCount * sizeof(uint32_t);
1415
1416 // Export Pragmas Table Offset and Entry Count
1417 hdr->exportPragmasOffset = offset;
Logan7cc1baf2010-11-28 23:46:11 +08001418 hdr->exportPragmasCount = mPragmas.size();
1419 hdr->exportPragmasSize = hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
Logan1f028c02010-11-27 01:02:48 +08001420
Logan7cc1baf2010-11-28 23:46:11 +08001421 offset += hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
1422
1423 for (PragmaList::const_iterator
1424 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1425 offset += I->first.size() + 1;
1426 offset += I->second.size() + 1;
1427 hdr->exportPragmasSize += I->first.size() + I->second.size() + 2;
1428 }
Logan1f028c02010-11-27 01:02:48 +08001429
1430 // Code Offset and Size
1431
1432 { // Always pad to the page boundary for now
1433 long pagesize = sysconf(_SC_PAGESIZE);
1434
1435 if (offset % pagesize > 0) {
1436 codeOffsetNeedPadding = true;
1437 offset += pagesize - (offset % pagesize);
1438 }
1439 }
1440
1441 hdr->codeOffset = offset;
1442 hdr->codeSize = MaxCodeSize;
1443
1444 offset += hdr->codeSize;
1445
1446 // Data (Global Variable) Offset and Size
1447 hdr->dataOffset = offset;
1448 hdr->dataSize = MaxGlobalVarSize;
1449
1450 offset += hdr->dataSize;
1451
1452 // Checksum
1453#if 1
1454 {
1455 // Note: This is an simple checksum implementation that are using xor
1456 // to calculate even parity (for code and data only).
1457
1458 uint32_t sum = 0;
1459 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
1460
Loganeb3d12b2010-12-16 06:20:18 +08001461 for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
Logan1f028c02010-11-27 01:02:48 +08001462 sum ^= *ptr++;
1463 }
1464
1465 hdr->checksum = sum;
1466 }
1467#else
1468 hdr->checksum = 0; // Set Field checksum. TODO(all)
1469#endif
1470
1471 // Write Header
1472 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
1473 sizeof(oBCCHeader), "Write oBCC header");
1474
1475 // Write Relocation Entry Table
1476 {
1477 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
1478
1479 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
1480
1481 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
1482 allocSize, "Write Relocation Entries");
1483 }
1484
1485 // Write Export Variables Table
1486 {
1487 uint32_t *record, *ptr;
1488
1489 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
1490 ptr = record;
1491
1492 if (!record) {
1493 goto bail;
1494 }
1495
1496 for (ExportVarList::const_iterator I = mExportVars.begin(),
1497 E = mExportVars.end(); I != E; I++) {
1498 *ptr++ = reinterpret_cast<uint32_t>(*I);
1499 }
1500
1501 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1502 hdr->exportVarsCount * sizeof(uint32_t),
1503 "Write ExportVars");
1504
1505 free(record);
1506 }
1507
1508 // Write Export Functions Table
1509 {
1510 uint32_t *record, *ptr;
1511
1512 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
1513 ptr = record;
1514
1515 if (!record) {
1516 goto bail;
1517 }
1518
1519 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
1520 E = mExportFuncs.end(); I != E; I++) {
1521 *ptr++ = reinterpret_cast<uint32_t>(*I);
1522 }
1523
1524 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1525 hdr->exportFuncsCount * sizeof(uint32_t),
1526 "Write ExportFuncs");
1527
1528 free(record);
1529 }
1530
1531
Logan7cc1baf2010-11-28 23:46:11 +08001532 // Write Export Pragmas Table
1533 {
1534 uint32_t pragmaEntryOffset =
1535 hdr->exportPragmasCount * sizeof(oBCCPragmaEntry);
Logan1f028c02010-11-27 01:02:48 +08001536
Logan7cc1baf2010-11-28 23:46:11 +08001537 for (PragmaList::const_iterator
1538 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1539 oBCCPragmaEntry entry;
1540
1541 entry.pragmaNameOffset = pragmaEntryOffset;
1542 entry.pragmaNameSize = I->first.size();
1543 pragmaEntryOffset += entry.pragmaNameSize + 1;
1544
1545 entry.pragmaValueOffset = pragmaEntryOffset;
1546 entry.pragmaValueSize = I->second.size();
1547 pragmaEntryOffset += entry.pragmaValueSize + 1;
1548
1549 sysWriteFully(mCacheFd, (char *)&entry, sizeof(oBCCPragmaEntry),
1550 "Write export pragma entry");
1551 }
1552
1553 for (PragmaList::const_iterator
1554 I = mPragmas.begin(), E = mPragmas.end(); I != E; ++I) {
1555 sysWriteFully(mCacheFd, I->first.c_str(), I->first.size() + 1,
1556 "Write export pragma name string");
1557 sysWriteFully(mCacheFd, I->second.c_str(), I->second.size() + 1,
1558 "Write export pragma value string");
1559 }
1560 }
Logan1f028c02010-11-27 01:02:48 +08001561
1562 if (codeOffsetNeedPadding) {
1563 // requires additional padding
1564 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
1565 }
1566
1567 // Write Generated Code and Global Variable
1568 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
1569 "Write code and global variable");
1570
1571 goto close_return;
1572
1573bail:
1574 if (ftruncate(mCacheFd, 0) != 0) {
1575 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
1576 }
1577
1578close_return:
1579 free(hdr);
1580 close(mCacheFd);
1581 mCacheFd = -1;
1582}
1583
1584
1585// OpenCacheFile() returns fd of the cache file.
1586// Input:
1587// BCCchar *resName: Used to genCacheFileName()
1588// bool createIfMissing: If false, turn off caching
1589// Output:
1590// returns fd: If -1: Failed
1591// mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
1592// cache file's file descriptor
1593// Note: openCacheFile() will check the cache file's validity,
1594// such as Magic number, sourceWhen... dependencies.
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001595int Compiler::openCacheFile(const BCCchar *resName,
1596 const BCCchar *cacheDir,
1597 bool createIfMissing) {
Logan1f028c02010-11-27 01:02:48 +08001598 int fd, cc;
1599 struct stat fdStat, fileStat;
1600 bool readOnly = false;
1601
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001602 char *cacheFileName = genCacheFileName(cacheDir, resName, ".oBCC");
Logan1f028c02010-11-27 01:02:48 +08001603
1604 mCacheNew = false;
1605
1606retry:
1607 /*
1608 * Try to open the cache file. If we've been asked to,
1609 * create it if it doesn't exist.
1610 */
1611 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
1612 if (fd < 0) {
1613 fd = open(cacheFileName, O_RDONLY, 0);
1614 if (fd < 0) {
1615 if (createIfMissing) {
1616 LOGW("Can't open bcc-cache '%s': %s\n",
1617 cacheFileName, strerror(errno));
1618 mUseCache = false;
1619 }
1620 return fd;
1621 }
1622 readOnly = true;
1623 }
1624
1625 /*
1626 * Grab an exclusive lock on the cache file. If somebody else is
1627 * working on it, we'll block here until they complete.
1628 */
1629 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
1630 cacheFileName, fd);
1631
1632 cc = flock(fd, LOCK_EX | LOCK_NB);
1633 if (cc != 0) {
1634 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
1635 cc = flock(fd, LOCK_EX);
1636 }
1637
1638 if (cc != 0) {
1639 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
1640 close(fd);
1641 return -1;
1642 }
1643 LOGV("bcc: locked cache file\n");
1644
1645 /*
1646 * Check to see if the fd we opened and locked matches the file in
1647 * the filesystem. If they don't, then somebody else unlinked ours
1648 * and created a new file, and we need to use that one instead. (If
1649 * we caught them between the unlink and the create, we'll get an
1650 * ENOENT from the file stat.)
1651 */
1652 cc = fstat(fd, &fdStat);
1653 if (cc != 0) {
1654 LOGE("Can't stat open file '%s'\n", cacheFileName);
1655 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1656 goto close_fail;
1657 }
1658 cc = stat(cacheFileName, &fileStat);
1659 if (cc != 0 ||
1660 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
1661 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
1662 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1663 flock(fd, LOCK_UN);
1664 close(fd);
1665 usleep(250 * 1000); // if something is hosed, don't peg machine
1666 goto retry;
1667 }
1668
1669 /*
1670 * We have the correct file open and locked. If the file size is zero,
1671 * then it was just created by us, and we want to fill in some fields
1672 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
1673 * verify that the fields in the header match our expectations, and
1674 * reset the file if they don't.
1675 */
1676 if (fdStat.st_size == 0) {
1677 if (readOnly) { // The device is readOnly --> close_fail
1678 LOGW("bcc: file has zero length and isn't writable\n");
1679 goto close_fail;
1680 }
1681 /*cc = createEmptyHeader(fd);
1682 if (cc != 0)
1683 goto close_fail;
1684 */
1685 mCacheNew = true;
1686 LOGV("bcc: successfully initialized new cache file\n");
1687 } else {
1688 // Calculate sourceWhen
1689 // XXX
Loganb9b04162010-12-20 16:36:57 +08001690 long sourceWhen = mSourceModTime;
Logan1f028c02010-11-27 01:02:48 +08001691 uint32_t rslibWhen = 0;
Logan9d94f162010-12-07 12:39:25 +08001692 uint32_t libRSWhen = statModifyTime(libRSPath);
1693 uint32_t libbccWhen = statModifyTime(libBccPath);
Logan1f028c02010-11-27 01:02:48 +08001694 if (!checkHeaderAndDependencies(fd,
1695 sourceWhen,
1696 rslibWhen,
1697 libRSWhen,
1698 libbccWhen)) {
1699 // If checkHeaderAndDependencies returns 0: FAILED
1700 // Will truncate the file and retry to createIfMissing the file
1701
1702 if (readOnly) { // Shouldn't be readonly.
1703 /*
1704 * We could unlink and rewrite the file if we own it or
1705 * the "sticky" bit isn't set on the directory. However,
1706 * we're not able to truncate it, which spoils things. So,
1707 * give up now.
1708 */
1709 if (createIfMissing) {
1710 LOGW("Cached file %s is stale and not writable\n",
1711 cacheFileName);
1712 }
1713 goto close_fail;
1714 }
1715
1716 /*
1717 * If we truncate the existing file before unlinking it, any
1718 * process that has it mapped will fail when it tries to touch
1719 * the pages? Probably OK because we use MAP_PRIVATE.
1720 */
1721 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
1722 cacheFileName);
1723 if (ftruncate(fd, 0) != 0) {
1724 LOGW("Warning: unable to truncate cache file '%s': %s\n",
1725 cacheFileName, strerror(errno));
1726 /* keep going */
1727 }
1728 if (unlink(cacheFileName) != 0) {
1729 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
1730 cacheFileName, errno, strerror(errno));
1731 /* keep going; permission failure should probably be fatal */
1732 }
1733 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1734 flock(fd, LOCK_UN);
1735 close(fd);
1736 goto retry;
1737 } else {
1738 // Got cacheFile! Good to go.
1739 LOGV("Good cache file\n");
1740 }
1741 }
1742
1743 assert(fd >= 0);
1744 return fd;
1745
1746close_fail:
1747 flock(fd, LOCK_UN);
1748 close(fd);
1749 return -1;
1750} // End of openCacheFile()
1751
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001752// Input: cacheDir
1753// Input: resName
1754// Input: extName
1755//
1756// Note: cacheFile = resName + extName
1757//
1758// Output: Returns cachePath == cacheDir + cacheFile
1759char *Compiler::genCacheFileName(const char *cacheDir,
1760 const char *resName,
1761 const char *extName) {
1762 char cachePath[512];
1763 char cacheFile[sizeof(cachePath)];
1764 const size_t kBufLen = sizeof(cachePath) - 1;
Logan1f028c02010-11-27 01:02:48 +08001765
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001766 cacheFile[0] = '\0';
1767 // Note: resName today is usually something like
1768 // "/com.android.fountain:raw/fountain"
1769 if (resName[0] != '/') {
1770 // Get the absolute path of the raw/***.bc file.
1771
1772 // Generate the absolute path. This doesn't do everything it
1773 // should, e.g. if resName is "./out/whatever" it doesn't crunch
1774 // the leading "./" out because this if-block is not triggered,
1775 // but it'll make do.
1776 //
1777 if (getcwd(cacheFile, kBufLen) == NULL) {
Logan1f028c02010-11-27 01:02:48 +08001778 LOGE("Can't get CWD while opening raw/***.bc file\n");
1779 return NULL;
1780 }
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001781 // Append "/" at the end of cacheFile so far.
1782 strncat(cacheFile, "/", kBufLen);
1783 }
1784
1785 // cacheFile = resName + extName
1786 //
1787 strncat(cacheFile, resName, kBufLen);
1788 if (extName != NULL) {
Logan1f028c02010-11-27 01:02:48 +08001789 // TODO(srhines): strncat() is a bit dangerous
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001790 strncat(cacheFile, extName, kBufLen);
Logan1f028c02010-11-27 01:02:48 +08001791 }
1792
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001793 // Turn the path into a flat filename by replacing
1794 // any slashes after the first one with '@' characters.
1795 char *cp = cacheFile + 1;
Logan1f028c02010-11-27 01:02:48 +08001796 while (*cp != '\0') {
1797 if (*cp == '/') {
1798 *cp = '@';
1799 }
1800 cp++;
1801 }
1802
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001803 // Tack on the file name for the actual cache file path.
1804 strncpy(cachePath, cacheDir, kBufLen);
1805 strncat(cachePath, cacheFile, kBufLen);
Logan1f028c02010-11-27 01:02:48 +08001806
Shih-wei Liaoe6a18512010-12-09 12:38:10 -08001807 LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
1808 return strdup(cachePath);
Logan1f028c02010-11-27 01:02:48 +08001809}
1810
1811/*
1812 * Read the oBCC header, verify it, then read the dependent section
1813 * and verify that data as well.
1814 *
1815 * On successful return, the file will be seeked immediately past the
1816 * oBCC header.
1817 */
1818bool Compiler::checkHeaderAndDependencies(int fd,
Loganb9b04162010-12-20 16:36:57 +08001819 long sourceWhen,
Logan1f028c02010-11-27 01:02:48 +08001820 uint32_t rslibWhen,
1821 uint32_t libRSWhen,
1822 uint32_t libbccWhen) {
Logan1f028c02010-11-27 01:02:48 +08001823 oBCCHeader optHdr;
Logan1f028c02010-11-27 01:02:48 +08001824
Loganb9b04162010-12-20 16:36:57 +08001825 // The header is guaranteed to be at the start of the cached file.
1826 // Seek to the start position.
Logan1f028c02010-11-27 01:02:48 +08001827 if (lseek(fd, 0, SEEK_SET) != 0) {
1828 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
Loganb9b04162010-12-20 16:36:57 +08001829 return false;
Logan1f028c02010-11-27 01:02:48 +08001830 }
1831
Loganb9b04162010-12-20 16:36:57 +08001832 // Read and do trivial verification on the bcc header. The header is
1833 // always in host byte order.
1834 ssize_t nread = read(fd, &optHdr, sizeof(optHdr));
1835 if (nread < 0) {
Logan1f028c02010-11-27 01:02:48 +08001836 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
Loganb9b04162010-12-20 16:36:57 +08001837 return false;
1838 } else if (nread != sizeof(optHdr)) {
Logan1f028c02010-11-27 01:02:48 +08001839 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
Loganb9b04162010-12-20 16:36:57 +08001840 (int) nread, sizeof(optHdr));
1841 return false;
Logan1f028c02010-11-27 01:02:48 +08001842 }
1843
Loganb9b04162010-12-20 16:36:57 +08001844 uint8_t const *magic = optHdr.magic;
Logan1f028c02010-11-27 01:02:48 +08001845 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
1846 /* not an oBCC file, or previous attempt was interrupted */
1847 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
1848 magic[0], magic[1], magic[2], magic[3]);
Loganb9b04162010-12-20 16:36:57 +08001849 return false;
Logan1f028c02010-11-27 01:02:48 +08001850 }
1851
Loganb9b04162010-12-20 16:36:57 +08001852 uint8_t const *magicVer = optHdr.magicVersion;
Logancd045f92010-12-06 19:04:53 +08001853 if (memcmp(magicVer, OBCC_MAGIC_VERS, 4) != 0) {
Logan1f028c02010-11-27 01:02:48 +08001854 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
1855 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
Loganb9b04162010-12-20 16:36:57 +08001856 return false;
Logan1f028c02010-11-27 01:02:48 +08001857 }
1858
Loganb9b04162010-12-20 16:36:57 +08001859 // Check the file dependencies
Logan1f028c02010-11-27 01:02:48 +08001860
Loganb9b04162010-12-20 16:36:57 +08001861 if (optHdr.sourceWhen && (optHdr.sourceWhen != sourceWhen)) {
1862 LOGI("bcc: source file mod time mismatch (%08lx vs %08lx)\n",
1863 (unsigned long)optHdr.sourceWhen, (unsigned long)sourceWhen);
1864 return false;
Logan1f028c02010-11-27 01:02:48 +08001865 }
Loganb9b04162010-12-20 16:36:57 +08001866
1867 uint32_t val;
Shih-wei Liaodb69c552010-12-07 01:37:48 -08001868
Logan1f028c02010-11-27 01:02:48 +08001869 val = optHdr.rslibWhen;
1870 if (val && (val != rslibWhen)) {
1871 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
1872 val, rslibWhen);
Loganb9b04162010-12-20 16:36:57 +08001873 return false;
Logan1f028c02010-11-27 01:02:48 +08001874 }
Loganb9b04162010-12-20 16:36:57 +08001875
Logan1f028c02010-11-27 01:02:48 +08001876 val = optHdr.libRSWhen;
1877 if (val && (val != libRSWhen)) {
1878 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
1879 val, libRSWhen);
Loganb9b04162010-12-20 16:36:57 +08001880 return false;
Logan1f028c02010-11-27 01:02:48 +08001881 }
Loganb9b04162010-12-20 16:36:57 +08001882
Logan1f028c02010-11-27 01:02:48 +08001883 val = optHdr.libbccWhen;
1884 if (val && (val != libbccWhen)) {
1885 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
1886 val, libbccWhen);
Loganb9b04162010-12-20 16:36:57 +08001887 return false;
1888 }
1889
1890 // Check the CRC32 of the file
1891 if (optHdr.sourceCRC32 && optHdr.sourceCRC32 != mSourceCRC32) {
1892 LOGI("bcc: libbcc bitcode file crc32 mismatch (%08lx vs %08lx)\n",
1893 optHdr.sourceCRC32, mSourceCRC32);
1894 return false;
1895 }
1896
1897 // Check the cache file has __isThreadable or not. If it is present,
1898 // then we have to call mpSymbolLookupFn for __clearThreadable.
1899 if (optHdr.libRSThreadable && mpSymbolLookupFn) {
1900 mpSymbolLookupFn(mpSymbolLookupContext, "__clearThreadable");
Logan1f028c02010-11-27 01:02:48 +08001901 }
1902
1903 return true;
Logan1f028c02010-11-27 01:02:48 +08001904}
1905
1906} // namespace bcc