blob: 8aee2e9efe5b6811705e3b23d71e4d2b4ccf1b58 [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>
156#include "bcc_runtime.h"
Loganfc9530e2010-11-26 19:49:07 +0800157#include "bcc_emitted_func_code.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700158
Zonr Chang932648d2010-10-13 22:23:56 +0800159#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700160// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
161
Zonr Chang932648d2010-10-13 22:23:56 +0800162#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700163// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
164
165// #define PROVIDE_TRACE_CODEGEN
166
167#if defined(USE_DISASSEMBLER)
Loganf2dbef82010-11-26 19:58:08 +0800168# include "bcc_buff_mem_object.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800169# include "llvm/MC/MCInst.h"
170# include "llvm/MC/MCAsmInfo.h"
171# include "llvm/MC/MCInstPrinter.h"
172# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700173// If you want the disassemble results written to file, define this:
174# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700175#endif
176
177#include <set>
178#include <map>
179#include <list>
180#include <cmath>
181#include <string>
182#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800183#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700184
Zonr Chang932648d2010-10-13 22:23:56 +0800185// VMCore
186#include "llvm/Use.h"
187#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800188#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800189#include "llvm/Module.h"
190#include "llvm/Function.h"
191#include "llvm/Constant.h"
192#include "llvm/Constants.h"
193#include "llvm/Instruction.h"
194#include "llvm/PassManager.h"
195#include "llvm/LLVMContext.h"
196#include "llvm/GlobalValue.h"
197#include "llvm/Instructions.h"
198#include "llvm/OperandTraits.h"
199#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700200
201// System
Zonr Chang932648d2010-10-13 22:23:56 +0800202#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700203
204// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800205#include "llvm/ADT/APInt.h"
206#include "llvm/ADT/APFloat.h"
207#include "llvm/ADT/DenseMap.h"
208#include "llvm/ADT/ValueMap.h"
209#include "llvm/ADT/StringMap.h"
210#include "llvm/ADT/OwningPtr.h"
211#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700212
213// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800214#include "llvm/Target/TargetData.h"
215#include "llvm/Target/TargetSelect.h"
216#include "llvm/Target/TargetOptions.h"
217#include "llvm/Target/TargetMachine.h"
218#include "llvm/Target/TargetJITInfo.h"
219#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700220#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700221
222// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800223#include "llvm/Support/Casting.h"
224#include "llvm/Support/raw_ostream.h"
225#include "llvm/Support/ValueHandle.h"
226#include "llvm/Support/MemoryBuffer.h"
227#include "llvm/Support/MemoryObject.h"
228#include "llvm/Support/ManagedStatic.h"
229#include "llvm/Support/ErrorHandling.h"
230#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700231#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700232
233// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800234#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700235
236// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800237#include "llvm/CodeGen/Passes.h"
238#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700239#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700240#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700241#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700242#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700243#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700244#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700245#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700246#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700247
248// ExecutionEngine
249#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700250#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700251
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700252extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700253
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800254// For caching
255struct oBCCHeader {
256 uint8_t magic[4]; // includes version number
257 uint8_t magicVersion[4];
258
259 uint32_t sourceWhen;
260 uint32_t rslibWhen;
261 uint32_t libRSWhen;
262 uint32_t libbccWhen;
263
264 uint32_t cachedCodeDataAddr;
265 uint32_t rootAddr;
266 uint32_t initAddr;
267
268 uint32_t relocOffset; // offset of reloc table.
269 uint32_t relocCount;
270 uint32_t exportVarsOffset; // offset of export var table
271 uint32_t exportVarsCount;
272 uint32_t exportFuncsOffset; // offset of export func table
273 uint32_t exportFuncsCount;
274 uint32_t exportPragmasOffset; // offset of export pragma table
275 uint32_t exportPragmasCount;
276
277 uint32_t codeOffset; // offset of code: 64-bit alignment
278 uint32_t codeSize;
279 uint32_t dataOffset; // offset of data section
280 uint32_t dataSize;
281
282 // uint32_t flags; // some info flags
283 uint32_t checksum; // adler32 checksum covering deps/opt
284};
285
Logan824dd0a2010-11-20 01:45:54 +0800286struct oBCCRelocEntry {
287 uint32_t relocType; // target instruction relocation type
288 uint32_t relocOffset; // offset of hole (holeAddr - codeAddr)
289 uint32_t cachedResultAddr; // address resolved at compile time
290
Logan634bd832010-11-20 09:00:36 +0800291 oBCCRelocEntry(uint32_t ty, uintptr_t off, void *addr)
Logan824dd0a2010-11-20 01:45:54 +0800292 : relocType(ty),
293 relocOffset(static_cast<uint32_t>(off)),
294 cachedResultAddr(reinterpret_cast<uint32_t>(addr)) {
295 }
296};
297
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800298/* oBCCHeader Offset Table */
299#define k_magic offsetof(oBCCHeader, magic)
300#define k_magicVersion offsetof(oBCCHeader, magicVersion)
301#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
302#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
303#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
304#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
305#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
306#define k_rootAddr offsetof(oBCCHeader, rootAddr)
307#define k_initAddr offsetof(oBCCHeader, initAddr)
308#define k_relocOffset offsetof(oBCCHeader, relocOffset)
309#define k_relocCount offsetof(oBCCHeader, relocCount)
310#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
311#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
312#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
313#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
314#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
315#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
316#define k_codeOffset offsetof(oBCCHeader, codeOffset)
317#define k_codeSize offsetof(oBCCHeader, codeSize)
318#define k_dataOffset offsetof(oBCCHeader, dataOffset)
319#define k_dataSize offsetof(oBCCHeader, dataSize)
320#define k_checksum offsetof(oBCCHeader, checksum)
321
322/* oBCC file magic number */
323#define OBCC_MAGIC "bcc\n"
324/* version, encoded in 4 bytes of ASCII */
325#define OBCC_MAGIC_VERS "001\0"
326
327#define TEMP_FAILURE_RETRY1(exp) ({ \
328 typeof (exp) _rc; \
329 do { \
330 _rc = (exp); \
331 } while (_rc == -1 && errno == EINTR); \
332 _rc; })
333
334static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
335{
336 while (count != 0) {
337 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
338 if (actual < 0) {
339 int err = errno;
340 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
341 return err;
342 } else if (actual != (ssize_t) count) {
343 LOGD("%s: partial write (will retry): (%d of %zd)\n",
344 logMsg, (int) actual, count);
345 buf = (const void*) (((const uint8_t*) buf) + actual);
346 }
347 count -= actual;
348 }
349
350 return 0;
351}
352
Zonr Chang932648d2010-10-13 22:23:56 +0800353//
354// Compilation class that suits Android's needs.
355// (Support: no argument passed, ...)
356//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700357namespace bcc {
358
359class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800360 // This part is designed to be orthogonal to those exported bcc*() functions
361 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700362
Zonr Chang932648d2010-10-13 22:23:56 +0800363 //////////////////////////////////////////////////////////////////////////////
364 // The variable section below (e.g., Triple, CodeGenOptLevel)
365 // is initialized in GlobalInitialization()
366 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700367 static bool GlobalInitialized;
Loganc0b9f652010-11-24 22:33:16 +0800368 static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700369
Zonr Chang932648d2010-10-13 22:23:56 +0800370 // If given, this will be the name of the target triple to compile for.
371 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700372 static std::string Triple;
373
374 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700375
Zonr Chang932648d2010-10-13 22:23:56 +0800376 // End of section of GlobalInitializing variables
377 //////////////////////////////////////////////////////////////////////////////
378
379 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700380 static std::string CPU;
381
Zonr Chang932648d2010-10-13 22:23:56 +0800382 // The list of target specific features to enable or disable -- this should
383 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700384 static std::vector<std::string> Features;
385
386 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800387 const char *mName;
388 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700389 };
390 static struct Runtime Runtimes[];
391
392 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800393 if (GlobalInitialized)
394 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700395
Zonr Chang932648d2010-10-13 22:23:56 +0800396 // if (!llvm::llvm_is_multithreaded())
397 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700398
Zonr Chang932648d2010-10-13 22:23:56 +0800399 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700400 Triple = TARGET_TRIPLE_STRING;
401
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800402 // TODO(sliao): NEON for JIT
Zonr Chang932648d2010-10-13 22:23:56 +0800403 // Features.push_back("+neon");
404 // Features.push_back("+vmlx");
405 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700406 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700407 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700408
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700409#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
410 LLVMInitializeARMTargetInfo();
411 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700412#if defined(USE_DISASSEMBLER)
413 LLVMInitializeARMDisassembler();
414 LLVMInitializeARMAsmPrinter();
415#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700416#endif
417
418#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
419 LLVMInitializeX86TargetInfo();
420 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700421#if defined(USE_DISASSEMBLER)
422 LLVMInitializeX86Disassembler();
423 LLVMInitializeX86AsmPrinter();
424#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700425#endif
426
427#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
428 LLVMInitializeX86TargetInfo();
429 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700430#if defined(USE_DISASSEMBLER)
431 LLVMInitializeX86Disassembler();
432 LLVMInitializeX86AsmPrinter();
433#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700434#endif
435
Zonr Chang932648d2010-10-13 22:23:56 +0800436 // -O0: llvm::CodeGenOpt::None
437 // -O1: llvm::CodeGenOpt::Less
438 // -O2: llvm::CodeGenOpt::Default
439 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700440 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700441
Zonr Chang932648d2010-10-13 22:23:56 +0800442 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700443
Zonr Chang932648d2010-10-13 22:23:56 +0800444 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700445 llvm::NoFramePointerElim = false;
446
Zonr Chang932648d2010-10-13 22:23:56 +0800447 // Use hardfloat ABI
448 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800449 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800450 // softfp. To use softfp, change following 2 lines to
451 //
452 // llvm::FloatABIType = llvm::FloatABI::Soft;
453 // llvm::UseSoftFloat = true;
454 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700455 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700456 llvm::UseSoftFloat = false;
457
Zonr Chang932648d2010-10-13 22:23:56 +0800458 // BCC needs all unknown symbols resolved at JIT/compilation time.
459 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700460 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
461
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700462#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800463 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700464 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
465#else
Zonr Chang932648d2010-10-13 22:23:56 +0800466 // This is set for the linker (specify how large of the virtual addresses
467 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700468 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
469#endif
470
Zonr Chang932648d2010-10-13 22:23:56 +0800471 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700472 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
473
Zonr Chang932648d2010-10-13 22:23:56 +0800474 // Register allocation policy:
475 // createFastRegisterAllocator: fast but bad quality
476 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700477 llvm::RegisterRegAlloc::setDefault
478 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700479 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700480 llvm::createLinearScanRegisterAllocator);
481
482 GlobalInitialized = true;
483 return;
484 }
485
486 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800487 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700488 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700489 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800490 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700491 }
492
493 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700494 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700495 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700496
497 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700498 std::string mError;
499
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700500 inline bool hasError() const {
501 return !mError.empty();
502 }
Zonr Chang932648d2010-10-13 22:23:56 +0800503 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700504 mError.assign(Error); // Copying
505 return;
506 }
Zonr Chang932648d2010-10-13 22:23:56 +0800507 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700508 mError = Error;
509 return;
510 }
511
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800512 bool mUseCache; // Set by readBC()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800513 bool mCacheNew; // Set by readBC()
514 int mCacheFd; // Set by readBC()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800515 char *mCacheMapAddr; // Set by loadCacheFile() if mCacheNew is false
516 oBCCHeader *mCacheHdr; // Set by loadCacheFile()
517 size_t mCacheSize; // Set by loadCacheFile()
518 ptrdiff_t mCacheDiff; // Set by loadCacheFile()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800519 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
520 // Used by genCacheFile() for dumping
521
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700522 typedef std::list< std::pair<std::string, std::string> > PragmaList;
523 PragmaList mPragmas;
524
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700525 typedef std::list<void*> ExportVarList;
526 ExportVarList mExportVars;
527
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700528 typedef std::list<void*> ExportFuncList;
529 ExportFuncList mExportFuncs;
530
Zonr Chang932648d2010-10-13 22:23:56 +0800531 //////////////////////////////////////////////////////////////////////////////
532 // Memory manager for the code reside in memory
533 //
534 // The memory for our code emitter is very simple and is conforming to the
535 // design decisions of Android RenderScript's Exection Environment:
536 // The code, data, and symbol sizes are limited (currently 100KB.)
537 //
538 // It's very different from typical compiler, which has no limitation
539 // on the code size. How does code emitter know the size of the code
540 // it is about to emit? It does not know beforehand. We want to solve
541 // this without complicating the code emitter too much.
542 //
543 // We solve this by pre-allocating a certain amount of memory,
544 // and then start the code emission. Once the buffer overflows, the emitter
545 // simply discards all the subsequent emission but still has a counter
546 // on how many bytes have been emitted.
547 //
548 // So once the whole emission is done, if there's a buffer overflow,
549 // it re-allocates the buffer with enough size (based on the
550 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800551
552 // 128 KiB for code
Loganc0b9f652010-11-24 22:33:16 +0800553 static const unsigned int MaxCodeSize = BCC_MMAP_IMG_CODE_SIZE;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800554 // 1 KiB for global offset table (GOT)
555 static const unsigned int MaxGOTSize = 1 * 1024;
556 // 128 KiB for global variable
Loganc0b9f652010-11-24 22:33:16 +0800557 static const unsigned int MaxGlobalVarSize = BCC_MMAP_IMG_DATA_SIZE;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800558
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700559 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700560 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800561 //
562 // Our memory layout is as follows:
563 //
564 // The direction of arrows (-> and <-) shows memory's growth direction
565 // when more space is needed.
566 //
567 // @mpCodeMem:
568 // +--------------------------------------------------------------+
569 // | Function Memory ... -> <- ... Stub/GOT |
570 // +--------------------------------------------------------------+
571 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
572 //
573 // Where size of GOT is @MaxGOTSize KiB.
574 //
575 // @mpGVMem:
576 // +--------------------------------------------------------------+
577 // | Global variable ... -> |
578 // +--------------------------------------------------------------+
579 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
580 //
581 //
582 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
583 // of function code's memory usage
584 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
585 // of stub/GOT's memory usage
586 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
587 // of global variable's memory usage
588 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700589 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700590 uintptr_t mCurSGMemIdx;
591 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800592 void *mpCodeMem;
593 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700594
Zonr Chang932648d2010-10-13 22:23:56 +0800595 // GOT Base
596 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700597
598 typedef std::map<const llvm::Function*, pair<void* /* start address */,
599 void* /* end address */>
600 > FunctionMapTy;
601 FunctionMapTy mFunctionMap;
602
Zonr Chang932648d2010-10-13 22:23:56 +0800603 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700604 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700605 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700606
Zonr Chang932648d2010-10-13 22:23:56 +0800607 uint8_t *allocateSGMemory(uintptr_t Size,
608 unsigned Alignment = 1 /* no alignment */) {
609 intptr_t FreeMemSize = getFreeCodeMemSize();
610 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
611 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700612 return NULL;
613
Zonr Chang932648d2010-10-13 22:23:56 +0800614 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700615 Alignment = 1;
616
Zonr Chang932648d2010-10-13 22:23:56 +0800617 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700618 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
619
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700620 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700621
622 return result;
623 }
624
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700625 inline uintptr_t getFreeGVMemSize() const {
626 return MaxGlobalVarSize - mCurGVMemIdx;
627 }
Zonr Chang932648d2010-10-13 22:23:56 +0800628 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700629 return reinterpret_cast<uint8_t*>(mpGVMem);
630 }
631
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700632 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700633 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700634 reset();
635 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700636
Loganc0b9f652010-11-24 22:33:16 +0800637 // Try to use fixed address
638
639 // Note: If we failed to allocate mpCodeMem at fixed address,
640 // the caching mechanism has to either perform relocation or
641 // give up. If the caching mechanism gives up, then we have to
642 // recompile the bitcode and wasting a lot of time.
643
644 for (size_t i = 0; i < BCC_MMAP_IMG_COUNT; ++i) {
645 if (Compiler::BccMmapImgAddrTaken[i]) {
646 // The address BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE has
647 // been taken.
648 continue;
649 }
650
651 // Occupy the mmap image address first (No matter allocation
652 // success or not. Keep occupying if succeed; otherwise,
653 // keep occupying as a mark of failure.)
654 Compiler::BccMmapImgAddrTaken[i] = true;
655
656 void *currMmapImgAddr =
657 reinterpret_cast<void *>(BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE);
658
659 mpCodeMem = mmap(currMmapImgAddr, BCC_MMAP_IMG_SIZE,
Loganad7e8e12010-11-22 20:43:43 +0800660 PROT_READ | PROT_EXEC | PROT_WRITE,
661 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
662 -1, 0);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800663
Loganad7e8e12010-11-22 20:43:43 +0800664 if (mpCodeMem == MAP_FAILED) {
Loganc0b9f652010-11-24 22:33:16 +0800665 LOGE("Mmap mpCodeMem at %p failed with reason: %s. Retrying ..\n",
666 currMmapImgAddr, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800667 } else {
Loganc0b9f652010-11-24 22:33:16 +0800668 // Good, we have got one mmap image address.
669 break;
Loganad7e8e12010-11-22 20:43:43 +0800670 }
671 }
672
Loganc0b9f652010-11-24 22:33:16 +0800673 if (!mpCodeMem || mpCodeMem == MAP_FAILED) {
674 LOGE("Try to allocate mpCodeMem at arbitary address.\n");
Loganad7e8e12010-11-22 20:43:43 +0800675
Loganc0b9f652010-11-24 22:33:16 +0800676 mpCodeMem = mmap(NULL, BCC_MMAP_IMG_SIZE,
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800677 PROT_READ | PROT_EXEC | PROT_WRITE,
678 MAP_PRIVATE | MAP_ANON,
Loganad7e8e12010-11-22 20:43:43 +0800679 -1, 0);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800680
Loganad7e8e12010-11-22 20:43:43 +0800681 if (mpCodeMem == MAP_FAILED) {
682 LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
683 llvm::report_fatal_error("Failed to allocate memory for emitting "
684 "codes\n" + ErrMsg);
685 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800686 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800687
Loganc0b9f652010-11-24 22:33:16 +0800688 LOGE("Mmap mpCodeMem at %p successfully.\n", mpCodeMem);
689
Loganad7e8e12010-11-22 20:43:43 +0800690 // Set global variable pool
691 mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
692
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700693 return;
694 }
695
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800696 inline uint8_t *getCodeMemBase() const {
697 return reinterpret_cast<uint8_t*>(mpCodeMem);
698 }
699
Zonr Chang932648d2010-10-13 22:23:56 +0800700 // setMemoryWritable - When code generation is in progress, the code pages
701 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700702 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700703 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700704 return;
705 }
706
Zonr Chang932648d2010-10-13 22:23:56 +0800707 // When code generation is done and we're ready to start execution, the
708 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700709 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700710 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700711 return;
712 }
713
Zonr Chang932648d2010-10-13 22:23:56 +0800714 // Setting this flag to true makes the memory manager garbage values over
715 // freed memory. This is useful for testing and debugging, and is to be
716 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700717 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800718 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700719 return;
720 }
721
Zonr Chang932648d2010-10-13 22:23:56 +0800722 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700723
Zonr Chang932648d2010-10-13 22:23:56 +0800724 // If the current table requires a Global Offset Table, this method is
725 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700726 void AllocateGOT() {
727 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700728 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700729 HasGOT = true;
730 return;
731 }
732
Zonr Chang932648d2010-10-13 22:23:56 +0800733 // If this is managing a Global Offset Table, this method should return a
734 // pointer to its base.
735 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700736 return mpGOTBase;
737 }
738
Zonr Chang932648d2010-10-13 22:23:56 +0800739 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700740
Zonr Chang932648d2010-10-13 22:23:56 +0800741 // When we start JITing a function, the JIT calls this method to allocate a
742 // block of free RWX memory, which returns a pointer to it. If the JIT wants
743 // to request a block of memory of at least a certain size, it passes that
744 // value as ActualSize, and this method returns a block with at least that
745 // much space. If the JIT doesn't know ahead of time how much space it will
746 // need to emit the function, it passes 0 for the ActualSize. In either
747 // case, this method is required to pass back the size of the allocated
748 // block through ActualSize. The JIT will be careful to not write more than
749 // the returned ActualSize bytes of memory.
750 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
751 intptr_t FreeMemSize = getFreeCodeMemSize();
752 if ((FreeMemSize < 0) ||
753 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
754 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700755 return NULL;
756
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700757 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700758 return (getCodeMemBase() + mCurFuncMemIdx);
759 }
760
Zonr Chang932648d2010-10-13 22:23:56 +0800761 // This method is called by the JIT to allocate space for a function stub
762 // (used to handle limited branch displacements) while it is JIT compiling a
763 // function. For example, if foo calls bar, and if bar either needs to be
764 // lazily compiled or is a native function that exists too far away from the
765 // call site to work, this method will be used to make a thunk for it. The
766 // stub should be "close" to the current function body, but should not be
767 // included in the 'actualsize' returned by startFunctionBody.
768 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700769 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700770 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700771 }
772
Zonr Chang932648d2010-10-13 22:23:56 +0800773 // This method is called when the JIT is done codegen'ing the specified
774 // function. At this point we know the size of the JIT compiled function.
775 // This passes in FunctionStart (which was returned by the startFunctionBody
776 // method) and FunctionEnd which is a pointer to the actual end of the
777 // function. This method should mark the space allocated and remember where
778 // it is in case the client wants to deallocate it.
779 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
780 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700781 assert(FunctionEnd > FunctionStart);
782 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
783 "Mismatched function start/end!");
784
Zonr Chang932648d2010-10-13 22:23:56 +0800785 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700786 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700787 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700788 "Code size excess the limitation!");
789 mCurFuncMemIdx += FunctionCodeSize;
790
Zonr Chang932648d2010-10-13 22:23:56 +0800791 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700792 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
793 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800794 mFunctionMap.insert(
795 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
796 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700797
798 return;
799 }
800
Zonr Chang932648d2010-10-13 22:23:56 +0800801 // Allocate a (function code) memory block of the given size. This method
802 // cannot be called between calls to startFunctionBody and endFunctionBody.
803 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
804 if (getFreeCodeMemSize() < Size)
805 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700806 return NULL;
807
Zonr Chang932648d2010-10-13 22:23:56 +0800808 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700809 Alignment = 1;
810
Zonr Chang932648d2010-10-13 22:23:56 +0800811 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700812 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800813 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700814
815 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
816
817 return result;
818 }
819
Zonr Chang932648d2010-10-13 22:23:56 +0800820 // Allocate memory for a global variable.
821 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700822 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800823 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700824 LOGE("No Global Memory");
825 return NULL;
826 }
827
Zonr Chang932648d2010-10-13 22:23:56 +0800828 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700829 Alignment = 1;
830
Zonr Chang932648d2010-10-13 22:23:56 +0800831 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700832 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800833 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700834
835 mCurGVMemIdx = (result + Size) - getGVMemBase();
836
837 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700838 }
839
Zonr Chang932648d2010-10-13 22:23:56 +0800840 // Free the specified function body. The argument must be the return value
841 // from a call to startFunctionBody() that hasn't been deallocated yet. This
842 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700843 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800844 // linear search
845 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
846 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
847 E = mFunctionMap.end();
848 I != E;
849 I++)
850 if (I->second.first == Body) {
851 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
852 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700853 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800854 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700855
Zonr Chang932648d2010-10-13 22:23:56 +0800856 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700857
Zonr Chang932648d2010-10-13 22:23:56 +0800858 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700859 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
860
861 assert(SizeNeedMove >= 0 &&
862 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
863 " be correctly calculated!");
864
Zonr Chang932648d2010-10-13 22:23:56 +0800865 if (SizeNeedMove > 0)
866 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700867 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
868 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
869
870 return;
871 }
872
Zonr Chang932648d2010-10-13 22:23:56 +0800873 // When we finished JITing the function, if exception handling is set, we
874 // emit the exception table.
875 uint8_t *startExceptionTable(const llvm::Function *F,
876 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700877 assert(false && "Exception is not allowed in our language specification");
878 return NULL;
879 }
880
Zonr Chang932648d2010-10-13 22:23:56 +0800881 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700882 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800883 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700884 assert(false && "Exception is not allowed in our language specification");
885 return;
886 }
887
Zonr Chang932648d2010-10-13 22:23:56 +0800888 // Free the specified exception table's memory. The argument must be the
889 // return value from a call to startExceptionTable() that hasn't been
890 // deallocated yet. This is never called when the JIT is currently emitting
891 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700892 void deallocateExceptionTable(void *ET) {
893 assert(false && "Exception is not allowed in our language specification");
894 return;
895 }
896
Zonr Chang932648d2010-10-13 22:23:56 +0800897 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700898 void reset() {
899 mpGOTBase = NULL;
900 HasGOT = false;
901
902 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700903 mCurSGMemIdx = MaxCodeSize - 1;
904 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700905
906 mFunctionMap.clear();
907
908 return;
909 }
910
911 ~CodeMemoryManager() {
Logan82e67012010-11-25 00:29:34 +0800912 if (mpCodeMem && mpCodeMem != MAP_FAILED) {
913 munmap(mpCodeMem, BCC_MMAP_IMG_SIZE);
Loganc0b9f652010-11-24 22:33:16 +0800914
915 // TODO(logan): Reset Compiler::BccMmapImgAddrTaken[i] to false, so
916 // that the address can be reused.
917 }
Logan82e67012010-11-25 00:29:34 +0800918
919 mpCodeMem = 0;
920 mpGVMem = 0;
921
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700922 return;
923 }
Zonr Chang932648d2010-10-13 22:23:56 +0800924 };
925 // End of class CodeMemoryManager
926 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700927
Zonr Chang932648d2010-10-13 22:23:56 +0800928 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700929 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800930 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700931 mCodeMemMgr.reset(new CodeMemoryManager());
932 return mCodeMemMgr.get();
933 }
934
Zonr Chang932648d2010-10-13 22:23:56 +0800935 //////////////////////////////////////////////////////////////////////////////
936 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700937 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700938 public:
939 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
940 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
941
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800942 GlobalAddressMapTy mGlobalAddressMap;
943
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700944 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800945 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700946
Zonr Chang932648d2010-10-13 22:23:56 +0800947 // The JITInfo for the target we are compiling to
948 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700949
Zonr Chang932648d2010-10-13 22:23:56 +0800950 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700951
Zonr Chang932648d2010-10-13 22:23:56 +0800952 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700953
Zonr Chang932648d2010-10-13 22:23:56 +0800954 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700955
Zonr Chang932648d2010-10-13 22:23:56 +0800956 typedef std::map<const std::string,
957 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700958 EmittedFunctionsMapTy mEmittedFunctions;
959
Zonr Chang932648d2010-10-13 22:23:56 +0800960 // This vector is a mapping from MBB ID's to their address. It is filled in
961 // by the StartMachineBasicBlock callback and queried by the
962 // getMachineBasicBlockAddress callback.
963 std::vector<uintptr_t> mMBBLocations;
964
965 // The constant pool for the current function.
966 llvm::MachineConstantPool *mpConstantPool;
967
968 // A pointer to the first entry in the constant pool.
969 void *mpConstantPoolBase;
970
971 // Addresses of individual constant pool entries.
972 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
973
974 // The jump tables for the current function.
975 llvm::MachineJumpTableInfo *mpJumpTable;
976
977 // A pointer to the first entry in the jump table.
978 void *mpJumpTableBase;
979
980 // When outputting a function stub in the context of some other function, we
981 // save BufferBegin/BufferEnd/CurBufferPtr here.
982 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
983
984 // These are the relocations that the function needs, as emitted.
985 std::vector<llvm::MachineRelocation> mRelocations;
986
Logan824dd0a2010-11-20 01:45:54 +0800987 std::vector<oBCCRelocEntry> mCachingRelocations;
988
Zonr Chang932648d2010-10-13 22:23:56 +0800989 // This vector is a mapping from Label ID's to their address.
990 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
991
992 // Machine module info for exception informations
993 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700994
Zonr Chang932648d2010-10-13 22:23:56 +0800995 // Replace an existing mapping for GV with a new address. This updates both
996 // maps as required. If Addr is null, the entry for the global is removed
997 // from the mappings.
998 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
999 if (Addr == NULL) {
1000 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001001 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
1002 void *OldVal;
1003
Zonr Chang932648d2010-10-13 22:23:56 +08001004 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001005 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001006 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001007 OldVal = I->second;
1008 mGlobalAddressMap.erase(I);
1009 }
1010
1011 return OldVal;
1012 }
1013
Zonr Chang932648d2010-10-13 22:23:56 +08001014 void *&CurVal = mGlobalAddressMap[GV];
1015 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001016
1017 CurVal = Addr;
1018
1019 return OldVal;
1020 }
1021
Zonr Chang932648d2010-10-13 22:23:56 +08001022 // Tell the execution engine that the specified global is at the specified
1023 // location. This is used internally as functions are JIT'd and as global
1024 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001025 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001026 void *&CurVal = mGlobalAddressMap[GV];
1027 assert((CurVal == 0 || Addr == 0) &&
1028 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001029 CurVal = Addr;
1030 return;
1031 }
1032
Zonr Chang932648d2010-10-13 22:23:56 +08001033 // This returns the address of the specified global value if it is has
1034 // already been codegen'd, otherwise it returns null.
1035 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001036 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001037 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
1038 }
1039
Zonr Chang932648d2010-10-13 22:23:56 +08001040 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
1041 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001042 MCP->getConstants();
1043
Zonr Chang932648d2010-10-13 22:23:56 +08001044 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001045 return 0;
1046
1047 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001048 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001049 llvm::MachineConstantPoolEntry CPE = Constants[i];
1050 unsigned int AlignMask = CPE.getAlignment() - 1;
1051 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +08001052 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001053 Size += mpTD->getTypeAllocSize(Ty);
1054 }
1055
1056 return Size;
1057 }
1058
Zonr Chang932648d2010-10-13 22:23:56 +08001059 // This function converts a Constant* into a GenericValue. The interesting
1060 // part is if C is a ConstantExpr.
1061 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
1062 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001063 return;
Zonr Chang932648d2010-10-13 22:23:56 +08001064 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
1065 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
1066 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001067
Zonr Chang932648d2010-10-13 22:23:56 +08001068 switch (CE->getOpcode()) {
1069 case llvm::Instruction::GetElementPtr: {
1070 // Compute the index
1071 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
1072 CE->op_end());
1073 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
1074 &Indices[0],
1075 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001076
Zonr Chang932648d2010-10-13 22:23:56 +08001077 GetConstantValue(Op0, Result);
1078 Result.PointerVal =
1079 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001080
Zonr Chang932648d2010-10-13 22:23:56 +08001081 return;
1082 }
1083 case llvm::Instruction::Trunc: {
1084 uint32_t BitWidth =
1085 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1086
1087 GetConstantValue(Op0, Result);
1088 Result.IntVal = Result.IntVal.trunc(BitWidth);
1089
1090 return;
1091 }
1092 case llvm::Instruction::ZExt: {
1093 uint32_t BitWidth =
1094 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1095
1096 GetConstantValue(Op0, Result);
1097 Result.IntVal = Result.IntVal.zext(BitWidth);
1098
1099 return;
1100 }
1101 case llvm::Instruction::SExt: {
1102 uint32_t BitWidth =
1103 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1104
1105 GetConstantValue(Op0, Result);
1106 Result.IntVal = Result.IntVal.sext(BitWidth);
1107
1108 return;
1109 }
1110 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001111 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001112 GetConstantValue(Op0, Result);
1113 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1114 return;
1115 }
1116 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001117 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001118 GetConstantValue(Op0, Result);
1119 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1120 return;
1121 }
1122 case llvm::Instruction::UIToFP: {
1123 GetConstantValue(Op0, Result);
1124 if (CE->getType()->isFloatTy())
1125 Result.FloatVal =
1126 static_cast<float>(Result.IntVal.roundToDouble());
1127 else if (CE->getType()->isDoubleTy())
1128 Result.DoubleVal = Result.IntVal.roundToDouble();
1129 else if (CE->getType()->isX86_FP80Ty()) {
1130 const uint64_t zero[] = { 0, 0 };
1131 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1132 apf.convertFromAPInt(Result.IntVal,
1133 false,
1134 llvm::APFloat::rmNearestTiesToEven);
1135 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001136 }
Zonr Chang932648d2010-10-13 22:23:56 +08001137 return;
1138 }
1139 case llvm::Instruction::SIToFP: {
1140 GetConstantValue(Op0, Result);
1141 if (CE->getType()->isFloatTy())
1142 Result.FloatVal =
1143 static_cast<float>(Result.IntVal.signedRoundToDouble());
1144 else if (CE->getType()->isDoubleTy())
1145 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1146 else if (CE->getType()->isX86_FP80Ty()) {
1147 const uint64_t zero[] = { 0, 0 };
1148 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1149 apf.convertFromAPInt(Result.IntVal,
1150 true,
1151 llvm::APFloat::rmNearestTiesToEven);
1152 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001153 }
Zonr Chang932648d2010-10-13 22:23:56 +08001154 return;
1155 }
1156 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001157 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001158 case llvm::Instruction::FPToSI: {
1159 uint32_t BitWidth =
1160 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001161
Zonr Chang932648d2010-10-13 22:23:56 +08001162 GetConstantValue(Op0, Result);
1163 if (Op0->getType()->isFloatTy())
1164 Result.IntVal =
1165 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1166 else if (Op0->getType()->isDoubleTy())
1167 Result.IntVal =
1168 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1169 BitWidth);
1170 else if (Op0->getType()->isX86_FP80Ty()) {
1171 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1172 uint64_t V;
1173 bool Ignored;
1174 apf.convertToInteger(&V,
1175 BitWidth,
1176 CE->getOpcode() == llvm::Instruction::FPToSI,
1177 llvm::APFloat::rmTowardZero,
1178 &Ignored);
1179 Result.IntVal = V; // endian?
1180 }
1181 return;
1182 }
1183 case llvm::Instruction::PtrToInt: {
1184 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1185
1186 GetConstantValue(Op0, Result);
1187 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1188 (Result.PointerVal));
1189
1190 return;
1191 }
1192 case llvm::Instruction::IntToPtr: {
1193 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1194
1195 GetConstantValue(Op0, Result);
1196 if (PtrWidth != Result.IntVal.getBitWidth())
1197 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1198 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1199
1200 Result.PointerVal =
1201 llvm::PointerTy(
1202 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1203
1204 return;
1205 }
1206 case llvm::Instruction::BitCast: {
1207 GetConstantValue(Op0, Result);
1208 const llvm::Type *DestTy = CE->getType();
1209
1210 switch (Op0->getType()->getTypeID()) {
1211 case llvm::Type::IntegerTyID: {
1212 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1213 if (DestTy->isFloatTy())
1214 Result.FloatVal = Result.IntVal.bitsToFloat();
1215 else if (DestTy->isDoubleTy())
1216 Result.DoubleVal = Result.IntVal.bitsToDouble();
1217 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001218 }
Zonr Chang932648d2010-10-13 22:23:56 +08001219 case llvm::Type::FloatTyID: {
1220 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1221 Result.IntVal.floatToBits(Result.FloatVal);
1222 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001223 }
Zonr Chang932648d2010-10-13 22:23:56 +08001224 case llvm::Type::DoubleTyID: {
1225 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1226 Result.IntVal.doubleToBits(Result.DoubleVal);
1227 break;
1228 }
1229 case llvm::Type::PointerTyID: {
1230 assert(DestTy->isPointerTy() && "Invalid bitcast");
1231 break; // getConstantValue(Op0) above already converted it
1232 }
1233 default: {
1234 llvm_unreachable("Invalid bitcast operand");
1235 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001236 }
Zonr Chang932648d2010-10-13 22:23:56 +08001237 return;
1238 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001239 case llvm::Instruction::Add:
1240 case llvm::Instruction::FAdd:
1241 case llvm::Instruction::Sub:
1242 case llvm::Instruction::FSub:
1243 case llvm::Instruction::Mul:
1244 case llvm::Instruction::FMul:
1245 case llvm::Instruction::UDiv:
1246 case llvm::Instruction::SDiv:
1247 case llvm::Instruction::URem:
1248 case llvm::Instruction::SRem:
1249 case llvm::Instruction::And:
1250 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001251 case llvm::Instruction::Xor: {
1252 llvm::GenericValue LHS, RHS;
1253 GetConstantValue(Op0, LHS);
1254 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001255
Zonr Chang932648d2010-10-13 22:23:56 +08001256 switch (Op0->getType()->getTypeID()) {
1257 case llvm::Type::IntegerTyID: {
1258 switch (CE->getOpcode()) {
1259 case llvm::Instruction::Add: {
1260 Result.IntVal = LHS.IntVal + RHS.IntVal;
1261 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001262 }
Zonr Chang932648d2010-10-13 22:23:56 +08001263 case llvm::Instruction::Sub: {
1264 Result.IntVal = LHS.IntVal - RHS.IntVal;
1265 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001266 }
Zonr Chang932648d2010-10-13 22:23:56 +08001267 case llvm::Instruction::Mul: {
1268 Result.IntVal = LHS.IntVal * RHS.IntVal;
1269 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001270 }
Zonr Chang932648d2010-10-13 22:23:56 +08001271 case llvm::Instruction::UDiv: {
1272 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1273 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001274 }
Zonr Chang932648d2010-10-13 22:23:56 +08001275 case llvm::Instruction::SDiv: {
1276 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1277 break;
1278 }
1279 case llvm::Instruction::URem: {
1280 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1281 break;
1282 }
1283 case llvm::Instruction::SRem: {
1284 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1285 break;
1286 }
1287 case llvm::Instruction::And: {
1288 Result.IntVal = LHS.IntVal & RHS.IntVal;
1289 break;
1290 }
1291 case llvm::Instruction::Or: {
1292 Result.IntVal = LHS.IntVal | RHS.IntVal;
1293 break;
1294 }
1295 case llvm::Instruction::Xor: {
1296 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1297 break;
1298 }
1299 default: {
1300 llvm_unreachable("Invalid integer opcode");
1301 }
1302 }
1303 break;
1304 }
1305 case llvm::Type::FloatTyID: {
1306 switch (CE->getOpcode()) {
1307 case llvm::Instruction::FAdd: {
1308 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1309 break;
1310 }
1311 case llvm::Instruction::FSub: {
1312 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1313 break;
1314 }
1315 case llvm::Instruction::FMul: {
1316 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1317 break;
1318 }
1319 case llvm::Instruction::FDiv: {
1320 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1321 break;
1322 }
1323 case llvm::Instruction::FRem: {
1324 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1325 break;
1326 }
1327 default: {
1328 llvm_unreachable("Invalid float opcode");
1329 }
1330 }
1331 break;
1332 }
1333 case llvm::Type::DoubleTyID: {
1334 switch (CE->getOpcode()) {
1335 case llvm::Instruction::FAdd: {
1336 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1337 break;
1338 }
1339 case llvm::Instruction::FSub: {
1340 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1341 break;
1342 }
1343 case llvm::Instruction::FMul: {
1344 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1345 break;
1346 }
1347 case llvm::Instruction::FDiv: {
1348 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1349 break;
1350 }
1351 case llvm::Instruction::FRem: {
1352 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1353 break;
1354 }
1355 default: {
1356 llvm_unreachable("Invalid double opcode");
1357 }
1358 }
1359 break;
1360 }
1361 case llvm::Type::X86_FP80TyID:
1362 case llvm::Type::PPC_FP128TyID:
1363 case llvm::Type::FP128TyID: {
1364 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1365 switch (CE->getOpcode()) {
1366 case llvm::Instruction::FAdd: {
1367 apfLHS.add(llvm::APFloat(RHS.IntVal),
1368 llvm::APFloat::rmNearestTiesToEven);
1369 break;
1370 }
1371 case llvm::Instruction::FSub: {
1372 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1373 llvm::APFloat::rmNearestTiesToEven);
1374 break;
1375 }
1376 case llvm::Instruction::FMul: {
1377 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1378 llvm::APFloat::rmNearestTiesToEven);
1379 break;
1380 }
1381 case llvm::Instruction::FDiv: {
1382 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1383 llvm::APFloat::rmNearestTiesToEven);
1384 break;
1385 }
1386 case llvm::Instruction::FRem: {
1387 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1388 llvm::APFloat::rmNearestTiesToEven);
1389 break;
1390 }
1391 default: {
1392 llvm_unreachable("Invalid long double opcode");
1393 }
1394 }
1395 Result.IntVal = apfLHS.bitcastToAPInt();
1396 break;
1397 }
1398 default: {
1399 llvm_unreachable("Bad add type!");
1400 }
1401 } // End switch (Op0->getType()->getTypeID())
1402 return;
1403 }
1404 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001405 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001406 }
1407 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001408
1409 std::string msg;
1410 llvm::raw_string_ostream Msg(msg);
1411 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001412 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001413 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001414
1415 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001416 case llvm::Type::FloatTyID: {
1417 Result.FloatVal =
1418 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001419 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001420 }
1421 case llvm::Type::DoubleTyID: {
1422 Result.DoubleVal =
1423 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001424 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001425 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001426 case llvm::Type::X86_FP80TyID:
1427 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001428 case llvm::Type::PPC_FP128TyID: {
1429 Result.IntVal =
1430 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001431 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001432 }
1433 case llvm::Type::IntegerTyID: {
1434 Result.IntVal =
1435 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001436 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001437 }
1438 case llvm::Type::PointerTyID: {
1439 switch (C->getValueID()) {
1440 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001441 Result.PointerVal = NULL;
1442 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001443 }
1444 case llvm::Value::FunctionVal: {
1445 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1446 Result.PointerVal =
1447 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001448 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001449 }
1450 case llvm::Value::GlobalVariableVal: {
1451 const llvm::GlobalVariable *GV =
1452 static_cast<const llvm::GlobalVariable*>(C);
1453 Result.PointerVal =
1454 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001455 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001456 }
1457 case llvm::Value::BlockAddressVal: {
1458 assert(false && "JIT does not support address-of-label yet!");
1459 }
1460 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001461 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001462 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001463 }
1464 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001465 }
1466 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001467 std::string msg;
1468 llvm::raw_string_ostream Msg(msg);
1469 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001470 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001471 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001472 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001473 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001474 return;
1475 }
1476
Zonr Chang932648d2010-10-13 22:23:56 +08001477 // Stores the data in @Val of type @Ty at address @Addr.
1478 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001479 const llvm::Type *Ty) {
1480 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1481
Zonr Chang932648d2010-10-13 22:23:56 +08001482 switch (Ty->getTypeID()) {
1483 case llvm::Type::IntegerTyID: {
1484 const llvm::APInt &IntVal = Val.IntVal;
1485 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1486 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001487
Zonr Chang932648d2010-10-13 22:23:56 +08001488 const uint8_t *Src =
1489 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001490
Zonr Chang932648d2010-10-13 22:23:56 +08001491 if (llvm::sys::isLittleEndianHost()) {
1492 // Little-endian host - the source is ordered from LSB to MSB.
1493 // Order the destination from LSB to MSB: Do a straight copy.
1494 memcpy(Addr, Src, StoreBytes);
1495 } else {
1496 // Big-endian host - the source is an array of 64 bit words
1497 // ordered from LSW to MSW.
1498 //
1499 // Each word is ordered from MSB to LSB.
1500 //
1501 // Order the destination from MSB to LSB:
1502 // Reverse the word order, but not the bytes in a word.
1503 unsigned int i = StoreBytes;
1504 while (i > sizeof(uint64_t)) {
1505 i -= sizeof(uint64_t);
1506 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1507 Src,
1508 sizeof(uint64_t));
1509 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001510 }
Zonr Chang932648d2010-10-13 22:23:56 +08001511 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001512 }
1513 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001514 }
1515 case llvm::Type::FloatTyID: {
1516 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001517 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001518 }
1519 case llvm::Type::DoubleTyID: {
1520 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001521 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001522 }
1523 case llvm::Type::X86_FP80TyID: {
1524 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001525 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001526 }
1527 case llvm::Type::PointerTyID: {
1528 // Ensure 64 bit target pointers are fully initialized on 32 bit
1529 // hosts.
1530 if (StoreBytes != sizeof(llvm::PointerTy))
1531 memset(Addr, 0, StoreBytes);
1532 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001533 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001534 }
1535 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001536 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001537 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001538 }
1539
Zonr Chang932648d2010-10-13 22:23:56 +08001540 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1541 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1542 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001543
1544 return;
1545 }
1546
Zonr Chang932648d2010-10-13 22:23:56 +08001547 // Recursive function to apply a @Constant value into the specified memory
1548 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001549 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001550 switch (C->getValueID()) {
1551 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001552 // Nothing to do
1553 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001554 }
1555 case llvm::Value::ConstantVectorVal: {
1556 // dynamic cast may hurt performance
1557 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001558
Zonr Chang932648d2010-10-13 22:23:56 +08001559 unsigned int ElementSize = mpTD->getTypeAllocSize
1560 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001561
Zonr Chang932648d2010-10-13 22:23:56 +08001562 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1563 InitializeConstantToMemory(
1564 CP->getOperand(i),
1565 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001566 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001567 }
1568 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001569 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1570 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001571 }
1572 case llvm::Value::ConstantArrayVal: {
1573 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1574 unsigned int ElementSize = mpTD->getTypeAllocSize
1575 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001576
Zonr Chang932648d2010-10-13 22:23:56 +08001577 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1578 InitializeConstantToMemory(
1579 CPA->getOperand(i),
1580 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1581 break;
1582 }
1583 case llvm::Value::ConstantStructVal: {
1584 const llvm::ConstantStruct *CPS =
1585 static_cast<const llvm::ConstantStruct*>(C);
1586 const llvm::StructLayout *SL = mpTD->getStructLayout
1587 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001588
Zonr Chang932648d2010-10-13 22:23:56 +08001589 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1590 InitializeConstantToMemory(
1591 CPS->getOperand(i),
1592 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1593 break;
1594 }
1595 default: {
1596 if (C->getType()->isFirstClassType()) {
1597 llvm::GenericValue Val;
1598 GetConstantValue(C, Val);
1599 StoreValueToMemory(Val, Addr, C->getType());
1600 } else {
1601 llvm_unreachable("Unknown constant type to initialize memory "
1602 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001603 }
1604 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001605 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001606 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001607 return;
1608 }
1609
1610 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001611 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001612 return;
1613
Zonr Chang932648d2010-10-13 22:23:56 +08001614 // Constant pool address resolution is handled by the target itself in ARM
1615 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001616#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001617 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1618 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001619
Zonr Chang932648d2010-10-13 22:23:56 +08001620 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001621 return;
1622
1623 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1624 unsigned Align = MCP->getConstantPoolAlignment();
1625
1626 mpConstantPoolBase = allocateSpace(Size, Align);
1627 mpConstantPool = MCP;
1628
Zonr Chang932648d2010-10-13 22:23:56 +08001629 if (mpConstantPoolBase == NULL)
1630 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001631
1632 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001633 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001634 llvm::MachineConstantPoolEntry CPE = Constants[i];
1635 unsigned AlignMask = CPE.getAlignment() - 1;
1636 Offset = (Offset + AlignMask) & ~AlignMask;
1637
1638 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1639 mConstPoolAddresses.push_back(CAddr);
1640
Zonr Chang932648d2010-10-13 22:23:56 +08001641 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001642 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001643 ("Initialize memory with machine specific constant pool"
1644 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001645
1646 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1647
1648 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1649 Offset += mpTD->getTypeAllocSize(Ty);
1650 }
1651#endif
1652 return;
1653 }
1654
1655 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001656 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001657 return;
1658
Zonr Chang932648d2010-10-13 22:23:56 +08001659 const std::vector<llvm::MachineJumpTableEntry> &JT =
1660 MJTI->getJumpTables();
1661 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001662 return;
1663
1664 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001665 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001666 NumEntries += JT[i].MBBs.size();
1667
1668 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1669
Zonr Chang932648d2010-10-13 22:23:56 +08001670 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001671 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001672 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001673
1674 return;
1675 }
1676
1677 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001678 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001679 return;
1680
Zonr Chang932648d2010-10-13 22:23:56 +08001681 const std::vector<llvm::MachineJumpTableEntry> &JT =
1682 MJTI->getJumpTables();
1683 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001684 return;
1685
Zonr Chang932648d2010-10-13 22:23:56 +08001686 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1687 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1688 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001689
Zonr Chang932648d2010-10-13 22:23:56 +08001690 // For each jump table, map each target in the jump table to the
1691 // address of an emitted MachineBasicBlock.
1692 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1693 for (int i = 0, ie = JT.size(); i != ie; i++) {
1694 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1695 // Store the address of the basic block for this jump table slot in the
1696 // memory we allocated for the jump table in 'initJumpTableInfo'
1697 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001698 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1699 }
1700 }
1701
Zonr Chang932648d2010-10-13 22:23:56 +08001702 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1703 bool MayNeedFarStub) {
1704 switch (V->getValueID()) {
1705 case llvm::Value::FunctionVal: {
1706 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001707
Zonr Chang932648d2010-10-13 22:23:56 +08001708 // If we have code, go ahead and return that.
1709 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1710 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001711
Zonr Chang932648d2010-10-13 22:23:56 +08001712 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1713 // Return the function stub if it's already created.
1714 // We do this first so that:
1715 // we're returning the same address for the function as any
1716 // previous call.
1717 //
1718 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1719 // guaranteed to be close enough to call.
1720 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001721
Zonr Chang932648d2010-10-13 22:23:56 +08001722 // If we know the target can handle arbitrary-distance calls, try to
1723 // return a direct pointer.
1724 if (!MayNeedFarStub) {
1725 //
1726 // x86_64 architecture may encounter the bug:
1727 // http://llvm.org/bugs/show_bug.cgi?id=5201
1728 // which generate instruction "call" instead of "callq".
1729 //
1730 // And once the real address of stub is greater than 64-bit
1731 // long, the replacement will truncate to 32-bit resulting a
1732 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001733#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001734 // If this is an external function pointer, we can force the JIT
1735 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001736 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1737 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1738 // Changing to false because wanting to allow later calls to
1739 // mpTJI->relocate() without aborting. For caching purpose
1740 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001741#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001742 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001743
Zonr Chang932648d2010-10-13 22:23:56 +08001744 // Otherwise, we may need a to emit a stub, and, conservatively, we
1745 // always do so.
1746 return GetLazyFunctionStub(F);
1747 break;
1748 }
1749 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001750 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1751 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001752 }
1753 case llvm::Value::GlobalAliasVal: {
1754 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1755 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001756
Zonr Chang932648d2010-10-13 22:23:56 +08001757 switch (GV->getValueID()) {
1758 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001759 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001760 // code-gen'd?
1761 return GetPointerToFunction(
1762 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001763 /* AbortOnFailure = */false);
1764 // Changing to false because wanting to allow later calls to
1765 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001766 break;
1767 }
1768 case llvm::Value::GlobalVariableVal: {
1769 if (void *P = mGlobalAddressMap[GV])
1770 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001771
Zonr Chang932648d2010-10-13 22:23:56 +08001772 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1773 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001774
Zonr Chang932648d2010-10-13 22:23:56 +08001775 return mGlobalAddressMap[GV];
1776 break;
1777 }
1778 case llvm::Value::GlobalAliasVal: {
1779 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001780 }
1781 }
1782 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001783 }
1784 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001785 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001786 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001787 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001788 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001789 }
1790
Zonr Chang932648d2010-10-13 22:23:56 +08001791 // If the specified function has been code-gen'd, return a pointer to the
1792 // function. If not, compile it, or use a stub to implement lazy compilation
1793 // if available.
1794 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1795 // If we have already code generated the function, just return the
1796 // address.
1797 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001798 return Addr;
1799
Zonr Chang932648d2010-10-13 22:23:56 +08001800 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001801 return GetLazyFunctionStub(F);
1802 }
1803
Zonr Chang932648d2010-10-13 22:23:56 +08001804 typedef llvm::DenseMap<const llvm::Function*,
1805 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001806 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1807
Zonr Chang932648d2010-10-13 22:23:56 +08001808 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001809 return mFunctionToLazyStubMap.lookup(F);
1810 }
1811
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001812 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001813 void *GetLazyFunctionStub(llvm::Function *F) {
1814 // If we already have a lazy stub for this function, recycle it.
1815 void *&Stub = mFunctionToLazyStubMap[F];
1816 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001817 return Stub;
1818
Zonr Chang932648d2010-10-13 22:23:56 +08001819 // In any cases, we should NOT resolve function at runtime (though we are
1820 // able to). We resolve this right now.
1821 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001822 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1823 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1824 // Changing to false because wanting to allow later calls to
1825 // mpTJI->relocate() without aborting. For caching purpose
1826 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001827
Zonr Chang932648d2010-10-13 22:23:56 +08001828 // Codegen a new stub, calling the actual address of the external
1829 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001830 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1831 startGVStub(F, SL.Size, SL.Alignment);
1832 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1833 finishGVStub();
1834
Zonr Chang932648d2010-10-13 22:23:56 +08001835 // We really want the address of the stub in the GlobalAddressMap for the
1836 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001837 UpdateGlobalMapping(F, Stub);
1838
Zonr Chang932648d2010-10-13 22:23:56 +08001839 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001840 PendingFunctions.insert(F);
1841 else
Zonr Chang932648d2010-10-13 22:23:56 +08001842 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1843 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001844
1845 return Stub;
1846 }
1847
Zonr Chang932648d2010-10-13 22:23:56 +08001848 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1849 void *Addr = GetPointerToGlobalIfAvailable(F);
1850 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001851 return Addr;
1852
1853 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1854 "Internal error: only external defined function routes here!");
1855
Zonr Chang932648d2010-10-13 22:23:56 +08001856 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001857 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001858 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001859
Zonr Chang932648d2010-10-13 22:23:56 +08001860 // If we resolved the symbol to a null address (eg. a weak external)
1861 // return a null pointer let the application handle it.
1862 if (Addr == NULL) {
1863 if (AbortOnFailure)
1864 llvm::report_fatal_error("Could not resolve external function "
1865 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001866 else
1867 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001868 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001869
1870 AddGlobalMapping(F, Addr);
1871
1872 return Addr;
1873 }
1874
Zonr Chang932648d2010-10-13 22:23:56 +08001875 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001876 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001877 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001878 return Addr;
1879
Zonr Chang932648d2010-10-13 22:23:56 +08001880 if (mpSymbolLookupFn)
1881 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001882 return Addr;
1883
Zonr Chang932648d2010-10-13 22:23:56 +08001884 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001885 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001886 "' which could not be resolved!");
1887
1888 return NULL;
1889 }
1890
Zonr Chang932648d2010-10-13 22:23:56 +08001891 // Return the address of the specified global variable, possibly emitting it
1892 // to memory if needed. This is used by the Emitter.
1893 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1894 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1895 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001896 return Ptr;
1897
Zonr Chang932648d2010-10-13 22:23:56 +08001898 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1899 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001900 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1901 AddGlobalMapping(GV, Ptr);
1902 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001903 // If the global hasn't been emitted to memory yet, allocate space and
1904 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001905 Ptr = GetMemoryForGV(GV);
1906 AddGlobalMapping(GV, Ptr);
1907 EmitGlobalVariable(GV);
1908 }
1909
1910 return Ptr;
1911 }
1912
Zonr Chang932648d2010-10-13 22:23:56 +08001913 // This method abstracts memory allocation of global variable so that the
1914 // JIT can allocate thread local variables depending on the target.
1915 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1916 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001917
Zonr Chang932648d2010-10-13 22:23:56 +08001918 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001919 size_t S = mpTD->getTypeAllocSize(GlobalType);
1920 size_t A = mpTD->getPreferredAlignment(GV);
1921
Zonr Chang932648d2010-10-13 22:23:56 +08001922 if (GV->isThreadLocal()) {
1923 // We can support TLS by
1924 //
1925 // Ptr = TJI.allocateThreadLocalMemory(S);
1926 //
1927 // But I tend not to.
1928 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001929 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001930 ("Compilation of Thread Local Storage (TLS) is disabled!");
1931
Zonr Chang932648d2010-10-13 22:23:56 +08001932 } else if (mpTJI->allocateSeparateGVMemory()) {
1933 if (A <= 8) {
1934 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001935 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001936 // Allocate (S + A) bytes of memory, then use an aligned pointer
1937 // within that space.
1938 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001939 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001940 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1941 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001942 }
1943 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001944 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001945 }
1946
1947 return Ptr;
1948 }
1949
1950 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001951 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001952
Zonr Chang932648d2010-10-13 22:23:56 +08001953 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001954 llvm::report_fatal_error
1955 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001956
Zonr Chang932648d2010-10-13 22:23:56 +08001957 if (GA == NULL) {
1958 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001959 GA = GetMemoryForGV(GV);
1960 AddGlobalMapping(GV, GA);
1961 }
1962
1963 InitializeConstantToMemory(GV->getInitializer(), GA);
1964
Zonr Chang932648d2010-10-13 22:23:56 +08001965 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001966 return;
1967 }
1968
1969 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1970 > GlobalToIndirectSymMapTy;
1971 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1972
Zonr Chang932648d2010-10-13 22:23:56 +08001973 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1974 // Make sure GV is emitted first, and create a stub containing the fully
1975 // resolved address.
1976 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001977
Zonr Chang932648d2010-10-13 22:23:56 +08001978 // If we already have a stub for this global variable, recycle it.
1979 void *&IndirectSym = GlobalToIndirectSymMap[V];
1980 // Otherwise, codegen a new indirect symbol.
1981 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001982 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1983
1984 return IndirectSym;
1985 }
1986
Zonr Chang932648d2010-10-13 22:23:56 +08001987 // This is the equivalent of FunctionToLazyStubMap for external functions.
1988 //
1989 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1990 // It's actually here to make it more likely that far calls
1991 // succeed, but no single stub can guarantee that. I'll
1992 // remove this in a subsequent checkin when I actually fix
1993 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001994 std::map<void*, void*> ExternalFnToStubMap;
1995
Zonr Chang932648d2010-10-13 22:23:56 +08001996 // Return a stub for the function at the specified address.
1997 void *GetExternalFunctionStub(void *FnAddr) {
1998 void *&Stub = ExternalFnToStubMap[FnAddr];
1999 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002000 return Stub;
2001
2002 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2003 startGVStub(0, SL.Size, SL.Alignment);
2004 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
2005 finishGVStub();
2006
2007 return Stub;
2008 }
2009
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002010#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002011 const llvm::MCAsmInfo *mpAsmInfo;
2012 const llvm::MCDisassembler *mpDisassmbler;
2013 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002014
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002015 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002016 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002017 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08002018 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002019#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002020 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08002021 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
2022 ErrorInfo,
2023 llvm::raw_fd_ostream::F_Append);
2024 if (!ErrorInfo.empty()) { // some errors occurred
2025 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002026 delete OS;
2027 return;
2028 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002029#else
2030 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002031#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002032 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
2033 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002034
Zonr Chang932648d2010-10-13 22:23:56 +08002035 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002036 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08002037 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002038 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08002039 if (mpIP == NULL)
2040 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
2041 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002042
Zonr Chang932648d2010-10-13 22:23:56 +08002043 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
2044 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002045 uint64_t Size;
2046 uint64_t Index;
2047
Zonr Chang932648d2010-10-13 22:23:56 +08002048 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002049 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002050
Zonr Chang932648d2010-10-13 22:23:56 +08002051 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2052 /* REMOVED */ llvm::nulls())) {
2053 (*OS).indent(4)
2054 .write("0x", 2)
2055 .write_hex((uint32_t) Start + Index)
2056 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002057 mpIP->printInst(&Inst, *OS);
2058 *OS << "\n";
2059 } else {
2060 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002061 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002062 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002063 }
2064
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002065 *OS << "\n";
2066 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002067
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002068#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002069 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002070 OS->close();
2071 delete OS;
2072#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002073 return;
2074 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002075#else
Zonr Chang932648d2010-10-13 22:23:56 +08002076 inline void Disassemble(const std::string &Name, uint8_t *Start,
2077 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002078 return;
2079 }
Zonr Chang932648d2010-10-13 22:23:56 +08002080#endif // defined(USE_DISASSEMBLER)
2081
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002082 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002083 // Resolver to undefined symbol in CodeEmitter
2084 BCCSymbolLookupFn mpSymbolLookupFn;
2085 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002086
2087 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002088 // Will take the ownership of @MemMgr
2089 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2090 : mpMemMgr(pMemMgr),
2091 mpTarget(NULL),
2092 mpTJI(NULL),
2093 mpTD(NULL),
2094 mpCurEmitFunction(NULL),
2095 mpConstantPool(NULL),
2096 mpJumpTable(NULL),
2097 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002098#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002099 mpAsmInfo(NULL),
2100 mpDisassmbler(NULL),
2101 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002102#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002103 mpSymbolLookupFn(NULL),
2104 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002105 return;
2106 }
2107
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002108 inline global_addresses_const_iterator global_address_begin() const {
2109 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002110 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002111 inline global_addresses_const_iterator global_address_end() const {
2112 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002113 }
2114
Logan824dd0a2010-11-20 01:45:54 +08002115 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2116 return mCachingRelocations;
2117 }
2118
Zonr Chang932648d2010-10-13 22:23:56 +08002119 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002120 mpSymbolLookupFn = pFn;
2121 mpSymbolLookupContext = pContext;
2122 return;
2123 }
2124
Zonr Chang932648d2010-10-13 22:23:56 +08002125 void setTargetMachine(llvm::TargetMachine &TM) {
2126 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002127 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002128 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002129 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002130 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002131 mpTD = TM.getTargetData();
2132
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002133 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2134
2135 return;
2136 }
2137
Zonr Chang932648d2010-10-13 22:23:56 +08002138 // This callback is invoked when the specified function is about to be code
2139 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002140 void startFunction(llvm::MachineFunction &F) {
2141 uintptr_t ActualSize = 0;
2142
2143 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002144
2145 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2146 // MachineCodeEmitter, which is the super class of the class
2147 // JITCodeEmitter.
2148 //
2149 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2150 // allocated for this code buffer.
2151 //
2152 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2153 // code. This is guranteed to be in the range
2154 // [BufferBegin, BufferEnd]. If this pointer is at
2155 // BufferEnd, it will never move due to code emission, and
2156 // all code emission requests will be ignored (this is the
2157 // buffer overflow condition).
2158 BufferBegin = CurBufferPtr =
2159 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002160 BufferEnd = BufferBegin + ActualSize;
2161
Zonr Chang932648d2010-10-13 22:23:56 +08002162 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002163 mpCurEmitFunction = new EmittedFunctionCode();
2164 mpCurEmitFunction->FunctionBody = BufferBegin;
2165
Zonr Chang932648d2010-10-13 22:23:56 +08002166 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002167 emitAlignment(16);
2168
2169 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002170 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002171 initJumpTableInfo(MJTI);
2172
Zonr Chang932648d2010-10-13 22:23:56 +08002173 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002174 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2175
2176 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2177
2178 mpCurEmitFunction->Code = CurBufferPtr;
2179
2180 mMBBLocations.clear();
2181
2182 return;
2183 }
2184
Zonr Chang932648d2010-10-13 22:23:56 +08002185 // This callback is invoked when the specified function has finished code
2186 // generation. If a buffer overflow has occurred, this method returns true
2187 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002188 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002189 if (CurBufferPtr == BufferEnd) {
2190 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002191 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2192 return false;
2193 }
2194
Zonr Chang932648d2010-10-13 22:23:56 +08002195 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002196 emitJumpTableInfo(MJTI);
2197
Zonr Chang932648d2010-10-13 22:23:56 +08002198 // FnStart is the start of the text, not the start of the constant pool
2199 // and other per-function data.
2200 uint8_t *FnStart =
2201 reinterpret_cast<uint8_t*>(
2202 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002203
Zonr Chang932648d2010-10-13 22:23:56 +08002204 // FnEnd is the end of the function's machine code.
2205 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002206
Zonr Chang932648d2010-10-13 22:23:56 +08002207 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002208 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2209
Zonr Chang932648d2010-10-13 22:23:56 +08002210 // Resolve the relocations to concrete pointers.
2211 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2212 llvm::MachineRelocation &MR = mRelocations[i];
2213 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002214
Zonr Chang932648d2010-10-13 22:23:56 +08002215 if (!MR.letTargetResolve()) {
2216 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002217 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002218
2219 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002220 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002221 }
2222
Zonr Chang932648d2010-10-13 22:23:56 +08002223 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002224 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2225 BufferBegin
2226 + MR.getMachineCodeOffset(),
2227 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002228 } else if (MR.isIndirectSymbol()) {
2229 ResultPtr =
2230 GetPointerToGVIndirectSym(
2231 MR.getGlobalValue(),
2232 BufferBegin + MR.getMachineCodeOffset());
2233 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002234 ResultPtr =
2235 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002236 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002237 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002238 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002239 } else {
2240 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2241 ResultPtr =
2242 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2243 }
2244
Logan824dd0a2010-11-20 01:45:54 +08002245 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2246 // TODO(logan): Cache external symbol relocation entry.
2247 // Currently, we are not caching them. But since Android
2248 // system is using prelink, it is not a problem.
2249
2250 // Cache the relocation result address
2251 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002252 oBCCRelocEntry(MR.getRelocationType(),
2253 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002254 ResultPtr));
2255 }
2256
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002257 MR.setResultPointer(ResultPtr);
2258 }
2259 }
2260
2261 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2262 mpMemMgr->getGOTBase());
2263 }
2264
2265 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002266 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2267 // global variables that were referenced in the relocations.
2268 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002269 return false;
2270
Zonr Chang932648d2010-10-13 22:23:56 +08002271 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002272 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2273 BufferBegin = CurBufferPtr = 0;
2274
Zonr Chang932648d2010-10-13 22:23:56 +08002275 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002276 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2277 mpCurEmitFunction = NULL;
2278
2279 mRelocations.clear();
2280 mConstPoolAddresses.clear();
2281
Zonr Chang932648d2010-10-13 22:23:56 +08002282 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002283 mpMMI->EndFunction();
2284
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002285 updateFunctionStub(F.getFunction());
2286
Zonr Chang932648d2010-10-13 22:23:56 +08002287 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002288 mpMemMgr->setMemoryExecutable();
2289
2290 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2291
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002292 return false;
2293 }
2294
Zonr Chang932648d2010-10-13 22:23:56 +08002295 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002296 unsigned Alignment) {
2297 mpSavedBufferBegin = BufferBegin;
2298 mpSavedBufferEnd = BufferEnd;
2299 mpSavedCurBufferPtr = CurBufferPtr;
2300
2301 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2302 Alignment);
2303 BufferEnd = BufferBegin + StubSize + 1;
2304
2305 return;
2306 }
2307
Zonr Chang932648d2010-10-13 22:23:56 +08002308 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002309 mpSavedBufferBegin = BufferBegin;
2310 mpSavedBufferEnd = BufferEnd;
2311 mpSavedCurBufferPtr = CurBufferPtr;
2312
Zonr Chang932648d2010-10-13 22:23:56 +08002313 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002314 BufferEnd = BufferBegin + StubSize + 1;
2315
2316 return;
2317 }
2318
2319 void finishGVStub() {
2320 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2321
Zonr Chang932648d2010-10-13 22:23:56 +08002322 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002323 BufferBegin = mpSavedBufferBegin;
2324 BufferEnd = mpSavedBufferEnd;
2325 CurBufferPtr = mpSavedCurBufferPtr;
2326
2327 return;
2328 }
2329
Zonr Chang932648d2010-10-13 22:23:56 +08002330 // Allocates and fills storage for an indirect GlobalValue, and returns the
2331 // address.
2332 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002333 const uint8_t *Buffer, size_t Size,
2334 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002335 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002336 memcpy(IndGV, Buffer, Size);
2337 return IndGV;
2338 }
2339
Zonr Chang932648d2010-10-13 22:23:56 +08002340 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002341 void emitLabel(llvm::MCSymbol *Label) {
2342 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002343 return;
2344 }
2345
Zonr Chang932648d2010-10-13 22:23:56 +08002346 // Allocate memory for a global. Unlike allocateSpace, this method does not
2347 // allocate memory in the current output buffer, because a global may live
2348 // longer than the current function.
2349 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2350 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002351 return mpMemMgr->allocateGlobal(Size, Alignment);
2352 }
2353
Zonr Chang932648d2010-10-13 22:23:56 +08002354 // This should be called by the target when a new basic block is about to be
2355 // emitted. This way the MCE knows where the start of the block is, and can
2356 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002357 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002358 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002359 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2360 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2361 return;
2362 }
2363
Zonr Chang932648d2010-10-13 22:23:56 +08002364 // Whenever a relocatable address is needed, it should be noted with this
2365 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002366 void addRelocation(const llvm::MachineRelocation &MR) {
2367 mRelocations.push_back(MR);
2368 return;
2369 }
2370
Zonr Chang932648d2010-10-13 22:23:56 +08002371 // Return the address of the @Index entry in the constant pool that was
2372 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002373 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2374 assert(Index < mpConstantPool->getConstants().size() &&
2375 "Invalid constant pool index!");
2376 return mConstPoolAddresses[Index];
2377 }
2378
Zonr Chang932648d2010-10-13 22:23:56 +08002379 // Return the address of the jump table with index @Index in the function
2380 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002381 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002382 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002383 mpJumpTable->getJumpTables();
2384
Zonr Chang932648d2010-10-13 22:23:56 +08002385 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002386
2387 unsigned int Offset = 0;
2388 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2389
Zonr Chang932648d2010-10-13 22:23:56 +08002390 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002391 Offset += JT[i].MBBs.size();
2392 Offset *= EntrySize;
2393
Zonr Chang932648d2010-10-13 22:23:56 +08002394 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002395 }
2396
Zonr Chang932648d2010-10-13 22:23:56 +08002397 // Return the address of the specified MachineBasicBlock, only usable after
2398 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002399 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2400 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002401 mMBBLocations[MBB->getNumber()] &&
2402 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002403 return mMBBLocations[MBB->getNumber()];
2404 }
2405
Zonr Chang932648d2010-10-13 22:23:56 +08002406 // Return the address of the specified LabelID, only usable after the
2407 // LabelID has been emitted.
2408 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002409 assert(mLabelLocations.count(Label) && "Label not emitted!");
2410 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002411 }
2412
Zonr Chang932648d2010-10-13 22:23:56 +08002413 // Specifies the MachineModuleInfo object. This is used for exception
2414 // handling purposes.
2415 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002416 mpMMI = Info;
2417 return;
2418 }
2419
Zonr Chang932648d2010-10-13 22:23:56 +08002420 void updateFunctionStub(const llvm::Function *F) {
2421 // Get the empty stub we generated earlier.
2422 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002423 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002424 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002425 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002426 else
2427 return;
2428
Zonr Chang932648d2010-10-13 22:23:56 +08002429 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002430
2431 assert(Addr != Stub &&
2432 "Function must have non-stub address to be updated.");
2433
Zonr Chang932648d2010-10-13 22:23:56 +08002434 // Tell the target jit info to rewrite the stub at the specified address,
2435 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002436 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2437 startGVStub(Stub, SL.Size);
2438 mpTJI->emitFunctionStub(F, Addr, *this);
2439 finishGVStub();
2440
Zonr Chang932648d2010-10-13 22:23:56 +08002441 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2442 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002443
2444 PendingFunctions.erase(I);
2445
2446 return;
2447 }
2448
Zonr Chang932648d2010-10-13 22:23:56 +08002449 // Once you finish the compilation on a translation unit, you can call this
2450 // function to recycle the memory (which is used at compilation time and not
2451 // needed for runtime).
2452 //
2453 // NOTE: You should not call this funtion until the code-gen passes for a
2454 // given module is done. Otherwise, the results is undefined and may
2455 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002456 void releaseUnnecessary() {
2457 mMBBLocations.clear();
2458 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002459 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002460 mFunctionToLazyStubMap.clear();
2461 GlobalToIndirectSymMap.clear();
2462 ExternalFnToStubMap.clear();
2463 PendingFunctions.clear();
2464
2465 return;
2466 }
2467
2468 void reset() {
2469 releaseUnnecessary();
2470
2471 mpSymbolLookupFn = NULL;
2472 mpSymbolLookupContext = NULL;
2473
2474 mpTJI = NULL;
2475 mpTD = NULL;
2476
Zonr Chang932648d2010-10-13 22:23:56 +08002477 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2478 E = mEmittedFunctions.end();
2479 I != E;
2480 I++)
2481 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002482 delete I->second;
2483 mEmittedFunctions.clear();
2484
2485 mpMemMgr->reset();
2486
2487 return;
2488 }
2489
Zonr Chang932648d2010-10-13 22:23:56 +08002490 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002491 return lookup( llvm::StringRef(Name) );
2492 }
2493
Zonr Chang932648d2010-10-13 22:23:56 +08002494 void *lookup(const llvm::StringRef &Name) {
2495 EmittedFunctionsMapTy::const_iterator I =
2496 mEmittedFunctions.find(Name.str());
2497 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002498 return NULL;
2499 else
2500 return I->second->Code;
2501 }
2502
Zonr Chang932648d2010-10-13 22:23:56 +08002503 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002504 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002505 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002506 int functionCount = mEmittedFunctions.size();
2507
Zonr Chang932648d2010-10-13 22:23:56 +08002508 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002509 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002510 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002511 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002512 if (functions)
2513 for (EmittedFunctionsMapTy::const_iterator
2514 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2515 (I != E) && (functionCount > 0);
2516 I++, functionCount--)
2517 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002518
2519 return;
2520 }
2521
Zonr Chang932648d2010-10-13 22:23:56 +08002522 void getFunctionBinary(BCCchar *label,
2523 BCCvoid **base,
2524 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002525 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002526 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002527 *base = NULL;
2528 *length = 0;
2529 } else {
2530 *base = I->second->Code;
2531 *length = I->second->Size;
2532 }
2533 return;
2534 }
2535
2536 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002537 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002538#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002539 delete mpAsmInfo;
2540 delete mpDisassmbler;
2541 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002542#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002543 return;
2544 }
Zonr Chang932648d2010-10-13 22:23:56 +08002545 };
2546 // End of Class CodeEmitter
2547 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002548
Zonr Chang932648d2010-10-13 22:23:56 +08002549 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002550 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002551 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002552 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2553 return mCodeEmitter.get();
2554 }
2555
2556 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002557 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002558
Zonr Chang932648d2010-10-13 22:23:56 +08002559 llvm::LLVMContext *mContext;
2560 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002561
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002562 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002563
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002564 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002565 Compiler()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002566 : mUseCache(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002567 mCacheNew(false),
2568 mCacheFd(-1),
2569 mCacheMapAddr(NULL),
2570 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002571 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002572 mCacheDiff(0),
2573 mCodeDataAddr(NULL),
2574 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002575 mpSymbolLookupContext(NULL),
2576 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002577 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002578 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002579 llvm::remove_fatal_error_handler();
2580 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002581 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002582 return;
2583 }
2584
Zonr Chang932648d2010-10-13 22:23:56 +08002585 // interface for BCCscript::registerSymbolCallback()
2586 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002587 mpSymbolLookupFn = pFn;
2588 mpSymbolLookupContext = pContext;
2589 return;
2590 }
2591
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002592 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002593 GlobalInitialization();
2594 mModule = module;
2595 return hasError();
2596 }
2597
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002598 int readBC(const char *bitcode,
Loganc0b9f652010-11-24 22:33:16 +08002599 size_t bitcodeSize,
2600 const BCCchar *resName) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002601 GlobalInitialization();
2602
Loganc0b9f652010-11-24 22:33:16 +08002603 if (resName) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002604 // Turn on mUseCache mode iff
2605 // 1. Has resName
2606 // and, assuming USE_RELOCATE is false:
2607 // 2. Later running code doesn't violate the following condition:
2608 // mCodeDataAddr (set in loadCacheFile()) ==
2609 // mCacheHdr->cachedCodeDataAddr
2610 //
2611 // BTW, this condition is achievable only when in the earlier
2612 // cache-generating run,
2613 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
2614 // which means the mmap'ed is in the reserved area,
2615 //
2616 // Note: Upon violation, mUseCache will be set back to false.
2617 mUseCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002618
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002619 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2620 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2621 return -mCacheFd;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002622 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002623 }
2624
2625 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002626
Zonr Chang932648d2010-10-13 22:23:56 +08002627 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002628 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002629
Zonr Chang932648d2010-10-13 22:23:56 +08002630 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002631 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002632 llvm::StringRef(bitcode, bitcodeSize)));
2633
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002634 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002635 setError("Error reading input program bitcode into memory");
2636 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002637 }
2638
Zonr Chang932648d2010-10-13 22:23:56 +08002639 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002640 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2641 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002642 return hasError();
2643 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002644
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002645 int linkBC(const char *bitcode, size_t bitcodeSize) {
2646 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002647
2648 if (bitcode == NULL || bitcodeSize <= 0)
2649 return 0;
2650
2651 if (mModule == NULL) {
2652 setError("No module presents for linking");
2653 return hasError();
2654 }
2655
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002656 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002657 llvm::StringRef(bitcode, bitcodeSize)));
2658
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002659 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002660 setError("Error reading input library bitcode into memory");
2661 return hasError();
2662 }
2663
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002664 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002665 *mContext,
2666 &mError));
2667 if (Lib.get() == NULL)
2668 return hasError();
2669
2670 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2671 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002672
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002673 // Everything for linking should be settled down here with no error occurs
2674 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002675 return hasError();
2676 }
2677
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002678 // interface for bccLoadBinary()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002679 int loadCacheFile() {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002680 // Check File Descriptor
2681 if (mCacheFd < 0) {
2682 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2683 goto giveup;
2684 }
2685
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002686 // Check File Size
2687 struct stat statCacheFd;
2688 if (fstat(mCacheFd, &statCacheFd) < 0) {
2689 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2690 goto giveup;
2691 }
2692
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002693 mCacheSize = statCacheFd.st_size;
2694
2695 if (mCacheSize < sizeof(oBCCHeader) ||
2696 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002697 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2698 goto giveup;
2699 }
2700
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002701 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2702 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2703 goto giveup;
2704 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002705
Loganc0b9f652010-11-24 22:33:16 +08002706 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002707 {
Loganc0b9f652010-11-24 22:33:16 +08002708 // Read cached file and perform quick integrity check
2709
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002710 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002711 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
Loganad7e8e12010-11-22 20:43:43 +08002712 (unsigned int)mCacheSize,
2713 (unsigned long long int)heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002714
2715 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002716 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002717 flock(mCacheFd, LOCK_UN);
2718 LOGE("allocation failed.\n");
2719 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002720 }
2721
2722 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2723 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002724 if (nread != (size_t)heuristicCodeOffset) {
2725 LOGE("read(mCacheFd) failed\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002726 goto bail;
2727 }
2728
2729 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002730 // Sanity check
2731 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2732 LOGE("assertion failed: heuristic code offset is not correct.\n");
2733 goto bail;
2734 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002735 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2736 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2737 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2738 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2739 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002740
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002741 // Verify the Cache File
2742 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2743 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002744 goto bail;
2745 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002746
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002747 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2748 LOGE("bad oBCC version 0x%08x\n",
2749 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2750 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002751 }
2752
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002753 if (mCacheSize < mCacheHdr->relocOffset +
2754 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2755 LOGE("relocate table overflow\n");
2756 goto bail;
2757 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002758
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002759 if (mCacheSize < mCacheHdr->exportVarsOffset +
2760 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2761 LOGE("export variables table overflow\n");
2762 goto bail;
2763 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002764
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002765 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2766 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2767 LOGE("export functions table overflow\n");
2768 goto bail;
2769 }
2770
2771 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2772 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2773 LOGE("export pragmas table overflow\n");
2774 goto bail;
2775 }
2776
2777 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2778 LOGE("code cache overflow\n");
2779 goto bail;
2780 }
2781
2782 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2783 LOGE("data (global variable) cache overflow\n");
2784 goto bail;
2785 }
Loganefd637b2010-11-25 01:21:03 +08002786
2787 long pagesize = sysconf(_SC_PAGESIZE);
2788 if (mCacheHdr->codeOffset % pagesize != 0) {
2789 LOGE("code offset must aligned to pagesize\n");
2790 goto bail;
2791 }
Loganc0b9f652010-11-24 22:33:16 +08002792 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002793
Loganc0b9f652010-11-24 22:33:16 +08002794 // Part 2. Deal with the codedata section
2795 {
Loganefd637b2010-11-25 01:21:03 +08002796 long pagesize = sysconf(_SC_PAGESIZE);
Loganc0b9f652010-11-24 22:33:16 +08002797
Loganefd637b2010-11-25 01:21:03 +08002798 if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
2799 void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002800
Loganefd637b2010-11-25 01:21:03 +08002801 // Try to mmap at cached address directly.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002802 mCodeDataAddr = (char *) mmap(addr,
2803 BCC_MMAP_IMG_SIZE,
Loganefd637b2010-11-25 01:21:03 +08002804 PROT_READ | PROT_EXEC | PROT_WRITE,
2805 MAP_PRIVATE | MAP_FIXED,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002806 mCacheFd,
2807 mCacheHdr->codeOffset);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002808
Loganefd637b2010-11-25 01:21:03 +08002809 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
2810 // Cheers! Mapped at the cached address successfully.
Loganc0b9f652010-11-24 22:33:16 +08002811
Logan2ad855d2010-11-25 19:53:06 +08002812 // Update the BccMmapImgAddrTaken table (if required)
Loganefd637b2010-11-25 01:21:03 +08002813 if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
2814 size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
2815
2816 if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
2817 (offset / BCC_MMAP_IMG_SIZE) < BCC_MMAP_IMG_COUNT) {
Loganefd637b2010-11-25 01:21:03 +08002818 Compiler::BccMmapImgAddrTaken[offset / BCC_MMAP_IMG_SIZE] = true;
2819 }
Loganc0b9f652010-11-24 22:33:16 +08002820 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002821
Logan2ad855d2010-11-25 19:53:06 +08002822#if 1
2823 // Check the checksum of code and data
2824 {
2825 uint32_t sum = mCacheHdr->checksum;
2826 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
2827
2828 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
2829 sum ^= *ptr++;
2830 }
2831
2832 if (sum != 0) {
2833 LOGE("Checksum check failed\n");
2834 goto bail;
2835 }
Logan9f6a10d2010-11-25 23:40:47 +08002836
2837 LOGE("Passed checksum even parity verification.\n");
Logan2ad855d2010-11-25 19:53:06 +08002838 }
2839#endif
2840
Loganefd637b2010-11-25 01:21:03 +08002841 flock(mCacheFd, LOCK_UN);
2842 return 0; // loadCacheFile succeed!
2843 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002844 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002845 }
2846
Loganc0b9f652010-11-24 22:33:16 +08002847#if !USE_RELOCATE
2848 // Note: Since this build does not support relocation, we have no
2849 // choose but give up to load the cached file, and recompile the
2850 // code.
2851
2852 flock(mCacheFd, LOCK_UN);
2853 goto bail;
2854#else
2855
2856 // Note: Currently, relocation code is not working. Give up now.
2857 flock(mCacheFd, LOCK_UN);
2858 goto bail;
2859
2860 // TODO(logan): Following code is not working. Don't use them.
2861 // And rewrite them asap.
2862#if 0
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002863 {
Loganc0b9f652010-11-24 22:33:16 +08002864 // Try to allocate at arbitary address. And perform relocation.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002865 mCacheMapAddr = (char *) mmap(0,
2866 mCacheSize,
Loganc0b9f652010-11-24 22:33:16 +08002867 PROT_READ | PROT_EXEC | PROT_WRITE,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002868 MAP_PRIVATE,
2869 mCacheFd,
2870 0);
Loganc0b9f652010-11-24 22:33:16 +08002871
2872 if (mCacheMapAddr == MAP_FAILED) {
2873 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2874 flock(mCacheFd, LOCK_UN);
2875 goto giveup;
2876 }
2877
2878 flock(mCacheFd, LOCK_UN);
2879 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2880
2881 // Relocate
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002882 mCacheDiff = mCodeDataAddr -
2883 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2884
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002885 if (mCacheDiff) { // To relocate
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002886 if (mCacheHdr->rootAddr) {
2887 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002888 }
2889
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002890 if (mCacheHdr->initAddr) {
2891 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002892 }
2893
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002894 oBCCRelocEntry *cachedRelocTable =
2895 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2896 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002897
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002898 std::vector<llvm::MachineRelocation> relocations;
2899
2900 // Read in the relocs
2901 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2902 oBCCRelocEntry *entry = &cachedRelocTable[i];
2903
2904 llvm::MachineRelocation reloc =
2905 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2906 (unsigned)entry->relocType, 0, 0);
2907
2908 reloc.setResultPointer(
2909 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2910
2911 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002912 }
2913
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002914 // Rewrite machine code using llvm::TargetJITInfo relocate
2915 {
2916 llvm::TargetMachine *TM = NULL;
2917 const llvm::Target *Target;
2918 std::string FeaturesStr;
2919
2920 // Create TargetMachine
2921 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2922 if (hasError())
2923 goto bail;
2924
2925 if (!CPU.empty() || !Features.empty()) {
2926 llvm::SubtargetFeatures F;
2927 F.setCPU(CPU);
2928 for (std::vector<std::string>::const_iterator I = Features.begin(),
2929 E = Features.end(); I != E; I++)
2930 F.AddFeature(*I);
2931 FeaturesStr = F.getString();
2932 }
2933
2934 TM = Target->createTargetMachine(Triple, FeaturesStr);
2935 if (TM == NULL) {
2936 setError("Failed to create target machine implementation for the"
2937 " specified triple '" + Triple + "'");
2938 goto bail;
2939 }
2940
2941 TM->getJITInfo()->relocate(mCodeDataAddr,
2942 &relocations[0], relocations.size(),
2943 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2944
2945 if (mCodeEmitter.get()) {
2946 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2947 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2948 2 * 1024 /*MaxCodeSize*/,
2949 false);
2950 }
2951
2952 delete TM;
2953 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002954 } // End of if (mCacheDiff)
Loganc0b9f652010-11-24 22:33:16 +08002955
2956 return 0; // Success!
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002957 }
Loganc0b9f652010-11-24 22:33:16 +08002958#endif
2959#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002960
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002961 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002962 if (mCacheMapAddr) {
2963 free(mCacheMapAddr);
2964 }
Loganad7e8e12010-11-22 20:43:43 +08002965
Loganc0b9f652010-11-24 22:33:16 +08002966 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +08002967 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
Loganc0b9f652010-11-24 22:33:16 +08002968 LOGE("munmap failed: %s\n", strerror(errno));
2969 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002970 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002971
Logan43830d52010-11-25 19:27:29 +08002972 mCacheMapAddr = NULL;
2973 mCacheHdr = NULL;
2974 mCodeDataAddr = NULL;
Logan82e67012010-11-25 00:29:34 +08002975
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002976 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002977 return 1;
2978 }
2979
2980 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002981 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002982 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002983
Zonr Chang932648d2010-10-13 22:23:56 +08002984 llvm::TargetMachine *TM = NULL;
2985 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002986 std::string FeaturesStr;
2987
Zonr Chang932648d2010-10-13 22:23:56 +08002988 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002989
Zonr Chang932648d2010-10-13 22:23:56 +08002990 const llvm::NamedMDNode *PragmaMetadata;
2991 const llvm::NamedMDNode *ExportVarMetadata;
2992 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002993
Zonr Chang932648d2010-10-13 22:23:56 +08002994 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002995 return 0;
2996
Zonr Chang932648d2010-10-13 22:23:56 +08002997 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002998 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002999 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003000 goto on_bcc_compile_error;
3001
Zonr Chang932648d2010-10-13 22:23:56 +08003002 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003003 llvm::SubtargetFeatures F;
3004 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08003005 for (std::vector<std::string>::const_iterator I = Features.begin(),
3006 E = Features.end();
3007 I != E;
3008 I++)
3009 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003010 FeaturesStr = F.getString();
3011 }
3012
3013 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08003014 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003015 setError("Failed to create target machine implementation for the"
3016 " specified triple '" + Triple + "'");
3017 goto on_bcc_compile_error;
3018 }
3019
Zonr Chang932648d2010-10-13 22:23:56 +08003020 // Create memory manager for creation of code emitter later.
3021 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003022 setError("Failed to startup memory management for further compilation");
3023 goto on_bcc_compile_error;
3024 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003025 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003026
Zonr Chang932648d2010-10-13 22:23:56 +08003027 // Create code emitter
3028 if (!mCodeEmitter.get()) {
3029 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003030 setError("Failed to create machine code emitter to complete"
3031 " the compilation");
3032 goto on_bcc_compile_error;
3033 }
3034 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08003035 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003036 mCodeEmitter->reset();
3037 }
3038
3039 mCodeEmitter->setTargetMachine(*TM);
3040 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
3041 mpSymbolLookupContext);
3042
Zonr Chang932648d2010-10-13 22:23:56 +08003043 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003044 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003045
Zonr Chang5d35b972010-10-23 14:36:47 +08003046 // Load named metadata
3047 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
3048 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
3049 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
3050
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003051 // Create LTO passes and run them on the mModule
3052 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003053 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003054 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08003055 LTOPasses.add(new llvm::TargetData(*TD));
3056
3057 std::vector<const char*> ExportSymbols;
3058
3059 // A workaround for getting export variable and function name. Will refine
3060 // it soon.
3061 if (ExportVarMetadata) {
3062 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3063 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3064 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3065 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3066 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
3067 llvm::StringRef ExportVarName =
3068 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
3069 ExportSymbols.push_back(ExportVarName.data());
3070 }
3071 }
3072 }
3073 }
3074
3075 if (ExportFuncMetadata) {
3076 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3077 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3078 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3079 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3080 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
3081 llvm::StringRef ExportFuncName =
3082 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3083 ExportSymbols.push_back(ExportFuncName.data());
3084 }
3085 }
3086 }
3087 }
3088 // root() and init() are born to be exported
3089 ExportSymbols.push_back("root");
3090 ExportSymbols.push_back("init");
3091
Zonr Change5c7a542010-10-24 01:07:27 +08003092 // We now create passes list performing LTO. These are copied from
3093 // (including comments) llvm::createStandardLTOPasses().
3094
3095 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08003096 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003097
Zonr Change5c7a542010-10-24 01:07:27 +08003098 // Propagate constants at call sites into the functions they call. This
3099 // opens opportunities for globalopt (and inlining) by substituting
3100 // function pointers passed as arguments to direct uses of functions.
3101 LTOPasses.add(llvm::createIPSCCPPass());
3102
3103 // Now that we internalized some globals, see if we can hack on them!
3104 LTOPasses.add(llvm::createGlobalOptimizerPass());
3105
3106 // Linking modules together can lead to duplicated global constants, only
3107 // keep one copy of each constant...
3108 LTOPasses.add(llvm::createConstantMergePass());
3109
3110 // Remove unused arguments from functions...
3111 LTOPasses.add(llvm::createDeadArgEliminationPass());
3112
3113 // Reduce the code after globalopt and ipsccp. Both can open up
3114 // significant simplification opportunities, and both can propagate
3115 // functions through function pointers. When this happens, we often have
3116 // to resolve varargs calls, etc, so let instcombine do this.
3117 LTOPasses.add(llvm::createInstructionCombiningPass());
3118
3119 // Inline small functions
3120 LTOPasses.add(llvm::createFunctionInliningPass());
3121
3122 // Remove dead EH info.
3123 LTOPasses.add(llvm::createPruneEHPass());
3124
3125 // Internalize the globals again after inlining
3126 LTOPasses.add(llvm::createGlobalOptimizerPass());
3127
3128 // Remove dead functions.
3129 LTOPasses.add(llvm::createGlobalDCEPass());
3130
3131 // If we didn't decide to inline a function, check to see if we can
3132 // transform it to pass arguments by value instead of by reference.
3133 LTOPasses.add(llvm::createArgumentPromotionPass());
3134
3135 // The IPO passes may leave cruft around. Clean up after them.
3136 LTOPasses.add(llvm::createInstructionCombiningPass());
3137 LTOPasses.add(llvm::createJumpThreadingPass());
3138
3139 // Break up allocas
3140 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3141
3142 // Run a few AA driven optimizations here and now, to cleanup the code.
3143 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3144 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3145
3146 // Hoist loop invariants.
3147 LTOPasses.add(llvm::createLICMPass());
3148
3149 // Remove redundancies.
3150 LTOPasses.add(llvm::createGVNPass());
3151
3152 // Remove dead memcpys.
3153 LTOPasses.add(llvm::createMemCpyOptPass());
3154
3155 // Nuke dead stores.
3156 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3157
3158 // Cleanup and simplify the code after the scalar optimizations.
3159 LTOPasses.add(llvm::createInstructionCombiningPass());
3160
3161 LTOPasses.add(llvm::createJumpThreadingPass());
3162
3163 // Delete basic blocks, which optimization passes may have killed.
3164 LTOPasses.add(llvm::createCFGSimplificationPass());
3165
3166 // Now that we have optimized the program, discard unreachable functions.
3167 LTOPasses.add(llvm::createGlobalDCEPass());
3168
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003169 LTOPasses.run(*mModule);
3170 }
3171
Zonr Chang932648d2010-10-13 22:23:56 +08003172 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003173 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003174 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003175
Zonr Chang932648d2010-10-13 22:23:56 +08003176 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3177 *mCodeEmitter,
3178 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003179 setError("The machine code emission is not supported by BCC on target '"
3180 + Triple + "'");
3181 goto on_bcc_compile_error;
3182 }
3183
Zonr Chang932648d2010-10-13 22:23:56 +08003184 // Run the pass (the code emitter) on every non-declaration function in the
3185 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003186 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003187 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3188 I != E;
3189 I++)
3190 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003191 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003192
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003193 CodeGenPasses->doFinalization();
3194
Zonr Chang932648d2010-10-13 22:23:56 +08003195 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003196 if (ExportVarMetadata) {
3197 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3198 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3199 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3200 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3201 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003202 llvm::StringRef ExportVarName =
3203 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003204 CodeEmitter::global_addresses_const_iterator I, E;
3205 for (I = mCodeEmitter->global_address_begin(),
3206 E = mCodeEmitter->global_address_end();
3207 I != E;
3208 I++) {
3209 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003210 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003211 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003212 mExportVars.push_back(I->second);
3213 break;
3214 }
3215 }
Zonr Chang932648d2010-10-13 22:23:56 +08003216 if (I != mCodeEmitter->global_address_end())
3217 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003218 }
3219 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003220 // if reaching here, we know the global variable record in metadata is
3221 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003222 mExportVars.push_back(NULL);
3223 }
3224 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3225 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003226 }
3227
Zonr Chang932648d2010-10-13 22:23:56 +08003228 if (ExportFuncMetadata) {
3229 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3230 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3231 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3232 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3233 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003234 llvm::StringRef ExportFuncName =
3235 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3236 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3237 }
3238 }
3239 }
3240 }
3241
Zonr Chang932648d2010-10-13 22:23:56 +08003242 // Tell code emitter now can release the memory using during the JIT since
3243 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003244 mCodeEmitter->releaseUnnecessary();
3245
Zonr Chang932648d2010-10-13 22:23:56 +08003246 // Finally, read pragma information from the metadata node of the @Module if
3247 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003248 if (PragmaMetadata)
3249 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3250 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3251 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003252 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003253 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3254 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003255
Zonr Chang932648d2010-10-13 22:23:56 +08003256 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003257 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3258 llvm::StringRef PragmaName =
3259 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3260 llvm::StringRef PragmaValue =
3261 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3262
Zonr Chang932648d2010-10-13 22:23:56 +08003263 mPragmas.push_back(
3264 std::make_pair(std::string(PragmaName.data(),
3265 PragmaName.size()),
3266 std::string(PragmaValue.data(),
3267 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003268 }
3269 }
3270 }
3271
3272 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003273 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003274 if (CodeGenPasses) {
3275 delete CodeGenPasses;
3276 } else if (TD) {
3277 delete TD;
3278 }
3279 if (TM)
3280 delete TM;
3281
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003282 if (mError.empty()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003283 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003284 genCacheFile();
3285 flock(mCacheFd, LOCK_UN);
3286 }
Loganc0b9f652010-11-24 22:33:16 +08003287
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003288 return false;
3289 }
3290
Zonr Chang932648d2010-10-13 22:23:56 +08003291 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003292 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003293 }
3294
Zonr Chang932648d2010-10-13 22:23:56 +08003295 // interface for bccGetScriptInfoLog()
3296 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003297 return const_cast<char*>(mError.c_str());
3298 }
3299
Zonr Chang932648d2010-10-13 22:23:56 +08003300 // interface for bccGetScriptLabel()
3301 void *lookup(const char *name) {
3302 void *addr = NULL;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003303 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003304 if (!strcmp(name, "root")) {
3305 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3306 } else if (!strcmp(name, "init")) {
3307 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3308 }
3309 return addr;
3310 }
3311
Zonr Chang932648d2010-10-13 22:23:56 +08003312 if (mCodeEmitter.get())
3313 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003314 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003315 return addr;
3316 }
3317
Zonr Chang932648d2010-10-13 22:23:56 +08003318 // Interface for bccGetExportVars()
3319 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003320 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003321 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003322 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003323
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003324 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003325 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3326 if (actualVarCount)
3327 *actualVarCount = varCount;
3328 if (varCount > maxVarCount)
3329 varCount = maxVarCount;
3330 if (vars) {
3331 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3332 mCacheHdr->exportVarsOffset);
3333
3334 for (int i = 0; i < varCount; i++) {
3335 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3336 mCacheDiff);
3337 cachedVars++;
3338 }
3339 }
3340 return;
3341 }
3342
3343 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003344 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003345 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003346 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003347 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003348 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003349 for (ExportVarList::const_iterator I = mExportVars.begin(),
3350 E = mExportVars.end();
3351 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003352 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003353 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003354 }
3355 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003356
3357 return;
3358 }
3359
Zonr Chang932648d2010-10-13 22:23:56 +08003360 // Interface for bccGetExportFuncs()
3361 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003362 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003363 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003364 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003365
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003366 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003367 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3368 if (actualFuncCount)
3369 *actualFuncCount = funcCount;
3370 if (funcCount > maxFuncCount)
3371 funcCount = maxFuncCount;
3372 if (funcs) {
3373 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3374 mCacheHdr->exportFuncsOffset);
3375
3376 for (int i = 0; i < funcCount; i++) {
3377 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3378 mCacheDiff);
3379 cachedFuncs++;
3380 }
3381 }
3382 return;
3383 }
3384
3385 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003386 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003387 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003388 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003389 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003390 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003391 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3392 E = mExportFuncs.end();
3393 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003394 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003395 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003396 }
3397 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003398
3399 return;
3400 }
3401
Zonr Chang932648d2010-10-13 22:23:56 +08003402 // Interface for bccGetPragmas()
3403 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003404 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003405 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003406 int stringCount;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003407 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003408 if (actualStringCount)
3409 *actualStringCount = 0; // XXX
3410 return;
3411 }
3412
3413 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003414
Zonr Chang932648d2010-10-13 22:23:56 +08003415 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003416 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003417 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003418 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003419 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003420 for (PragmaList::const_iterator it = mPragmas.begin();
3421 stringCount > 0;
3422 stringCount -= 2, it++) {
3423 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3424 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003425 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003426 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003427
3428 return;
3429 }
3430
Zonr Chang932648d2010-10-13 22:23:56 +08003431 // Interface for bccGetFunctions()
3432 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003433 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003434 BCCchar **functions) {
3435 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003436 mCodeEmitter->getFunctionNames(actualFunctionCount,
3437 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003438 functions);
3439 else
3440 *actualFunctionCount = 0;
3441
3442 return;
3443 }
3444
Zonr Chang932648d2010-10-13 22:23:56 +08003445 // Interface for bccGetFunctionBinary()
3446 void getFunctionBinary(BCCchar *function,
3447 BCCvoid **base,
3448 BCCsizei *length) {
3449 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003450 mCodeEmitter->getFunctionBinary(function, base, length);
3451 } else {
3452 *base = NULL;
3453 *length = 0;
3454 }
3455 return;
3456 }
3457
Zonr Chang932648d2010-10-13 22:23:56 +08003458 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003459 return mModule;
3460 }
3461
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003462 ~Compiler() {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003463 if (!mCodeMemMgr.get()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003464 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003465 // managed by CodeMemoryManager.
3466
3467 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +08003468 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003469 LOGE("munmap failed while releasing mCodeDataAddr\n");
3470 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003471 }
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003472
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003473 if (mCacheMapAddr) {
3474 free(mCacheMapAddr);
3475 }
Logan82e67012010-11-25 00:29:34 +08003476
3477 mCodeDataAddr = 0;
3478 mCacheMapAddr = 0;
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003479 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003480
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003481 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003482 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003483 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003484 return;
3485 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003486
3487 private:
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003488 // Note: loadCacheFile() and genCacheFile() go hand in hand
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003489 void genCacheFile() {
3490 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3491 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3492 return;
3493 }
3494
3495 bool codeOffsetNeedPadding = false;
3496
3497 uint32_t offset = sizeof(oBCCHeader);
3498
3499 // BCC Cache File Header
3500 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3501
3502 if (!hdr) {
3503 LOGE("Unable to allocate oBCCHeader.\n");
3504 return;
3505 }
3506
3507 // Magic Words
3508 memcpy(hdr->magic, OBCC_MAGIC, 4);
3509 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3510
3511 // Timestamp
3512 hdr->sourceWhen = 0; // TODO(all)
3513 hdr->rslibWhen = 0; // TODO(all)
3514 hdr->libRSWhen = 0; // TODO(all)
3515 hdr->libbccWhen = 0; // TODO(all)
3516
3517 // Current Memory Address (Saved for Recalculation)
3518 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3519 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3520 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3521
3522 // Relocation Table Offset and Entry Count
3523 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003524 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003525
Logan824dd0a2010-11-20 01:45:54 +08003526 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003527
3528 // Export Variable Table Offset and Entry Count
3529 hdr->exportVarsOffset = offset;
3530 hdr->exportVarsCount = mExportVars.size();
3531
3532 offset += hdr->exportVarsCount * sizeof(uint32_t);
3533
3534 // Export Function Table Offset and Entry Count
3535 hdr->exportFuncsOffset = offset;
3536 hdr->exportFuncsCount = mExportFuncs.size();
3537
3538 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3539
3540 // Export Pragmas Table Offset and Entry Count
3541 hdr->exportPragmasOffset = offset;
3542 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3543
3544 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3545
3546 // Code Offset and Size
3547
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003548 //#ifdef BCC_CODE_ADDR
3549 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003550 long pagesize = sysconf(_SC_PAGESIZE);
3551
3552 if (offset % pagesize > 0) {
3553 codeOffsetNeedPadding = true;
3554 offset += pagesize - (offset % pagesize);
3555 }
3556 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003557 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003558 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3559 codeOffsetNeedPadding = true;
3560 offset += 0x08 - (offset & 0x07);
3561 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003562 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003563
3564 hdr->codeOffset = offset;
3565 hdr->codeSize = MaxCodeSize;
3566
3567 offset += hdr->codeSize;
3568
3569 // Data (Global Variable) Offset and Size
3570 hdr->dataOffset = offset;
3571 hdr->dataSize = MaxGlobalVarSize;
3572
3573 offset += hdr->dataSize;
3574
3575 // Checksum
Logan2ad855d2010-11-25 19:53:06 +08003576#if 1
3577 {
3578 // Note: This is an simple checksum implementation that are using xor
3579 // to calculate even parity (for code and data only).
3580
3581 uint32_t sum = 0;
3582 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
3583
3584 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
3585 sum ^= *ptr++;
3586 }
3587
3588 hdr->checksum = sum;
3589 }
3590#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003591 hdr->checksum = 0; // Set Field checksum. TODO(all)
Logan2ad855d2010-11-25 19:53:06 +08003592#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003593
3594 // Write Header
3595 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3596 sizeof(oBCCHeader), "Write oBCC header");
3597
Logan824dd0a2010-11-20 01:45:54 +08003598 // Write Relocation Entry Table
3599 {
3600 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003601
Logan824dd0a2010-11-20 01:45:54 +08003602 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3603
3604 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3605 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003606 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003607
3608 // Write Export Variables Table
3609 {
3610 uint32_t *record, *ptr;
3611
3612 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3613 ptr = record;
3614
3615 if (!record) {
3616 goto bail;
3617 }
3618
3619 for (ExportVarList::const_iterator I = mExportVars.begin(),
3620 E = mExportVars.end(); I != E; I++) {
3621 *ptr++ = reinterpret_cast<uint32_t>(*I);
3622 }
3623
3624 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3625 hdr->exportVarsCount * sizeof(uint32_t),
3626 "Write ExportVars");
3627
3628 free(record);
3629 }
3630
3631 // Write Export Functions Table
3632 {
3633 uint32_t *record, *ptr;
3634
3635 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3636 ptr = record;
3637
3638 if (!record) {
3639 goto bail;
3640 }
3641
3642 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3643 E = mExportFuncs.end(); I != E; I++) {
3644 *ptr++ = reinterpret_cast<uint32_t>(*I);
3645 }
3646
3647 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3648 hdr->exportFuncsCount * sizeof(uint32_t),
3649 "Write ExportFuncs");
3650
3651 free(record);
3652 }
3653
3654
3655 // TODO(all): Write Export Pragmas Table
3656#if 0
3657#else
3658 // Note: As long as we have comment out export pragmas table code,
3659 // we have to seek the position to correct offset.
3660
3661 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3662#endif
3663
3664 if (codeOffsetNeedPadding) {
3665 // requires additional padding
3666 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3667 }
3668
3669 // Write Generated Code and Global Variable
3670 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3671 "Write code and global variable");
3672
3673 goto close_return;
3674
3675 bail:
3676 if (ftruncate(mCacheFd, 0) != 0) {
3677 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3678 }
3679
3680 close_return:
3681 free(hdr);
3682 close(mCacheFd);
3683 mCacheFd = -1;
3684 return;
3685 }
3686
3687 // OpenCacheFile() returns fd of the cache file.
3688 // Input:
3689 // BCCchar *resName: Used to genCacheFileName()
3690 // bool createIfMissing: If false, turn off caching
3691 // Output:
3692 // returns fd: If -1: Failed
3693 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3694 // cache file's file descriptor
3695 // Note: openCacheFile() will check the cache file's validity,
3696 // such as Magic number, sourceWhen... dependencies.
3697 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3698 int fd, cc;
3699 struct stat fdStat, fileStat;
3700 bool readOnly = false;
3701
3702 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3703
3704 mCacheNew = false;
3705
3706 retry:
3707 /*
3708 * Try to open the cache file. If we've been asked to,
3709 * create it if it doesn't exist.
3710 */
3711 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3712 if (fd < 0) {
3713 fd = open(cacheFileName, O_RDONLY, 0);
3714 if (fd < 0) {
3715 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08003716 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003717 cacheFileName, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003718 mUseCache = false;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003719 }
3720 return fd;
3721 }
3722 readOnly = true;
3723 }
3724
3725 /*
3726 * Grab an exclusive lock on the cache file. If somebody else is
3727 * working on it, we'll block here until they complete.
3728 */
3729 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3730 cacheFileName, fd);
3731
3732 cc = flock(fd, LOCK_EX | LOCK_NB);
3733 if (cc != 0) {
3734 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3735 cc = flock(fd, LOCK_EX);
3736 }
3737
3738 if (cc != 0) {
3739 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3740 close(fd);
3741 return -1;
3742 }
3743 LOGV("bcc: locked cache file\n");
3744
3745 /*
3746 * Check to see if the fd we opened and locked matches the file in
3747 * the filesystem. If they don't, then somebody else unlinked ours
3748 * and created a new file, and we need to use that one instead. (If
3749 * we caught them between the unlink and the create, we'll get an
3750 * ENOENT from the file stat.)
3751 */
3752 cc = fstat(fd, &fdStat);
3753 if (cc != 0) {
3754 LOGE("Can't stat open file '%s'\n", cacheFileName);
3755 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3756 goto close_fail;
3757 }
3758 cc = stat(cacheFileName, &fileStat);
3759 if (cc != 0 ||
3760 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3761 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3762 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3763 flock(fd, LOCK_UN);
3764 close(fd);
3765 usleep(250 * 1000); // if something is hosed, don't peg machine
3766 goto retry;
3767 }
3768
3769 /*
3770 * We have the correct file open and locked. If the file size is zero,
3771 * then it was just created by us, and we want to fill in some fields
3772 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3773 * verify that the fields in the header match our expectations, and
3774 * reset the file if they don't.
3775 */
3776 if (fdStat.st_size == 0) {
3777 if (readOnly) { // The device is readOnly --> close_fail
3778 LOGW("bcc: file has zero length and isn't writable\n");
3779 goto close_fail;
3780 }
3781 /*cc = createEmptyHeader(fd);
3782 if (cc != 0)
3783 goto close_fail;
3784 */
3785 mCacheNew = true;
3786 LOGV("bcc: successfully initialized new cache file\n");
3787 } else {
3788 // Calculate sourceWhen
3789 // XXX
3790 uint32_t sourceWhen = 0;
3791 uint32_t rslibWhen = 0;
3792 uint32_t libRSWhen = 0;
3793 uint32_t libbccWhen = 0;
3794 if (!checkHeaderAndDependencies(fd,
3795 sourceWhen,
3796 rslibWhen,
3797 libRSWhen,
3798 libbccWhen)) {
3799 // If checkHeaderAndDependencies returns 0: FAILED
3800 // Will truncate the file and retry to createIfMissing the file
3801
3802 if (readOnly) { // Shouldn't be readonly.
3803 /*
3804 * We could unlink and rewrite the file if we own it or
3805 * the "sticky" bit isn't set on the directory. However,
3806 * we're not able to truncate it, which spoils things. So,
3807 * give up now.
3808 */
3809 if (createIfMissing) {
3810 LOGW("Cached file %s is stale and not writable\n",
3811 cacheFileName);
3812 }
3813 goto close_fail;
3814 }
3815
3816 /*
3817 * If we truncate the existing file before unlinking it, any
3818 * process that has it mapped will fail when it tries to touch
3819 * the pages? Probably OK because we use MAP_PRIVATE.
3820 */
3821 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3822 cacheFileName);
3823 if (ftruncate(fd, 0) != 0) {
3824 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3825 cacheFileName, strerror(errno));
3826 /* keep going */
3827 }
3828 if (unlink(cacheFileName) != 0) {
3829 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3830 cacheFileName, errno, strerror(errno));
3831 /* keep going; permission failure should probably be fatal */
3832 }
3833 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3834 flock(fd, LOCK_UN);
3835 close(fd);
3836 goto retry;
3837 } else {
3838 // Got cacheFile! Good to go.
3839 LOGV("Good cache file\n");
3840 }
3841 }
3842
3843 assert(fd >= 0);
3844 return fd;
3845
3846 close_fail:
3847 flock(fd, LOCK_UN);
3848 close(fd);
3849 return -1;
3850 } // End of openCacheFile()
3851
3852 char *genCacheFileName(const char *fileName, const char *subFileName) {
3853 char nameBuf[512];
3854 static const char kCachePath[] = "bcc-cache";
3855 char absoluteFile[sizeof(nameBuf)];
3856 const size_t kBufLen = sizeof(nameBuf) - 1;
3857 const char *dataRoot;
3858 char *cp;
3859
3860 // Get the absolute path of the raw/***.bc file.
3861 absoluteFile[0] = '\0';
3862 if (fileName[0] != '/') {
3863 /*
3864 * Generate the absolute path. This doesn't do everything it
3865 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3866 * the leading "./" out, but it'll do.
3867 */
3868 if (getcwd(absoluteFile, kBufLen) == NULL) {
3869 LOGE("Can't get CWD while opening raw/***.bc file\n");
3870 return NULL;
3871 }
3872 // TODO(srhines): strncat() is a bit dangerous
3873 strncat(absoluteFile, "/", kBufLen);
3874 }
3875 strncat(absoluteFile, fileName, kBufLen);
3876
3877 if (subFileName != NULL) {
3878 strncat(absoluteFile, "/", kBufLen);
3879 strncat(absoluteFile, subFileName, kBufLen);
3880 }
3881
3882 /* Turn the path into a flat filename by replacing
3883 * any slashes after the first one with '@' characters.
3884 */
3885 cp = absoluteFile + 1;
3886 while (*cp != '\0') {
3887 if (*cp == '/') {
3888 *cp = '@';
3889 }
3890 cp++;
3891 }
3892
3893 /* Build the name of the cache directory.
3894 */
3895 dataRoot = getenv("ANDROID_DATA");
3896 if (dataRoot == NULL)
3897 dataRoot = "/data";
3898 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3899
3900 /* Tack on the file name for the actual cache file path.
3901 */
3902 strncat(nameBuf, absoluteFile, kBufLen);
3903
3904 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3905 return strdup(nameBuf);
3906 }
3907
3908 /*
3909 * Read the oBCC header, verify it, then read the dependent section
3910 * and verify that data as well.
3911 *
3912 * On successful return, the file will be seeked immediately past the
3913 * oBCC header.
3914 */
3915 bool checkHeaderAndDependencies(int fd,
3916 uint32_t sourceWhen,
3917 uint32_t rslibWhen,
3918 uint32_t libRSWhen,
3919 uint32_t libbccWhen) {
3920 ssize_t actual;
3921 oBCCHeader optHdr;
3922 uint32_t val;
3923 uint8_t const *magic, *magicVer;
3924
3925 /*
3926 * Start at the start. The "bcc" header, when present, will always be
3927 * the first thing in the file.
3928 */
3929 if (lseek(fd, 0, SEEK_SET) != 0) {
3930 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3931 goto bail;
3932 }
3933
3934 /*
3935 * Read and do trivial verification on the bcc header. The header is
3936 * always in host byte order.
3937 */
3938 actual = read(fd, &optHdr, sizeof(optHdr));
3939 if (actual < 0) {
3940 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3941 goto bail;
3942 } else if (actual != sizeof(optHdr)) {
3943 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3944 (int) actual, sizeof(optHdr));
3945 goto bail;
3946 }
3947
3948 magic = optHdr.magic;
3949 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3950 /* not an oBCC file, or previous attempt was interrupted */
3951 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3952 magic[0], magic[1], magic[2], magic[3]);
3953 goto bail;
3954 }
3955
3956 magicVer = optHdr.magicVersion;
3957 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3958 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3959 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3960 goto bail;
3961 }
3962
3963 /*
3964 * Do the header flags match up with what we want?
3965 *
3966 * This is useful because it allows us to automatically regenerate
3967 * a file when settings change (e.g. verification is now mandatory),
3968 * but can cause difficulties if the thing we depend upon
3969 * were handled differently than the current options specify.
3970 *
3971 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3972 * by limiting the match mask.
3973 *
3974 * The only thing we really can't handle is incorrect byte-ordering.
3975 */
3976
3977 val = optHdr.sourceWhen;
3978 if (val && (val != sourceWhen)) {
3979 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3980 val, sourceWhen);
3981 goto bail;
3982 }
3983 val = optHdr.rslibWhen;
3984 if (val && (val != rslibWhen)) {
3985 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3986 val, rslibWhen);
3987 goto bail;
3988 }
3989 val = optHdr.libRSWhen;
3990 if (val && (val != libRSWhen)) {
3991 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3992 val, libRSWhen);
3993 goto bail;
3994 }
3995 val = optHdr.libbccWhen;
3996 if (val && (val != libbccWhen)) {
3997 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3998 val, libbccWhen);
3999 goto bail;
4000 }
4001
4002 return true;
4003
4004 bail:
4005 return false;
4006 }
4007
Zonr Chang932648d2010-10-13 22:23:56 +08004008};
4009// End of Class Compiler
4010////////////////////////////////////////////////////////////////////////////////
4011
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004012
4013bool Compiler::GlobalInitialized = false;
4014
Loganc0b9f652010-11-24 22:33:16 +08004015bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Loganad7e8e12010-11-22 20:43:43 +08004016
Zonr Chang932648d2010-10-13 22:23:56 +08004017// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004018llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
4019
4020std::string Compiler::Triple;
4021
4022std::string Compiler::CPU;
4023
4024std::vector<std::string> Compiler::Features;
4025
Zonr Chang932648d2010-10-13 22:23:56 +08004026// The named of metadata node that pragma resides (should be synced with
4027// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004028const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
4029
Zonr Chang932648d2010-10-13 22:23:56 +08004030// The named of metadata node that export variable name resides (should be
4031// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004032const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
4033
Zonr Chang932648d2010-10-13 22:23:56 +08004034// The named of metadata node that export function name resides (should be
4035// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004036const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
4037
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004038struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08004039 //////////////////////////////////////////////////////////////////////////////
4040 // Part I. Compiler
4041 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004042 Compiler compiler;
4043
Zonr Chang932648d2010-10-13 22:23:56 +08004044 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004045 compiler.registerSymbolCallback(pFn, pContext);
4046 }
4047
Zonr Chang932648d2010-10-13 22:23:56 +08004048 //////////////////////////////////////////////////////////////////////////////
4049 // Part II. Logistics & Error handling
4050 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004051 BCCscript() {
4052 bccError = BCC_NO_ERROR;
4053 }
4054
4055 ~BCCscript() {
4056 }
4057
4058 void setError(BCCenum error) {
4059 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
4060 bccError = error;
4061 }
4062 }
4063
4064 BCCenum getError() {
4065 BCCenum result = bccError;
4066 bccError = BCC_NO_ERROR;
4067 return result;
4068 }
4069
4070 BCCenum bccError;
4071};
4072
4073
4074extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004075BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004076 return new BCCscript();
4077}
4078
4079extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004080BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004081 return script->getError();
4082}
4083
4084extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004085void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004086 delete script;
4087}
4088
4089extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004090void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004091 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08004092 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004093 script->registerSymbolCallback(pFn, pContext);
4094}
4095
4096extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004097int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08004098 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004099 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08004100}
4101
4102extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004103int bccReadBC(BCCscript *script,
4104 const BCCchar *bitcode,
4105 BCCint size,
4106 const BCCchar *resName) {
4107 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004108}
4109
4110extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004111void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08004112 const BCCchar *bitcode,
4113 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004114 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08004115}
4116
4117extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004118void bccLoadBinary(BCCscript *script) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08004119 int result = script->compiler.loadCacheFile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004120 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004121 script->setError(BCC_INVALID_OPERATION);
4122}
4123
4124extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004125void bccCompileBC(BCCscript *script) {
4126 {
4127#if defined(__arm__)
4128 android::StopWatch compileTimer("RenderScript compile time");
4129#endif
4130 int result = script->compiler.compile();
4131 if (result)
4132 script->setError(BCC_INVALID_OPERATION);
4133 }
4134}
4135
4136extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004137void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004138 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08004139 BCCsizei *length,
4140 BCCchar *infoLog) {
4141 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004142 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004143 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004144 *length = messageLength;
4145
4146 if (infoLog && maxLength > 0) {
4147 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4148 memcpy(infoLog, message, trimmedLength);
4149 infoLog[trimmedLength] = 0;
4150 }
4151}
4152
4153extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004154void bccGetScriptLabel(BCCscript *script,
4155 const BCCchar *name,
4156 BCCvoid **address) {
4157 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004158 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004159 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004160 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004161 script->setError(BCC_INVALID_VALUE);
4162}
4163
4164extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004165void bccGetExportVars(BCCscript *script,
4166 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004167 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004168 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004169 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4170}
4171
4172extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004173void bccGetExportFuncs(BCCscript *script,
4174 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004175 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004176 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004177 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4178}
4179
4180extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004181void bccGetPragmas(BCCscript *script,
4182 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004183 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004184 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004185 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4186}
4187
4188extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004189void bccGetFunctions(BCCscript *script,
4190 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004191 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004192 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004193 script->compiler.getFunctions(actualFunctionCount,
4194 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004195 functions);
4196}
4197
4198extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004199void bccGetFunctionBinary(BCCscript *script,
4200 BCCchar *function,
4201 BCCvoid **base,
4202 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004203 script->compiler.getFunctionBinary(function, base, length);
4204}
4205
4206struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004207 const Compiler *compiler;
4208 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004209};
4210
Zonr Chang932648d2010-10-13 22:23:56 +08004211} // namespace bcc