blob: 1c7cd49796622c41398f88f70fa3fdb24c7dec3a [file] [log] [blame]
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001/*
Zonr Chang932648d2010-10-13 22:23:56 +08002 * Copyright 2010, The Android Open Source Project
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003 *
Zonr Chang932648d2010-10-13 22:23:56 +08004 * 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.
Shih-wei Liao77ed6142010-04-07 12:21:42 -070015 */
16
Zonr Chang932648d2010-10-13 22:23:56 +080017// Bitcode compiler (bcc) for Android:
18// This is an eager-compilation JIT running on Android.
19
Loganc0b9f652010-11-24 22:33:16 +080020#define BCC_MMAP_IMG_BEGIN 0x7e000000
21#define BCC_MMAP_IMG_COUNT 5
22
23#define BCC_MMAP_IMG_CODE_SIZE (128 * 1024)
24#define BCC_MMAP_IMG_DATA_SIZE (128 * 1024)
25#define BCC_MMAP_IMG_SIZE (BCC_MMAP_IMG_CODE_SIZE + BCC_MMAP_IMG_DATA_SIZE)
26
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080027
Shih-wei Liaobc5ed672010-11-24 01:53:02 -080028// Design of caching EXE:
29// ======================
Shih-wei Liao1c6ac2b2010-11-23 00:32:32 -080030// 1. Each process will have virtual address available starting at 0x7e00000.
31// E.g., Books and Youtube all have its own 0x7e00000. Next, we should
32// minimize the chance of needing to do relocation INSIDE an app too.
33//
34// 2. Each process will have ONE class static variable called BccCodeAddr.
35// I.e., even though the Compiler class will have multiple Compiler objects,
36// e.g, one object for carousel.rs and the other for pageturn.rs,
37// both Compiler objects will share 1 static variable called BccCodeAddr.
38//
39// Key observation: Every app (process) initiates, say 3, scripts (which
40// correspond to 3 Compiler objects) in the same order, usually.
41//
42// So, we should mmap to, e.g., 0x7e00000, 0x7e40000, 0x7e80000 for the 3
43// scripts, respectively. Each time, BccCodeAddr should be updated after
44// JITTing a script. BTW, in ~Compiler(), BccCodeAddr should NOT be
45// decremented back by CodeDataSize. I.e., for 3 scripts: A, B, C,
46// even if it's A -> B -> ~B -> C -> ~C -> B -> C ... no relocation will
47// ever be needed.)
48//
49// If we are lucky, then we don't need relocation ever, since next time the
50// application gets run, the 3 scripts are likely created in the SAME order.
Shih-wei Liaobc5ed672010-11-24 01:53:02 -080051//
52//
53// End-to-end algorithm on when to caching and when to JIT:
54// ========================================================
55// Prologue:
56// ---------
57// Assertion: bccReadBC() is always called and is before bccCompileBC(),
58// bccLoadBinary(), ...
59//
60// Key variable definitions: Normally,
61// Compiler::BccCodeAddr: non-zero if (USE_CACHE)
62// | (Stricter, because currently relocation doesn't work. So mUseCache only
63// | when BccCodeAddr is nonzero.)
64// V
65// mUseCache: In addition to (USE_CACHE), resName is non-zero
66// Note: mUseCache will be set to false later on whenever we find that caching
67// won't work. E.g., when mCodeDataAddr != mCacheHdr->cachedCodeDataAddr.
68// This is because currently relocation doesn't work.
69// | (Stricter, initially)
70// V
71// mCacheFd: In addition, >= 0 if openCacheFile() returns >= 0
72// | (Stricter)
73// V
74// mCacheNew: In addition, mCacheFd's size is 0, so need to call genCacheFile()
75// at the end of compile()
76//
77//
78// Main algorithm:
79// ---------------
80// #if !USE_RELOCATE
81// Case 1. ReadBC() doesn't detect a cache file:
82// compile(), which calls genCacheFile() at the end.
83// Note: mCacheNew will guard the invocation of genCacheFile()
84// Case 2. ReadBC() find a cache file
85// loadCacheFile(). But if loadCacheFile() failed, should go to Case 1.
86// #endif
Shih-wei Liao1c6ac2b2010-11-23 00:32:32 -080087
Shih-wei Liao77ed6142010-04-07 12:21:42 -070088#define LOG_TAG "bcc"
89#include <cutils/log.h>
90
91#include <ctype.h>
92#include <errno.h>
93#include <limits.h>
94#include <stdarg.h>
95#include <stdint.h>
96#include <stdio.h>
97#include <stdlib.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080098#include <stddef.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070099#include <string.h>
100#include <unistd.h>
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700101#include <sys/mman.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800102#include <sys/file.h>
103#include <sys/stat.h>
104#include <sys/types.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700105
106#include <cutils/hashmap.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800107#include <utils/StopWatch.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700108
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700109#if defined(__arm__)
Zonr Chang932648d2010-10-13 22:23:56 +0800110# define DEFAULT_ARM_CODEGEN
111# define PROVIDE_ARM_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700112#elif defined(__i386__)
Zonr Chang932648d2010-10-13 22:23:56 +0800113# define DEFAULT_X86_CODEGEN
114# define PROVIDE_X86_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700115#elif defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +0800116# define DEFAULT_X64_CODEGEN
117# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700118#endif
119
120#if defined(FORCE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800121# define DEFAULT_ARM_CODEGEN
122# undef DEFAULT_X86_CODEGEN
123# undef DEFAULT_X64_CODEGEN
124# define PROVIDE_ARM_CODEGEN
125# undef PROVIDE_X86_CODEGEN
126# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700127#elif defined(FORCE_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800128# undef DEFAULT_ARM_CODEGEN
129# define DEFAULT_X86_CODEGEN
130# undef DEFAULT_X64_CODEGEN
131# undef PROVIDE_ARM_CODEGEN
132# define PROVIDE_X86_CODEGEN
133# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700134#elif defined(FORCE_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800135# undef DEFAULT_ARM_CODEGEN
136# undef DEFAULT_X86_CODEGEN
137# define DEFAULT_X64_CODEGEN
138# undef PROVIDE_ARM_CODEGEN
139# undef PROVIDE_X86_CODEGEN
140# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700141#endif
142
143#if defined(DEFAULT_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800144# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700145#elif defined(DEFAULT_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800146# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700147#elif defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800148# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700149#endif
150
151#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
Zonr Chang932648d2010-10-13 22:23:56 +0800152# define ARM_USE_VFP
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700153#endif
154
155#include <bcc/bcc.h>
Logan30a36162010-11-26 23:29:13 +0800156#include <bcc/bcc_cache.h>
157#include "bcc_code_emitter.h"
158#include "bcc_code_mem_manager.h"
Loganfc9530e2010-11-26 19:49:07 +0800159#include "bcc_emitted_func_code.h"
Logan30a36162010-11-26 23:29:13 +0800160#include "bcc_runtime.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700161
Zonr Chang932648d2010-10-13 22:23:56 +0800162#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700163// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
164
Zonr Chang932648d2010-10-13 22:23:56 +0800165#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700166// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
167
168// #define PROVIDE_TRACE_CODEGEN
169
170#if defined(USE_DISASSEMBLER)
Loganf2dbef82010-11-26 19:58:08 +0800171# include "bcc_buff_mem_object.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800172# include "llvm/MC/MCInst.h"
173# include "llvm/MC/MCAsmInfo.h"
174# include "llvm/MC/MCInstPrinter.h"
175# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700176// If you want the disassemble results written to file, define this:
177# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700178#endif
179
180#include <set>
181#include <map>
182#include <list>
183#include <cmath>
184#include <string>
185#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800186#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700187
Zonr Chang932648d2010-10-13 22:23:56 +0800188// VMCore
189#include "llvm/Use.h"
190#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800191#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800192#include "llvm/Module.h"
193#include "llvm/Function.h"
194#include "llvm/Constant.h"
195#include "llvm/Constants.h"
196#include "llvm/Instruction.h"
197#include "llvm/PassManager.h"
198#include "llvm/LLVMContext.h"
199#include "llvm/GlobalValue.h"
200#include "llvm/Instructions.h"
201#include "llvm/OperandTraits.h"
202#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700203
204// System
Zonr Chang932648d2010-10-13 22:23:56 +0800205#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700206
207// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800208#include "llvm/ADT/APInt.h"
209#include "llvm/ADT/APFloat.h"
210#include "llvm/ADT/DenseMap.h"
211#include "llvm/ADT/ValueMap.h"
212#include "llvm/ADT/StringMap.h"
213#include "llvm/ADT/OwningPtr.h"
214#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700215
216// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800217#include "llvm/Target/TargetData.h"
218#include "llvm/Target/TargetSelect.h"
219#include "llvm/Target/TargetOptions.h"
220#include "llvm/Target/TargetMachine.h"
221#include "llvm/Target/TargetJITInfo.h"
222#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700223#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700224
225// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800226#include "llvm/Support/Casting.h"
227#include "llvm/Support/raw_ostream.h"
228#include "llvm/Support/ValueHandle.h"
229#include "llvm/Support/MemoryBuffer.h"
230#include "llvm/Support/MemoryObject.h"
231#include "llvm/Support/ManagedStatic.h"
232#include "llvm/Support/ErrorHandling.h"
233#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700234#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700235
236// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800237#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700238
239// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800240#include "llvm/CodeGen/Passes.h"
241#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700242#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700243#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700244#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700245#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700246#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700247#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700248#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700249#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700250
251// ExecutionEngine
252#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700253#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700254
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700255extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700256
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800257#define TEMP_FAILURE_RETRY1(exp) ({ \
258 typeof (exp) _rc; \
259 do { \
260 _rc = (exp); \
261 } while (_rc == -1 && errno == EINTR); \
262 _rc; })
263
264static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
265{
266 while (count != 0) {
267 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
268 if (actual < 0) {
269 int err = errno;
270 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
271 return err;
272 } else if (actual != (ssize_t) count) {
273 LOGD("%s: partial write (will retry): (%d of %zd)\n",
274 logMsg, (int) actual, count);
275 buf = (const void*) (((const uint8_t*) buf) + actual);
276 }
277 count -= actual;
278 }
279
280 return 0;
281}
282
Zonr Chang932648d2010-10-13 22:23:56 +0800283//
284// Compilation class that suits Android's needs.
285// (Support: no argument passed, ...)
286//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700287namespace bcc {
288
289class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800290 // This part is designed to be orthogonal to those exported bcc*() functions
291 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700292
Zonr Chang932648d2010-10-13 22:23:56 +0800293 //////////////////////////////////////////////////////////////////////////////
294 // The variable section below (e.g., Triple, CodeGenOptLevel)
295 // is initialized in GlobalInitialization()
296 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700297 static bool GlobalInitialized;
Loganc0b9f652010-11-24 22:33:16 +0800298 static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700299
Zonr Chang932648d2010-10-13 22:23:56 +0800300 // If given, this will be the name of the target triple to compile for.
301 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700302 static std::string Triple;
303
304 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700305
Zonr Chang932648d2010-10-13 22:23:56 +0800306 // End of section of GlobalInitializing variables
307 //////////////////////////////////////////////////////////////////////////////
308
309 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700310 static std::string CPU;
311
Zonr Chang932648d2010-10-13 22:23:56 +0800312 // The list of target specific features to enable or disable -- this should
313 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700314 static std::vector<std::string> Features;
315
316 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800317 const char *mName;
318 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700319 };
320 static struct Runtime Runtimes[];
321
322 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800323 if (GlobalInitialized)
324 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700325
Zonr Chang932648d2010-10-13 22:23:56 +0800326 // if (!llvm::llvm_is_multithreaded())
327 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700328
Zonr Chang932648d2010-10-13 22:23:56 +0800329 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700330 Triple = TARGET_TRIPLE_STRING;
331
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800332 // TODO(sliao): NEON for JIT
Zonr Chang932648d2010-10-13 22:23:56 +0800333 // Features.push_back("+neon");
334 // Features.push_back("+vmlx");
335 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700336 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700337 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700338
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700339#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
340 LLVMInitializeARMTargetInfo();
341 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700342#if defined(USE_DISASSEMBLER)
343 LLVMInitializeARMDisassembler();
344 LLVMInitializeARMAsmPrinter();
345#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700346#endif
347
348#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
349 LLVMInitializeX86TargetInfo();
350 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700351#if defined(USE_DISASSEMBLER)
352 LLVMInitializeX86Disassembler();
353 LLVMInitializeX86AsmPrinter();
354#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700355#endif
356
357#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
358 LLVMInitializeX86TargetInfo();
359 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700360#if defined(USE_DISASSEMBLER)
361 LLVMInitializeX86Disassembler();
362 LLVMInitializeX86AsmPrinter();
363#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700364#endif
365
Zonr Chang932648d2010-10-13 22:23:56 +0800366 // -O0: llvm::CodeGenOpt::None
367 // -O1: llvm::CodeGenOpt::Less
368 // -O2: llvm::CodeGenOpt::Default
369 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700370 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700371
Zonr Chang932648d2010-10-13 22:23:56 +0800372 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700373
Zonr Chang932648d2010-10-13 22:23:56 +0800374 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700375 llvm::NoFramePointerElim = false;
376
Zonr Chang932648d2010-10-13 22:23:56 +0800377 // Use hardfloat ABI
378 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800379 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800380 // softfp. To use softfp, change following 2 lines to
381 //
382 // llvm::FloatABIType = llvm::FloatABI::Soft;
383 // llvm::UseSoftFloat = true;
384 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700385 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700386 llvm::UseSoftFloat = false;
387
Zonr Chang932648d2010-10-13 22:23:56 +0800388 // BCC needs all unknown symbols resolved at JIT/compilation time.
389 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700390 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
391
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700392#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800393 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700394 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
395#else
Zonr Chang932648d2010-10-13 22:23:56 +0800396 // This is set for the linker (specify how large of the virtual addresses
397 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700398 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
399#endif
400
Zonr Chang932648d2010-10-13 22:23:56 +0800401 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700402 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
403
Zonr Chang932648d2010-10-13 22:23:56 +0800404 // Register allocation policy:
405 // createFastRegisterAllocator: fast but bad quality
406 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700407 llvm::RegisterRegAlloc::setDefault
408 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700409 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700410 llvm::createLinearScanRegisterAllocator);
411
412 GlobalInitialized = true;
413 return;
414 }
415
416 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800417 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700418 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700419 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800420 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700421 }
422
423 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700424 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700425 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700426
427 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700428 std::string mError;
429
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700430 inline bool hasError() const {
431 return !mError.empty();
432 }
Zonr Chang932648d2010-10-13 22:23:56 +0800433 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700434 mError.assign(Error); // Copying
435 return;
436 }
Zonr Chang932648d2010-10-13 22:23:56 +0800437 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700438 mError = Error;
439 return;
440 }
441
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800442 bool mUseCache; // Set by readBC()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800443 bool mCacheNew; // Set by readBC()
444 int mCacheFd; // Set by readBC()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800445 char *mCacheMapAddr; // Set by loadCacheFile() if mCacheNew is false
446 oBCCHeader *mCacheHdr; // Set by loadCacheFile()
447 size_t mCacheSize; // Set by loadCacheFile()
448 ptrdiff_t mCacheDiff; // Set by loadCacheFile()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800449 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
450 // Used by genCacheFile() for dumping
451
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700452 typedef std::list< std::pair<std::string, std::string> > PragmaList;
453 PragmaList mPragmas;
454
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700455 typedef std::list<void*> ExportVarList;
456 ExportVarList mExportVars;
457
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700458 typedef std::list<void*> ExportFuncList;
459 ExportFuncList mExportFuncs;
460
Zonr Chang932648d2010-10-13 22:23:56 +0800461 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700462 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800463 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700464 mCodeMemMgr.reset(new CodeMemoryManager());
465 return mCodeMemMgr.get();
466 }
467
Zonr Chang932648d2010-10-13 22:23:56 +0800468 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700469 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +0800470 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700471 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
472 return mCodeEmitter.get();
473 }
474
475 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +0800476 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700477
Zonr Chang932648d2010-10-13 22:23:56 +0800478 llvm::LLVMContext *mContext;
479 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700480
Zonr Chang6e1d6c32010-10-23 11:57:16 +0800481 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700482
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700483 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800484 Compiler()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800485 : mUseCache(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800486 mCacheNew(false),
487 mCacheFd(-1),
488 mCacheMapAddr(NULL),
489 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800490 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800491 mCacheDiff(0),
492 mCodeDataAddr(NULL),
493 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +0800494 mpSymbolLookupContext(NULL),
495 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +0800496 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800497 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700498 llvm::remove_fatal_error_handler();
499 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700500 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700501 return;
502 }
503
Zonr Chang932648d2010-10-13 22:23:56 +0800504 // interface for BCCscript::registerSymbolCallback()
505 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700506 mpSymbolLookupFn = pFn;
507 mpSymbolLookupContext = pContext;
508 return;
509 }
510
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800511 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +0800512 GlobalInitialization();
513 mModule = module;
514 return hasError();
515 }
516
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800517 int readBC(const char *bitcode,
Loganc0b9f652010-11-24 22:33:16 +0800518 size_t bitcodeSize,
519 const BCCchar *resName) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800520 GlobalInitialization();
521
Loganc0b9f652010-11-24 22:33:16 +0800522 if (resName) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800523 // Turn on mUseCache mode iff
524 // 1. Has resName
525 // and, assuming USE_RELOCATE is false:
526 // 2. Later running code doesn't violate the following condition:
527 // mCodeDataAddr (set in loadCacheFile()) ==
528 // mCacheHdr->cachedCodeDataAddr
529 //
530 // BTW, this condition is achievable only when in the earlier
531 // cache-generating run,
532 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
533 // which means the mmap'ed is in the reserved area,
534 //
535 // Note: Upon violation, mUseCache will be set back to false.
536 mUseCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800537
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800538 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
539 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
540 return -mCacheFd;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800541 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800542 }
543
544 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700545
Zonr Chang932648d2010-10-13 22:23:56 +0800546 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700547 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700548
Zonr Chang932648d2010-10-13 22:23:56 +0800549 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800550 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +0800551 llvm::StringRef(bitcode, bitcodeSize)));
552
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800553 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +0800554 setError("Error reading input program bitcode into memory");
555 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700556 }
557
Zonr Chang932648d2010-10-13 22:23:56 +0800558 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800559 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
560 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +0800561 return hasError();
562 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700563
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800564 int linkBC(const char *bitcode, size_t bitcodeSize) {
565 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +0800566
567 if (bitcode == NULL || bitcodeSize <= 0)
568 return 0;
569
570 if (mModule == NULL) {
571 setError("No module presents for linking");
572 return hasError();
573 }
574
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800575 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +0800576 llvm::StringRef(bitcode, bitcodeSize)));
577
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800578 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +0800579 setError("Error reading input library bitcode into memory");
580 return hasError();
581 }
582
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800583 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +0800584 *mContext,
585 &mError));
586 if (Lib.get() == NULL)
587 return hasError();
588
589 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
590 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700591
Zonr Chang6e1d6c32010-10-23 11:57:16 +0800592 // Everything for linking should be settled down here with no error occurs
593 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700594 return hasError();
595 }
596
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800597 // interface for bccLoadBinary()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800598 int loadCacheFile() {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800599 // Check File Descriptor
600 if (mCacheFd < 0) {
601 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
602 goto giveup;
603 }
604
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800605 // Check File Size
606 struct stat statCacheFd;
607 if (fstat(mCacheFd, &statCacheFd) < 0) {
608 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
609 goto giveup;
610 }
611
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800612 mCacheSize = statCacheFd.st_size;
613
614 if (mCacheSize < sizeof(oBCCHeader) ||
615 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800616 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
617 goto giveup;
618 }
619
Shih-wei Liao3d77c422010-11-21 19:51:59 -0800620 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
621 LOGE("Unable to seek to 0: %s\n", strerror(errno));
622 goto giveup;
623 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800624
Loganc0b9f652010-11-24 22:33:16 +0800625 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800626 {
Loganc0b9f652010-11-24 22:33:16 +0800627 // Read cached file and perform quick integrity check
628
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800629 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800630 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
Loganad7e8e12010-11-22 20:43:43 +0800631 (unsigned int)mCacheSize,
632 (unsigned long long int)heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800633
634 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800635 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800636 flock(mCacheFd, LOCK_UN);
637 LOGE("allocation failed.\n");
638 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800639 }
640
641 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
642 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800643 if (nread != (size_t)heuristicCodeOffset) {
644 LOGE("read(mCacheFd) failed\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800645 goto bail;
646 }
647
648 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800649 // Sanity check
650 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
651 LOGE("assertion failed: heuristic code offset is not correct.\n");
652 goto bail;
653 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800654 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
655 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
656 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
657 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
658 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800659
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800660 // Verify the Cache File
661 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
662 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800663 goto bail;
664 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800665
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800666 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
667 LOGE("bad oBCC version 0x%08x\n",
668 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
669 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800670 }
671
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800672 if (mCacheSize < mCacheHdr->relocOffset +
673 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
674 LOGE("relocate table overflow\n");
675 goto bail;
676 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800677
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800678 if (mCacheSize < mCacheHdr->exportVarsOffset +
679 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
680 LOGE("export variables table overflow\n");
681 goto bail;
682 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800683
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800684 if (mCacheSize < mCacheHdr->exportFuncsOffset +
685 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
686 LOGE("export functions table overflow\n");
687 goto bail;
688 }
689
690 if (mCacheSize < mCacheHdr->exportPragmasOffset +
691 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
692 LOGE("export pragmas table overflow\n");
693 goto bail;
694 }
695
696 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
697 LOGE("code cache overflow\n");
698 goto bail;
699 }
700
701 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
702 LOGE("data (global variable) cache overflow\n");
703 goto bail;
704 }
Loganefd637b2010-11-25 01:21:03 +0800705
706 long pagesize = sysconf(_SC_PAGESIZE);
707 if (mCacheHdr->codeOffset % pagesize != 0) {
708 LOGE("code offset must aligned to pagesize\n");
709 goto bail;
710 }
Loganc0b9f652010-11-24 22:33:16 +0800711 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800712
Loganc0b9f652010-11-24 22:33:16 +0800713 // Part 2. Deal with the codedata section
714 {
Loganefd637b2010-11-25 01:21:03 +0800715 long pagesize = sysconf(_SC_PAGESIZE);
Loganc0b9f652010-11-24 22:33:16 +0800716
Loganefd637b2010-11-25 01:21:03 +0800717 if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
718 void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800719
Loganefd637b2010-11-25 01:21:03 +0800720 // Try to mmap at cached address directly.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -0800721 mCodeDataAddr = (char *) mmap(addr,
722 BCC_MMAP_IMG_SIZE,
Loganefd637b2010-11-25 01:21:03 +0800723 PROT_READ | PROT_EXEC | PROT_WRITE,
724 MAP_PRIVATE | MAP_FIXED,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -0800725 mCacheFd,
726 mCacheHdr->codeOffset);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800727
Loganefd637b2010-11-25 01:21:03 +0800728 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
729 // Cheers! Mapped at the cached address successfully.
Loganc0b9f652010-11-24 22:33:16 +0800730
Logan2ad855d2010-11-25 19:53:06 +0800731 // Update the BccMmapImgAddrTaken table (if required)
Loganefd637b2010-11-25 01:21:03 +0800732 if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
733 size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
734
735 if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
736 (offset / BCC_MMAP_IMG_SIZE) < BCC_MMAP_IMG_COUNT) {
Loganefd637b2010-11-25 01:21:03 +0800737 Compiler::BccMmapImgAddrTaken[offset / BCC_MMAP_IMG_SIZE] = true;
738 }
Loganc0b9f652010-11-24 22:33:16 +0800739 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800740
Logan2ad855d2010-11-25 19:53:06 +0800741#if 1
742 // Check the checksum of code and data
743 {
744 uint32_t sum = mCacheHdr->checksum;
745 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
746
747 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
748 sum ^= *ptr++;
749 }
750
751 if (sum != 0) {
752 LOGE("Checksum check failed\n");
753 goto bail;
754 }
Logan9f6a10d2010-11-25 23:40:47 +0800755
756 LOGE("Passed checksum even parity verification.\n");
Logan2ad855d2010-11-25 19:53:06 +0800757 }
758#endif
759
Loganefd637b2010-11-25 01:21:03 +0800760 flock(mCacheFd, LOCK_UN);
761 return 0; // loadCacheFile succeed!
762 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800763 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800764 }
765
Loganc0b9f652010-11-24 22:33:16 +0800766#if !USE_RELOCATE
767 // Note: Since this build does not support relocation, we have no
768 // choose but give up to load the cached file, and recompile the
769 // code.
770
771 flock(mCacheFd, LOCK_UN);
772 goto bail;
773#else
774
775 // Note: Currently, relocation code is not working. Give up now.
776 flock(mCacheFd, LOCK_UN);
777 goto bail;
778
779 // TODO(logan): Following code is not working. Don't use them.
780 // And rewrite them asap.
781#if 0
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800782 {
Loganc0b9f652010-11-24 22:33:16 +0800783 // Try to allocate at arbitary address. And perform relocation.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -0800784 mCacheMapAddr = (char *) mmap(0,
785 mCacheSize,
Loganc0b9f652010-11-24 22:33:16 +0800786 PROT_READ | PROT_EXEC | PROT_WRITE,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -0800787 MAP_PRIVATE,
788 mCacheFd,
789 0);
Loganc0b9f652010-11-24 22:33:16 +0800790
791 if (mCacheMapAddr == MAP_FAILED) {
792 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
793 flock(mCacheFd, LOCK_UN);
794 goto giveup;
795 }
796
797 flock(mCacheFd, LOCK_UN);
798 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
799
800 // Relocate
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800801 mCacheDiff = mCodeDataAddr -
802 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
803
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800804 if (mCacheDiff) { // To relocate
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800805 if (mCacheHdr->rootAddr) {
806 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +0800807 }
808
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800809 if (mCacheHdr->initAddr) {
810 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +0800811 }
812
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800813 oBCCRelocEntry *cachedRelocTable =
814 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
815 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +0800816
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800817 std::vector<llvm::MachineRelocation> relocations;
818
819 // Read in the relocs
820 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
821 oBCCRelocEntry *entry = &cachedRelocTable[i];
822
823 llvm::MachineRelocation reloc =
824 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
825 (unsigned)entry->relocType, 0, 0);
826
827 reloc.setResultPointer(
828 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
829
830 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -0800831 }
832
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800833 // Rewrite machine code using llvm::TargetJITInfo relocate
834 {
835 llvm::TargetMachine *TM = NULL;
836 const llvm::Target *Target;
837 std::string FeaturesStr;
838
839 // Create TargetMachine
840 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
841 if (hasError())
842 goto bail;
843
844 if (!CPU.empty() || !Features.empty()) {
845 llvm::SubtargetFeatures F;
846 F.setCPU(CPU);
847 for (std::vector<std::string>::const_iterator I = Features.begin(),
848 E = Features.end(); I != E; I++)
849 F.AddFeature(*I);
850 FeaturesStr = F.getString();
851 }
852
853 TM = Target->createTargetMachine(Triple, FeaturesStr);
854 if (TM == NULL) {
855 setError("Failed to create target machine implementation for the"
856 " specified triple '" + Triple + "'");
857 goto bail;
858 }
859
860 TM->getJITInfo()->relocate(mCodeDataAddr,
861 &relocations[0], relocations.size(),
862 (unsigned char *)mCodeDataAddr+MaxCodeSize);
863
864 if (mCodeEmitter.get()) {
865 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
866 reinterpret_cast<uint8_t*>(mCodeDataAddr),
867 2 * 1024 /*MaxCodeSize*/,
868 false);
869 }
870
871 delete TM;
872 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800873 } // End of if (mCacheDiff)
Loganc0b9f652010-11-24 22:33:16 +0800874
875 return 0; // Success!
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800876 }
Loganc0b9f652010-11-24 22:33:16 +0800877#endif
878#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800879
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800880 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800881 if (mCacheMapAddr) {
882 free(mCacheMapAddr);
883 }
Loganad7e8e12010-11-22 20:43:43 +0800884
Loganc0b9f652010-11-24 22:33:16 +0800885 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +0800886 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
Loganc0b9f652010-11-24 22:33:16 +0800887 LOGE("munmap failed: %s\n", strerror(errno));
888 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800889 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800890
Logan43830d52010-11-25 19:27:29 +0800891 mCacheMapAddr = NULL;
892 mCacheHdr = NULL;
893 mCodeDataAddr = NULL;
Logan82e67012010-11-25 00:29:34 +0800894
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800895 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800896 return 1;
897 }
898
899 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700900 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +0800901 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700902
Zonr Chang932648d2010-10-13 22:23:56 +0800903 llvm::TargetMachine *TM = NULL;
904 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700905 std::string FeaturesStr;
906
Zonr Chang932648d2010-10-13 22:23:56 +0800907 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700908
Zonr Chang932648d2010-10-13 22:23:56 +0800909 const llvm::NamedMDNode *PragmaMetadata;
910 const llvm::NamedMDNode *ExportVarMetadata;
911 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700912
Zonr Chang932648d2010-10-13 22:23:56 +0800913 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700914 return 0;
915
Zonr Chang932648d2010-10-13 22:23:56 +0800916 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700917 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +0800918 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700919 goto on_bcc_compile_error;
920
Zonr Chang932648d2010-10-13 22:23:56 +0800921 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700922 llvm::SubtargetFeatures F;
923 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +0800924 for (std::vector<std::string>::const_iterator I = Features.begin(),
925 E = Features.end();
926 I != E;
927 I++)
928 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700929 FeaturesStr = F.getString();
930 }
931
932 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +0800933 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700934 setError("Failed to create target machine implementation for the"
935 " specified triple '" + Triple + "'");
936 goto on_bcc_compile_error;
937 }
938
Zonr Chang932648d2010-10-13 22:23:56 +0800939 // Create memory manager for creation of code emitter later.
940 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700941 setError("Failed to startup memory management for further compilation");
942 goto on_bcc_compile_error;
943 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800944 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700945
Zonr Chang932648d2010-10-13 22:23:56 +0800946 // Create code emitter
947 if (!mCodeEmitter.get()) {
948 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700949 setError("Failed to create machine code emitter to complete"
950 " the compilation");
951 goto on_bcc_compile_error;
952 }
953 } else {
Zonr Chang932648d2010-10-13 22:23:56 +0800954 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700955 mCodeEmitter->reset();
956 }
957
958 mCodeEmitter->setTargetMachine(*TM);
959 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
960 mpSymbolLookupContext);
961
Zonr Chang932648d2010-10-13 22:23:56 +0800962 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700963 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +0800964
Zonr Chang5d35b972010-10-23 14:36:47 +0800965 // Load named metadata
966 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
967 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
968 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
969
Zonr Chang6e1d6c32010-10-23 11:57:16 +0800970 // Create LTO passes and run them on the mModule
971 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800972 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +0800973 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +0800974 LTOPasses.add(new llvm::TargetData(*TD));
975
976 std::vector<const char*> ExportSymbols;
977
978 // A workaround for getting export variable and function name. Will refine
979 // it soon.
980 if (ExportVarMetadata) {
981 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
982 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
983 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
984 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
985 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
986 llvm::StringRef ExportVarName =
987 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
988 ExportSymbols.push_back(ExportVarName.data());
989 }
990 }
991 }
992 }
993
994 if (ExportFuncMetadata) {
995 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
996 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
997 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
998 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
999 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
1000 llvm::StringRef ExportFuncName =
1001 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
1002 ExportSymbols.push_back(ExportFuncName.data());
1003 }
1004 }
1005 }
1006 }
1007 // root() and init() are born to be exported
1008 ExportSymbols.push_back("root");
1009 ExportSymbols.push_back("init");
1010
Zonr Change5c7a542010-10-24 01:07:27 +08001011 // We now create passes list performing LTO. These are copied from
1012 // (including comments) llvm::createStandardLTOPasses().
1013
1014 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08001015 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08001016
Zonr Change5c7a542010-10-24 01:07:27 +08001017 // Propagate constants at call sites into the functions they call. This
1018 // opens opportunities for globalopt (and inlining) by substituting
1019 // function pointers passed as arguments to direct uses of functions.
1020 LTOPasses.add(llvm::createIPSCCPPass());
1021
1022 // Now that we internalized some globals, see if we can hack on them!
1023 LTOPasses.add(llvm::createGlobalOptimizerPass());
1024
1025 // Linking modules together can lead to duplicated global constants, only
1026 // keep one copy of each constant...
1027 LTOPasses.add(llvm::createConstantMergePass());
1028
1029 // Remove unused arguments from functions...
1030 LTOPasses.add(llvm::createDeadArgEliminationPass());
1031
1032 // Reduce the code after globalopt and ipsccp. Both can open up
1033 // significant simplification opportunities, and both can propagate
1034 // functions through function pointers. When this happens, we often have
1035 // to resolve varargs calls, etc, so let instcombine do this.
1036 LTOPasses.add(llvm::createInstructionCombiningPass());
1037
1038 // Inline small functions
1039 LTOPasses.add(llvm::createFunctionInliningPass());
1040
1041 // Remove dead EH info.
1042 LTOPasses.add(llvm::createPruneEHPass());
1043
1044 // Internalize the globals again after inlining
1045 LTOPasses.add(llvm::createGlobalOptimizerPass());
1046
1047 // Remove dead functions.
1048 LTOPasses.add(llvm::createGlobalDCEPass());
1049
1050 // If we didn't decide to inline a function, check to see if we can
1051 // transform it to pass arguments by value instead of by reference.
1052 LTOPasses.add(llvm::createArgumentPromotionPass());
1053
1054 // The IPO passes may leave cruft around. Clean up after them.
1055 LTOPasses.add(llvm::createInstructionCombiningPass());
1056 LTOPasses.add(llvm::createJumpThreadingPass());
1057
1058 // Break up allocas
1059 LTOPasses.add(llvm::createScalarReplAggregatesPass());
1060
1061 // Run a few AA driven optimizations here and now, to cleanup the code.
1062 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
1063 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
1064
1065 // Hoist loop invariants.
1066 LTOPasses.add(llvm::createLICMPass());
1067
1068 // Remove redundancies.
1069 LTOPasses.add(llvm::createGVNPass());
1070
1071 // Remove dead memcpys.
1072 LTOPasses.add(llvm::createMemCpyOptPass());
1073
1074 // Nuke dead stores.
1075 LTOPasses.add(llvm::createDeadStoreEliminationPass());
1076
1077 // Cleanup and simplify the code after the scalar optimizations.
1078 LTOPasses.add(llvm::createInstructionCombiningPass());
1079
1080 LTOPasses.add(llvm::createJumpThreadingPass());
1081
1082 // Delete basic blocks, which optimization passes may have killed.
1083 LTOPasses.add(llvm::createCFGSimplificationPass());
1084
1085 // Now that we have optimized the program, discard unreachable functions.
1086 LTOPasses.add(llvm::createGlobalDCEPass());
1087
Zonr Chang6e1d6c32010-10-23 11:57:16 +08001088 LTOPasses.run(*mModule);
1089 }
1090
Zonr Chang932648d2010-10-13 22:23:56 +08001091 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001092 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08001093 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001094
Zonr Chang932648d2010-10-13 22:23:56 +08001095 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
1096 *mCodeEmitter,
1097 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001098 setError("The machine code emission is not supported by BCC on target '"
1099 + Triple + "'");
1100 goto on_bcc_compile_error;
1101 }
1102
Zonr Chang932648d2010-10-13 22:23:56 +08001103 // Run the pass (the code emitter) on every non-declaration function in the
1104 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001105 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08001106 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
1107 I != E;
1108 I++)
1109 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001110 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07001111
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001112 CodeGenPasses->doFinalization();
1113
Zonr Chang932648d2010-10-13 22:23:56 +08001114 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08001115 if (ExportVarMetadata) {
1116 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
1117 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
1118 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
1119 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
1120 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001121 llvm::StringRef ExportVarName =
1122 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08001123 CodeEmitter::global_addresses_const_iterator I, E;
1124 for (I = mCodeEmitter->global_address_begin(),
1125 E = mCodeEmitter->global_address_end();
1126 I != E;
1127 I++) {
1128 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001129 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08001130 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001131 mExportVars.push_back(I->second);
1132 break;
1133 }
1134 }
Zonr Chang932648d2010-10-13 22:23:56 +08001135 if (I != mCodeEmitter->global_address_end())
1136 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001137 }
1138 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001139 // if reaching here, we know the global variable record in metadata is
1140 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001141 mExportVars.push_back(NULL);
1142 }
1143 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
1144 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001145 }
1146
Zonr Chang932648d2010-10-13 22:23:56 +08001147 if (ExportFuncMetadata) {
1148 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
1149 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
1150 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
1151 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
1152 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001153 llvm::StringRef ExportFuncName =
1154 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
1155 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
1156 }
1157 }
1158 }
1159 }
1160
Zonr Chang932648d2010-10-13 22:23:56 +08001161 // Tell code emitter now can release the memory using during the JIT since
1162 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001163 mCodeEmitter->releaseUnnecessary();
1164
Zonr Chang932648d2010-10-13 22:23:56 +08001165 // Finally, read pragma information from the metadata node of the @Module if
1166 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08001167 if (PragmaMetadata)
1168 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
1169 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
1170 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001171 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08001172 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
1173 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001174
Zonr Chang932648d2010-10-13 22:23:56 +08001175 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001176 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
1177 llvm::StringRef PragmaName =
1178 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
1179 llvm::StringRef PragmaValue =
1180 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
1181
Zonr Chang932648d2010-10-13 22:23:56 +08001182 mPragmas.push_back(
1183 std::make_pair(std::string(PragmaName.data(),
1184 PragmaName.size()),
1185 std::string(PragmaValue.data(),
1186 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001187 }
1188 }
1189 }
1190
1191 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08001192 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001193 if (CodeGenPasses) {
1194 delete CodeGenPasses;
1195 } else if (TD) {
1196 delete TD;
1197 }
1198 if (TM)
1199 delete TM;
1200
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07001201 if (mError.empty()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001202 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001203 genCacheFile();
1204 flock(mCacheFd, LOCK_UN);
1205 }
Loganc0b9f652010-11-24 22:33:16 +08001206
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07001207 return false;
1208 }
1209
Zonr Chang932648d2010-10-13 22:23:56 +08001210 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07001211 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001212 }
1213
Zonr Chang932648d2010-10-13 22:23:56 +08001214 // interface for bccGetScriptInfoLog()
1215 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001216 return const_cast<char*>(mError.c_str());
1217 }
1218
Zonr Chang932648d2010-10-13 22:23:56 +08001219 // interface for bccGetScriptLabel()
1220 void *lookup(const char *name) {
1221 void *addr = NULL;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001222 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001223 if (!strcmp(name, "root")) {
1224 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
1225 } else if (!strcmp(name, "init")) {
1226 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
1227 }
1228 return addr;
1229 }
1230
Zonr Chang932648d2010-10-13 22:23:56 +08001231 if (mCodeEmitter.get())
1232 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001233 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001234 return addr;
1235 }
1236
Zonr Chang932648d2010-10-13 22:23:56 +08001237 // Interface for bccGetExportVars()
1238 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001239 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08001240 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001241 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001242
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001243 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001244 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
1245 if (actualVarCount)
1246 *actualVarCount = varCount;
1247 if (varCount > maxVarCount)
1248 varCount = maxVarCount;
1249 if (vars) {
1250 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
1251 mCacheHdr->exportVarsOffset);
1252
1253 for (int i = 0; i < varCount; i++) {
1254 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
1255 mCacheDiff);
1256 cachedVars++;
1257 }
1258 }
1259 return;
1260 }
1261
1262 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08001263 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001264 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08001265 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001266 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001267 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08001268 for (ExportVarList::const_iterator I = mExportVars.begin(),
1269 E = mExportVars.end();
1270 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001271 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08001272 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001273 }
1274 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001275
1276 return;
1277 }
1278
Zonr Chang932648d2010-10-13 22:23:56 +08001279 // Interface for bccGetExportFuncs()
1280 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001281 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08001282 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001283 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001284
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001285 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001286 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
1287 if (actualFuncCount)
1288 *actualFuncCount = funcCount;
1289 if (funcCount > maxFuncCount)
1290 funcCount = maxFuncCount;
1291 if (funcs) {
1292 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
1293 mCacheHdr->exportFuncsOffset);
1294
1295 for (int i = 0; i < funcCount; i++) {
1296 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
1297 mCacheDiff);
1298 cachedFuncs++;
1299 }
1300 }
1301 return;
1302 }
1303
1304 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08001305 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001306 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08001307 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001308 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001309 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08001310 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
1311 E = mExportFuncs.end();
1312 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001313 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08001314 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001315 }
1316 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001317
1318 return;
1319 }
1320
Zonr Chang932648d2010-10-13 22:23:56 +08001321 // Interface for bccGetPragmas()
1322 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001323 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08001324 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001325 int stringCount;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001326 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001327 if (actualStringCount)
1328 *actualStringCount = 0; // XXX
1329 return;
1330 }
1331
1332 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001333
Zonr Chang932648d2010-10-13 22:23:56 +08001334 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001335 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08001336 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001337 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001338 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08001339 for (PragmaList::const_iterator it = mPragmas.begin();
1340 stringCount > 0;
1341 stringCount -= 2, it++) {
1342 *strings++ = const_cast<BCCchar*>(it->first.c_str());
1343 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001344 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001345 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001346
1347 return;
1348 }
1349
Zonr Chang932648d2010-10-13 22:23:56 +08001350 // Interface for bccGetFunctions()
1351 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001352 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08001353 BCCchar **functions) {
1354 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001355 mCodeEmitter->getFunctionNames(actualFunctionCount,
1356 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001357 functions);
1358 else
1359 *actualFunctionCount = 0;
1360
1361 return;
1362 }
1363
Zonr Chang932648d2010-10-13 22:23:56 +08001364 // Interface for bccGetFunctionBinary()
1365 void getFunctionBinary(BCCchar *function,
1366 BCCvoid **base,
1367 BCCsizei *length) {
1368 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001369 mCodeEmitter->getFunctionBinary(function, base, length);
1370 } else {
1371 *base = NULL;
1372 *length = 0;
1373 }
1374 return;
1375 }
1376
Zonr Chang932648d2010-10-13 22:23:56 +08001377 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001378 return mModule;
1379 }
1380
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001381 ~Compiler() {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08001382 if (!mCodeMemMgr.get()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001383 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08001384 // managed by CodeMemoryManager.
1385
1386 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +08001387 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08001388 LOGE("munmap failed while releasing mCodeDataAddr\n");
1389 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08001390 }
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08001391
Shih-wei Liao1f45b862010-11-21 23:22:38 -08001392 if (mCacheMapAddr) {
1393 free(mCacheMapAddr);
1394 }
Logan82e67012010-11-25 00:29:34 +08001395
1396 mCodeDataAddr = 0;
1397 mCacheMapAddr = 0;
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08001398 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08001399
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001400 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08001401 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001402 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001403 return;
1404 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001405
1406 private:
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001407 // Note: loadCacheFile() and genCacheFile() go hand in hand
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001408 void genCacheFile() {
1409 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
1410 LOGE("Unable to seek to 0: %s\n", strerror(errno));
1411 return;
1412 }
1413
1414 bool codeOffsetNeedPadding = false;
1415
1416 uint32_t offset = sizeof(oBCCHeader);
1417
1418 // BCC Cache File Header
1419 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
1420
1421 if (!hdr) {
1422 LOGE("Unable to allocate oBCCHeader.\n");
1423 return;
1424 }
1425
1426 // Magic Words
1427 memcpy(hdr->magic, OBCC_MAGIC, 4);
1428 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
1429
1430 // Timestamp
1431 hdr->sourceWhen = 0; // TODO(all)
1432 hdr->rslibWhen = 0; // TODO(all)
1433 hdr->libRSWhen = 0; // TODO(all)
1434 hdr->libbccWhen = 0; // TODO(all)
1435
1436 // Current Memory Address (Saved for Recalculation)
1437 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
1438 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
1439 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
1440
1441 // Relocation Table Offset and Entry Count
1442 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08001443 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001444
Logan824dd0a2010-11-20 01:45:54 +08001445 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001446
1447 // Export Variable Table Offset and Entry Count
1448 hdr->exportVarsOffset = offset;
1449 hdr->exportVarsCount = mExportVars.size();
1450
1451 offset += hdr->exportVarsCount * sizeof(uint32_t);
1452
1453 // Export Function Table Offset and Entry Count
1454 hdr->exportFuncsOffset = offset;
1455 hdr->exportFuncsCount = mExportFuncs.size();
1456
1457 offset += hdr->exportFuncsCount * sizeof(uint32_t);
1458
1459 // Export Pragmas Table Offset and Entry Count
1460 hdr->exportPragmasOffset = offset;
1461 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
1462
1463 offset += hdr->exportPragmasCount * sizeof(uint32_t);
1464
1465 // Code Offset and Size
1466
Shih-wei Liao1f45b862010-11-21 23:22:38 -08001467 //#ifdef BCC_CODE_ADDR
1468 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001469 long pagesize = sysconf(_SC_PAGESIZE);
1470
1471 if (offset % pagesize > 0) {
1472 codeOffsetNeedPadding = true;
1473 offset += pagesize - (offset % pagesize);
1474 }
1475 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08001476 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001477 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
1478 codeOffsetNeedPadding = true;
1479 offset += 0x08 - (offset & 0x07);
1480 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08001481 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001482
1483 hdr->codeOffset = offset;
1484 hdr->codeSize = MaxCodeSize;
1485
1486 offset += hdr->codeSize;
1487
1488 // Data (Global Variable) Offset and Size
1489 hdr->dataOffset = offset;
1490 hdr->dataSize = MaxGlobalVarSize;
1491
1492 offset += hdr->dataSize;
1493
1494 // Checksum
Logan2ad855d2010-11-25 19:53:06 +08001495#if 1
1496 {
1497 // Note: This is an simple checksum implementation that are using xor
1498 // to calculate even parity (for code and data only).
1499
1500 uint32_t sum = 0;
1501 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
1502
1503 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
1504 sum ^= *ptr++;
1505 }
1506
1507 hdr->checksum = sum;
1508 }
1509#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001510 hdr->checksum = 0; // Set Field checksum. TODO(all)
Logan2ad855d2010-11-25 19:53:06 +08001511#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001512
1513 // Write Header
1514 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
1515 sizeof(oBCCHeader), "Write oBCC header");
1516
Logan824dd0a2010-11-20 01:45:54 +08001517 // Write Relocation Entry Table
1518 {
1519 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001520
Logan824dd0a2010-11-20 01:45:54 +08001521 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
1522
1523 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
1524 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001525 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001526
1527 // Write Export Variables Table
1528 {
1529 uint32_t *record, *ptr;
1530
1531 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
1532 ptr = record;
1533
1534 if (!record) {
1535 goto bail;
1536 }
1537
1538 for (ExportVarList::const_iterator I = mExportVars.begin(),
1539 E = mExportVars.end(); I != E; I++) {
1540 *ptr++ = reinterpret_cast<uint32_t>(*I);
1541 }
1542
1543 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1544 hdr->exportVarsCount * sizeof(uint32_t),
1545 "Write ExportVars");
1546
1547 free(record);
1548 }
1549
1550 // Write Export Functions Table
1551 {
1552 uint32_t *record, *ptr;
1553
1554 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
1555 ptr = record;
1556
1557 if (!record) {
1558 goto bail;
1559 }
1560
1561 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
1562 E = mExportFuncs.end(); I != E; I++) {
1563 *ptr++ = reinterpret_cast<uint32_t>(*I);
1564 }
1565
1566 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
1567 hdr->exportFuncsCount * sizeof(uint32_t),
1568 "Write ExportFuncs");
1569
1570 free(record);
1571 }
1572
1573
1574 // TODO(all): Write Export Pragmas Table
1575#if 0
1576#else
1577 // Note: As long as we have comment out export pragmas table code,
1578 // we have to seek the position to correct offset.
1579
1580 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
1581#endif
1582
1583 if (codeOffsetNeedPadding) {
1584 // requires additional padding
1585 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
1586 }
1587
1588 // Write Generated Code and Global Variable
1589 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
1590 "Write code and global variable");
1591
1592 goto close_return;
1593
1594 bail:
1595 if (ftruncate(mCacheFd, 0) != 0) {
1596 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
1597 }
1598
1599 close_return:
1600 free(hdr);
1601 close(mCacheFd);
1602 mCacheFd = -1;
1603 return;
1604 }
1605
1606 // OpenCacheFile() returns fd of the cache file.
1607 // Input:
1608 // BCCchar *resName: Used to genCacheFileName()
1609 // bool createIfMissing: If false, turn off caching
1610 // Output:
1611 // returns fd: If -1: Failed
1612 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
1613 // cache file's file descriptor
1614 // Note: openCacheFile() will check the cache file's validity,
1615 // such as Magic number, sourceWhen... dependencies.
1616 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
1617 int fd, cc;
1618 struct stat fdStat, fileStat;
1619 bool readOnly = false;
1620
1621 char *cacheFileName = genCacheFileName(resName, ".oBCC");
1622
1623 mCacheNew = false;
1624
1625 retry:
1626 /*
1627 * Try to open the cache file. If we've been asked to,
1628 * create it if it doesn't exist.
1629 */
1630 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
1631 if (fd < 0) {
1632 fd = open(cacheFileName, O_RDONLY, 0);
1633 if (fd < 0) {
1634 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08001635 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001636 cacheFileName, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08001637 mUseCache = false;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001638 }
1639 return fd;
1640 }
1641 readOnly = true;
1642 }
1643
1644 /*
1645 * Grab an exclusive lock on the cache file. If somebody else is
1646 * working on it, we'll block here until they complete.
1647 */
1648 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
1649 cacheFileName, fd);
1650
1651 cc = flock(fd, LOCK_EX | LOCK_NB);
1652 if (cc != 0) {
1653 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
1654 cc = flock(fd, LOCK_EX);
1655 }
1656
1657 if (cc != 0) {
1658 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
1659 close(fd);
1660 return -1;
1661 }
1662 LOGV("bcc: locked cache file\n");
1663
1664 /*
1665 * Check to see if the fd we opened and locked matches the file in
1666 * the filesystem. If they don't, then somebody else unlinked ours
1667 * and created a new file, and we need to use that one instead. (If
1668 * we caught them between the unlink and the create, we'll get an
1669 * ENOENT from the file stat.)
1670 */
1671 cc = fstat(fd, &fdStat);
1672 if (cc != 0) {
1673 LOGE("Can't stat open file '%s'\n", cacheFileName);
1674 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1675 goto close_fail;
1676 }
1677 cc = stat(cacheFileName, &fileStat);
1678 if (cc != 0 ||
1679 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
1680 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
1681 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1682 flock(fd, LOCK_UN);
1683 close(fd);
1684 usleep(250 * 1000); // if something is hosed, don't peg machine
1685 goto retry;
1686 }
1687
1688 /*
1689 * We have the correct file open and locked. If the file size is zero,
1690 * then it was just created by us, and we want to fill in some fields
1691 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
1692 * verify that the fields in the header match our expectations, and
1693 * reset the file if they don't.
1694 */
1695 if (fdStat.st_size == 0) {
1696 if (readOnly) { // The device is readOnly --> close_fail
1697 LOGW("bcc: file has zero length and isn't writable\n");
1698 goto close_fail;
1699 }
1700 /*cc = createEmptyHeader(fd);
1701 if (cc != 0)
1702 goto close_fail;
1703 */
1704 mCacheNew = true;
1705 LOGV("bcc: successfully initialized new cache file\n");
1706 } else {
1707 // Calculate sourceWhen
1708 // XXX
1709 uint32_t sourceWhen = 0;
1710 uint32_t rslibWhen = 0;
1711 uint32_t libRSWhen = 0;
1712 uint32_t libbccWhen = 0;
1713 if (!checkHeaderAndDependencies(fd,
1714 sourceWhen,
1715 rslibWhen,
1716 libRSWhen,
1717 libbccWhen)) {
1718 // If checkHeaderAndDependencies returns 0: FAILED
1719 // Will truncate the file and retry to createIfMissing the file
1720
1721 if (readOnly) { // Shouldn't be readonly.
1722 /*
1723 * We could unlink and rewrite the file if we own it or
1724 * the "sticky" bit isn't set on the directory. However,
1725 * we're not able to truncate it, which spoils things. So,
1726 * give up now.
1727 */
1728 if (createIfMissing) {
1729 LOGW("Cached file %s is stale and not writable\n",
1730 cacheFileName);
1731 }
1732 goto close_fail;
1733 }
1734
1735 /*
1736 * If we truncate the existing file before unlinking it, any
1737 * process that has it mapped will fail when it tries to touch
1738 * the pages? Probably OK because we use MAP_PRIVATE.
1739 */
1740 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
1741 cacheFileName);
1742 if (ftruncate(fd, 0) != 0) {
1743 LOGW("Warning: unable to truncate cache file '%s': %s\n",
1744 cacheFileName, strerror(errno));
1745 /* keep going */
1746 }
1747 if (unlink(cacheFileName) != 0) {
1748 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
1749 cacheFileName, errno, strerror(errno));
1750 /* keep going; permission failure should probably be fatal */
1751 }
1752 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
1753 flock(fd, LOCK_UN);
1754 close(fd);
1755 goto retry;
1756 } else {
1757 // Got cacheFile! Good to go.
1758 LOGV("Good cache file\n");
1759 }
1760 }
1761
1762 assert(fd >= 0);
1763 return fd;
1764
1765 close_fail:
1766 flock(fd, LOCK_UN);
1767 close(fd);
1768 return -1;
1769 } // End of openCacheFile()
1770
1771 char *genCacheFileName(const char *fileName, const char *subFileName) {
1772 char nameBuf[512];
1773 static const char kCachePath[] = "bcc-cache";
1774 char absoluteFile[sizeof(nameBuf)];
1775 const size_t kBufLen = sizeof(nameBuf) - 1;
1776 const char *dataRoot;
1777 char *cp;
1778
1779 // Get the absolute path of the raw/***.bc file.
1780 absoluteFile[0] = '\0';
1781 if (fileName[0] != '/') {
1782 /*
1783 * Generate the absolute path. This doesn't do everything it
1784 * should, e.g. if filename is "./out/whatever" it doesn't crunch
1785 * the leading "./" out, but it'll do.
1786 */
1787 if (getcwd(absoluteFile, kBufLen) == NULL) {
1788 LOGE("Can't get CWD while opening raw/***.bc file\n");
1789 return NULL;
1790 }
1791 // TODO(srhines): strncat() is a bit dangerous
1792 strncat(absoluteFile, "/", kBufLen);
1793 }
1794 strncat(absoluteFile, fileName, kBufLen);
1795
1796 if (subFileName != NULL) {
1797 strncat(absoluteFile, "/", kBufLen);
1798 strncat(absoluteFile, subFileName, kBufLen);
1799 }
1800
1801 /* Turn the path into a flat filename by replacing
1802 * any slashes after the first one with '@' characters.
1803 */
1804 cp = absoluteFile + 1;
1805 while (*cp != '\0') {
1806 if (*cp == '/') {
1807 *cp = '@';
1808 }
1809 cp++;
1810 }
1811
1812 /* Build the name of the cache directory.
1813 */
1814 dataRoot = getenv("ANDROID_DATA");
1815 if (dataRoot == NULL)
1816 dataRoot = "/data";
1817 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
1818
1819 /* Tack on the file name for the actual cache file path.
1820 */
1821 strncat(nameBuf, absoluteFile, kBufLen);
1822
1823 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
1824 return strdup(nameBuf);
1825 }
1826
1827 /*
1828 * Read the oBCC header, verify it, then read the dependent section
1829 * and verify that data as well.
1830 *
1831 * On successful return, the file will be seeked immediately past the
1832 * oBCC header.
1833 */
1834 bool checkHeaderAndDependencies(int fd,
1835 uint32_t sourceWhen,
1836 uint32_t rslibWhen,
1837 uint32_t libRSWhen,
1838 uint32_t libbccWhen) {
1839 ssize_t actual;
1840 oBCCHeader optHdr;
1841 uint32_t val;
1842 uint8_t const *magic, *magicVer;
1843
1844 /*
1845 * Start at the start. The "bcc" header, when present, will always be
1846 * the first thing in the file.
1847 */
1848 if (lseek(fd, 0, SEEK_SET) != 0) {
1849 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
1850 goto bail;
1851 }
1852
1853 /*
1854 * Read and do trivial verification on the bcc header. The header is
1855 * always in host byte order.
1856 */
1857 actual = read(fd, &optHdr, sizeof(optHdr));
1858 if (actual < 0) {
1859 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
1860 goto bail;
1861 } else if (actual != sizeof(optHdr)) {
1862 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
1863 (int) actual, sizeof(optHdr));
1864 goto bail;
1865 }
1866
1867 magic = optHdr.magic;
1868 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
1869 /* not an oBCC file, or previous attempt was interrupted */
1870 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
1871 magic[0], magic[1], magic[2], magic[3]);
1872 goto bail;
1873 }
1874
1875 magicVer = optHdr.magicVersion;
1876 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
1877 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
1878 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
1879 goto bail;
1880 }
1881
1882 /*
1883 * Do the header flags match up with what we want?
1884 *
1885 * This is useful because it allows us to automatically regenerate
1886 * a file when settings change (e.g. verification is now mandatory),
1887 * but can cause difficulties if the thing we depend upon
1888 * were handled differently than the current options specify.
1889 *
1890 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
1891 * by limiting the match mask.
1892 *
1893 * The only thing we really can't handle is incorrect byte-ordering.
1894 */
1895
1896 val = optHdr.sourceWhen;
1897 if (val && (val != sourceWhen)) {
1898 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
1899 val, sourceWhen);
1900 goto bail;
1901 }
1902 val = optHdr.rslibWhen;
1903 if (val && (val != rslibWhen)) {
1904 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
1905 val, rslibWhen);
1906 goto bail;
1907 }
1908 val = optHdr.libRSWhen;
1909 if (val && (val != libRSWhen)) {
1910 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
1911 val, libRSWhen);
1912 goto bail;
1913 }
1914 val = optHdr.libbccWhen;
1915 if (val && (val != libbccWhen)) {
1916 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
1917 val, libbccWhen);
1918 goto bail;
1919 }
1920
1921 return true;
1922
1923 bail:
1924 return false;
1925 }
1926
Zonr Chang932648d2010-10-13 22:23:56 +08001927};
1928// End of Class Compiler
1929////////////////////////////////////////////////////////////////////////////////
1930
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001931
1932bool Compiler::GlobalInitialized = false;
1933
Loganc0b9f652010-11-24 22:33:16 +08001934bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Loganad7e8e12010-11-22 20:43:43 +08001935
Zonr Chang932648d2010-10-13 22:23:56 +08001936// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001937llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
1938
1939std::string Compiler::Triple;
1940
1941std::string Compiler::CPU;
1942
1943std::vector<std::string> Compiler::Features;
1944
Zonr Chang932648d2010-10-13 22:23:56 +08001945// The named of metadata node that pragma resides (should be synced with
1946// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001947const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
1948
Zonr Chang932648d2010-10-13 22:23:56 +08001949// The named of metadata node that export variable name resides (should be
1950// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001951const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
1952
Zonr Chang932648d2010-10-13 22:23:56 +08001953// The named of metadata node that export function name resides (should be
1954// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001955const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
1956
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001957struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08001958 //////////////////////////////////////////////////////////////////////////////
1959 // Part I. Compiler
1960 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001961 Compiler compiler;
1962
Zonr Chang932648d2010-10-13 22:23:56 +08001963 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001964 compiler.registerSymbolCallback(pFn, pContext);
1965 }
1966
Zonr Chang932648d2010-10-13 22:23:56 +08001967 //////////////////////////////////////////////////////////////////////////////
1968 // Part II. Logistics & Error handling
1969 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001970 BCCscript() {
1971 bccError = BCC_NO_ERROR;
1972 }
1973
1974 ~BCCscript() {
1975 }
1976
1977 void setError(BCCenum error) {
1978 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
1979 bccError = error;
1980 }
1981 }
1982
1983 BCCenum getError() {
1984 BCCenum result = bccError;
1985 bccError = BCC_NO_ERROR;
1986 return result;
1987 }
1988
1989 BCCenum bccError;
1990};
1991
1992
1993extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08001994BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001995 return new BCCscript();
1996}
1997
1998extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08001999BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002000 return script->getError();
2001}
2002
2003extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002004void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002005 delete script;
2006}
2007
2008extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002009void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002010 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08002011 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002012 script->registerSymbolCallback(pFn, pContext);
2013}
2014
2015extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002016int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08002017 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002018 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08002019}
2020
2021extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002022int bccReadBC(BCCscript *script,
2023 const BCCchar *bitcode,
2024 BCCint size,
2025 const BCCchar *resName) {
2026 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002027}
2028
2029extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002030void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08002031 const BCCchar *bitcode,
2032 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002033 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08002034}
2035
2036extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002037void bccLoadBinary(BCCscript *script) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002038 int result = script->compiler.loadCacheFile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002039 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002040 script->setError(BCC_INVALID_OPERATION);
2041}
2042
2043extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002044void bccCompileBC(BCCscript *script) {
2045 {
2046#if defined(__arm__)
2047 android::StopWatch compileTimer("RenderScript compile time");
2048#endif
2049 int result = script->compiler.compile();
2050 if (result)
2051 script->setError(BCC_INVALID_OPERATION);
2052 }
2053}
2054
2055extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002056void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002057 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08002058 BCCsizei *length,
2059 BCCchar *infoLog) {
2060 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002061 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002062 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002063 *length = messageLength;
2064
2065 if (infoLog && maxLength > 0) {
2066 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
2067 memcpy(infoLog, message, trimmedLength);
2068 infoLog[trimmedLength] = 0;
2069 }
2070}
2071
2072extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002073void bccGetScriptLabel(BCCscript *script,
2074 const BCCchar *name,
2075 BCCvoid **address) {
2076 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002077 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002078 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002079 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002080 script->setError(BCC_INVALID_VALUE);
2081}
2082
2083extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002084void bccGetExportVars(BCCscript *script,
2085 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002086 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002087 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002088 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
2089}
2090
2091extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002092void bccGetExportFuncs(BCCscript *script,
2093 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002094 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002095 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002096 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
2097}
2098
2099extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002100void bccGetPragmas(BCCscript *script,
2101 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002102 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002103 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002104 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
2105}
2106
2107extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002108void bccGetFunctions(BCCscript *script,
2109 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002110 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002111 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002112 script->compiler.getFunctions(actualFunctionCount,
2113 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002114 functions);
2115}
2116
2117extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002118void bccGetFunctionBinary(BCCscript *script,
2119 BCCchar *function,
2120 BCCvoid **base,
2121 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002122 script->compiler.getFunctionBinary(function, base, length);
2123}
2124
2125struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08002126 const Compiler *compiler;
2127 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002128};
2129
Zonr Chang932648d2010-10-13 22:23:56 +08002130} // namespace bcc