blob: c2c1037f6e0a200abdaace68eebb5575c5e6fb0b [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)
Zonr Chang932648d2010-10-13 22:23:56 +0800168# include "llvm/MC/MCInst.h"
169# include "llvm/MC/MCAsmInfo.h"
170# include "llvm/MC/MCInstPrinter.h"
171# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700172// If you want the disassemble results written to file, define this:
173# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700174#endif
175
176#include <set>
177#include <map>
178#include <list>
179#include <cmath>
180#include <string>
181#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800182#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700183
Zonr Chang932648d2010-10-13 22:23:56 +0800184// VMCore
185#include "llvm/Use.h"
186#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800187#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800188#include "llvm/Module.h"
189#include "llvm/Function.h"
190#include "llvm/Constant.h"
191#include "llvm/Constants.h"
192#include "llvm/Instruction.h"
193#include "llvm/PassManager.h"
194#include "llvm/LLVMContext.h"
195#include "llvm/GlobalValue.h"
196#include "llvm/Instructions.h"
197#include "llvm/OperandTraits.h"
198#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700199
200// System
Zonr Chang932648d2010-10-13 22:23:56 +0800201#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700202
203// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800204#include "llvm/ADT/APInt.h"
205#include "llvm/ADT/APFloat.h"
206#include "llvm/ADT/DenseMap.h"
207#include "llvm/ADT/ValueMap.h"
208#include "llvm/ADT/StringMap.h"
209#include "llvm/ADT/OwningPtr.h"
210#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700211
212// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800213#include "llvm/Target/TargetData.h"
214#include "llvm/Target/TargetSelect.h"
215#include "llvm/Target/TargetOptions.h"
216#include "llvm/Target/TargetMachine.h"
217#include "llvm/Target/TargetJITInfo.h"
218#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700219#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700220
221// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800222#include "llvm/Support/Casting.h"
223#include "llvm/Support/raw_ostream.h"
224#include "llvm/Support/ValueHandle.h"
225#include "llvm/Support/MemoryBuffer.h"
226#include "llvm/Support/MemoryObject.h"
227#include "llvm/Support/ManagedStatic.h"
228#include "llvm/Support/ErrorHandling.h"
229#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700230#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700231
232// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800233#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700234
235// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800236#include "llvm/CodeGen/Passes.h"
237#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700238#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700239#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700240#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700241#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700242#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700243#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700244#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700245#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700246
247// ExecutionEngine
248#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700249#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700250
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700251extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700252
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800253// For caching
254struct oBCCHeader {
255 uint8_t magic[4]; // includes version number
256 uint8_t magicVersion[4];
257
258 uint32_t sourceWhen;
259 uint32_t rslibWhen;
260 uint32_t libRSWhen;
261 uint32_t libbccWhen;
262
263 uint32_t cachedCodeDataAddr;
264 uint32_t rootAddr;
265 uint32_t initAddr;
266
267 uint32_t relocOffset; // offset of reloc table.
268 uint32_t relocCount;
269 uint32_t exportVarsOffset; // offset of export var table
270 uint32_t exportVarsCount;
271 uint32_t exportFuncsOffset; // offset of export func table
272 uint32_t exportFuncsCount;
273 uint32_t exportPragmasOffset; // offset of export pragma table
274 uint32_t exportPragmasCount;
275
276 uint32_t codeOffset; // offset of code: 64-bit alignment
277 uint32_t codeSize;
278 uint32_t dataOffset; // offset of data section
279 uint32_t dataSize;
280
281 // uint32_t flags; // some info flags
282 uint32_t checksum; // adler32 checksum covering deps/opt
283};
284
Logan824dd0a2010-11-20 01:45:54 +0800285struct oBCCRelocEntry {
286 uint32_t relocType; // target instruction relocation type
287 uint32_t relocOffset; // offset of hole (holeAddr - codeAddr)
288 uint32_t cachedResultAddr; // address resolved at compile time
289
Logan634bd832010-11-20 09:00:36 +0800290 oBCCRelocEntry(uint32_t ty, uintptr_t off, void *addr)
Logan824dd0a2010-11-20 01:45:54 +0800291 : relocType(ty),
292 relocOffset(static_cast<uint32_t>(off)),
293 cachedResultAddr(reinterpret_cast<uint32_t>(addr)) {
294 }
295};
296
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800297/* oBCCHeader Offset Table */
298#define k_magic offsetof(oBCCHeader, magic)
299#define k_magicVersion offsetof(oBCCHeader, magicVersion)
300#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
301#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
302#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
303#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
304#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
305#define k_rootAddr offsetof(oBCCHeader, rootAddr)
306#define k_initAddr offsetof(oBCCHeader, initAddr)
307#define k_relocOffset offsetof(oBCCHeader, relocOffset)
308#define k_relocCount offsetof(oBCCHeader, relocCount)
309#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
310#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
311#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
312#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
313#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
314#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
315#define k_codeOffset offsetof(oBCCHeader, codeOffset)
316#define k_codeSize offsetof(oBCCHeader, codeSize)
317#define k_dataOffset offsetof(oBCCHeader, dataOffset)
318#define k_dataSize offsetof(oBCCHeader, dataSize)
319#define k_checksum offsetof(oBCCHeader, checksum)
320
321/* oBCC file magic number */
322#define OBCC_MAGIC "bcc\n"
323/* version, encoded in 4 bytes of ASCII */
324#define OBCC_MAGIC_VERS "001\0"
325
326#define TEMP_FAILURE_RETRY1(exp) ({ \
327 typeof (exp) _rc; \
328 do { \
329 _rc = (exp); \
330 } while (_rc == -1 && errno == EINTR); \
331 _rc; })
332
333static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
334{
335 while (count != 0) {
336 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
337 if (actual < 0) {
338 int err = errno;
339 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
340 return err;
341 } else if (actual != (ssize_t) count) {
342 LOGD("%s: partial write (will retry): (%d of %zd)\n",
343 logMsg, (int) actual, count);
344 buf = (const void*) (((const uint8_t*) buf) + actual);
345 }
346 count -= actual;
347 }
348
349 return 0;
350}
351
Zonr Chang932648d2010-10-13 22:23:56 +0800352//
353// Compilation class that suits Android's needs.
354// (Support: no argument passed, ...)
355//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700356namespace bcc {
357
358class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800359 // This part is designed to be orthogonal to those exported bcc*() functions
360 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700361
Zonr Chang932648d2010-10-13 22:23:56 +0800362 //////////////////////////////////////////////////////////////////////////////
363 // The variable section below (e.g., Triple, CodeGenOptLevel)
364 // is initialized in GlobalInitialization()
365 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700366 static bool GlobalInitialized;
Loganc0b9f652010-11-24 22:33:16 +0800367 static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700368
Zonr Chang932648d2010-10-13 22:23:56 +0800369 // If given, this will be the name of the target triple to compile for.
370 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700371 static std::string Triple;
372
373 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700374
Zonr Chang932648d2010-10-13 22:23:56 +0800375 // End of section of GlobalInitializing variables
376 //////////////////////////////////////////////////////////////////////////////
377
378 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700379 static std::string CPU;
380
Zonr Chang932648d2010-10-13 22:23:56 +0800381 // The list of target specific features to enable or disable -- this should
382 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700383 static std::vector<std::string> Features;
384
385 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800386 const char *mName;
387 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700388 };
389 static struct Runtime Runtimes[];
390
391 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800392 if (GlobalInitialized)
393 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700394
Zonr Chang932648d2010-10-13 22:23:56 +0800395 // if (!llvm::llvm_is_multithreaded())
396 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700397
Zonr Chang932648d2010-10-13 22:23:56 +0800398 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700399 Triple = TARGET_TRIPLE_STRING;
400
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800401 // TODO(sliao): NEON for JIT
Zonr Chang932648d2010-10-13 22:23:56 +0800402 // Features.push_back("+neon");
403 // Features.push_back("+vmlx");
404 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700405 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700406 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700407
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700408#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
409 LLVMInitializeARMTargetInfo();
410 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700411#if defined(USE_DISASSEMBLER)
412 LLVMInitializeARMDisassembler();
413 LLVMInitializeARMAsmPrinter();
414#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700415#endif
416
417#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
418 LLVMInitializeX86TargetInfo();
419 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700420#if defined(USE_DISASSEMBLER)
421 LLVMInitializeX86Disassembler();
422 LLVMInitializeX86AsmPrinter();
423#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700424#endif
425
426#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
427 LLVMInitializeX86TargetInfo();
428 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700429#if defined(USE_DISASSEMBLER)
430 LLVMInitializeX86Disassembler();
431 LLVMInitializeX86AsmPrinter();
432#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700433#endif
434
Zonr Chang932648d2010-10-13 22:23:56 +0800435 // -O0: llvm::CodeGenOpt::None
436 // -O1: llvm::CodeGenOpt::Less
437 // -O2: llvm::CodeGenOpt::Default
438 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700439 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700440
Zonr Chang932648d2010-10-13 22:23:56 +0800441 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700442
Zonr Chang932648d2010-10-13 22:23:56 +0800443 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700444 llvm::NoFramePointerElim = false;
445
Zonr Chang932648d2010-10-13 22:23:56 +0800446 // Use hardfloat ABI
447 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800448 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800449 // softfp. To use softfp, change following 2 lines to
450 //
451 // llvm::FloatABIType = llvm::FloatABI::Soft;
452 // llvm::UseSoftFloat = true;
453 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700454 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700455 llvm::UseSoftFloat = false;
456
Zonr Chang932648d2010-10-13 22:23:56 +0800457 // BCC needs all unknown symbols resolved at JIT/compilation time.
458 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700459 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
460
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700461#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800462 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700463 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
464#else
Zonr Chang932648d2010-10-13 22:23:56 +0800465 // This is set for the linker (specify how large of the virtual addresses
466 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700467 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
468#endif
469
Zonr Chang932648d2010-10-13 22:23:56 +0800470 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700471 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
472
Zonr Chang932648d2010-10-13 22:23:56 +0800473 // Register allocation policy:
474 // createFastRegisterAllocator: fast but bad quality
475 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700476 llvm::RegisterRegAlloc::setDefault
477 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700478 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700479 llvm::createLinearScanRegisterAllocator);
480
481 GlobalInitialized = true;
482 return;
483 }
484
485 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800486 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700487 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700488 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800489 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700490 }
491
492 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700493 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700494 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700495
496 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700497 std::string mError;
498
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700499 inline bool hasError() const {
500 return !mError.empty();
501 }
Zonr Chang932648d2010-10-13 22:23:56 +0800502 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700503 mError.assign(Error); // Copying
504 return;
505 }
Zonr Chang932648d2010-10-13 22:23:56 +0800506 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700507 mError = Error;
508 return;
509 }
510
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800511 bool mUseCache; // Set by readBC()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800512 bool mCacheNew; // Set by readBC()
513 int mCacheFd; // Set by readBC()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800514 char *mCacheMapAddr; // Set by loadCacheFile() if mCacheNew is false
515 oBCCHeader *mCacheHdr; // Set by loadCacheFile()
516 size_t mCacheSize; // Set by loadCacheFile()
517 ptrdiff_t mCacheDiff; // Set by loadCacheFile()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800518 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
519 // Used by genCacheFile() for dumping
520
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700521 typedef std::list< std::pair<std::string, std::string> > PragmaList;
522 PragmaList mPragmas;
523
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700524 typedef std::list<void*> ExportVarList;
525 ExportVarList mExportVars;
526
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700527 typedef std::list<void*> ExportFuncList;
528 ExportFuncList mExportFuncs;
529
Zonr Chang932648d2010-10-13 22:23:56 +0800530 //////////////////////////////////////////////////////////////////////////////
531 // Memory manager for the code reside in memory
532 //
533 // The memory for our code emitter is very simple and is conforming to the
534 // design decisions of Android RenderScript's Exection Environment:
535 // The code, data, and symbol sizes are limited (currently 100KB.)
536 //
537 // It's very different from typical compiler, which has no limitation
538 // on the code size. How does code emitter know the size of the code
539 // it is about to emit? It does not know beforehand. We want to solve
540 // this without complicating the code emitter too much.
541 //
542 // We solve this by pre-allocating a certain amount of memory,
543 // and then start the code emission. Once the buffer overflows, the emitter
544 // simply discards all the subsequent emission but still has a counter
545 // on how many bytes have been emitted.
546 //
547 // So once the whole emission is done, if there's a buffer overflow,
548 // it re-allocates the buffer with enough size (based on the
549 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800550
551 // 128 KiB for code
Loganc0b9f652010-11-24 22:33:16 +0800552 static const unsigned int MaxCodeSize = BCC_MMAP_IMG_CODE_SIZE;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800553 // 1 KiB for global offset table (GOT)
554 static const unsigned int MaxGOTSize = 1 * 1024;
555 // 128 KiB for global variable
Loganc0b9f652010-11-24 22:33:16 +0800556 static const unsigned int MaxGlobalVarSize = BCC_MMAP_IMG_DATA_SIZE;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800557
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700558 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700559 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800560 //
561 // Our memory layout is as follows:
562 //
563 // The direction of arrows (-> and <-) shows memory's growth direction
564 // when more space is needed.
565 //
566 // @mpCodeMem:
567 // +--------------------------------------------------------------+
568 // | Function Memory ... -> <- ... Stub/GOT |
569 // +--------------------------------------------------------------+
570 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
571 //
572 // Where size of GOT is @MaxGOTSize KiB.
573 //
574 // @mpGVMem:
575 // +--------------------------------------------------------------+
576 // | Global variable ... -> |
577 // +--------------------------------------------------------------+
578 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
579 //
580 //
581 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
582 // of function code's memory usage
583 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
584 // of stub/GOT's memory usage
585 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
586 // of global variable's memory usage
587 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700588 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700589 uintptr_t mCurSGMemIdx;
590 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800591 void *mpCodeMem;
592 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700593
Zonr Chang932648d2010-10-13 22:23:56 +0800594 // GOT Base
595 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700596
597 typedef std::map<const llvm::Function*, pair<void* /* start address */,
598 void* /* end address */>
599 > FunctionMapTy;
600 FunctionMapTy mFunctionMap;
601
Zonr Chang932648d2010-10-13 22:23:56 +0800602 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700603 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700604 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700605
Zonr Chang932648d2010-10-13 22:23:56 +0800606 uint8_t *allocateSGMemory(uintptr_t Size,
607 unsigned Alignment = 1 /* no alignment */) {
608 intptr_t FreeMemSize = getFreeCodeMemSize();
609 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
610 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700611 return NULL;
612
Zonr Chang932648d2010-10-13 22:23:56 +0800613 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700614 Alignment = 1;
615
Zonr Chang932648d2010-10-13 22:23:56 +0800616 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700617 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
618
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700619 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700620
621 return result;
622 }
623
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700624 inline uintptr_t getFreeGVMemSize() const {
625 return MaxGlobalVarSize - mCurGVMemIdx;
626 }
Zonr Chang932648d2010-10-13 22:23:56 +0800627 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700628 return reinterpret_cast<uint8_t*>(mpGVMem);
629 }
630
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700631 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700632 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700633 reset();
634 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700635
Loganc0b9f652010-11-24 22:33:16 +0800636 // Try to use fixed address
637
638 // Note: If we failed to allocate mpCodeMem at fixed address,
639 // the caching mechanism has to either perform relocation or
640 // give up. If the caching mechanism gives up, then we have to
641 // recompile the bitcode and wasting a lot of time.
642
643 for (size_t i = 0; i < BCC_MMAP_IMG_COUNT; ++i) {
644 if (Compiler::BccMmapImgAddrTaken[i]) {
645 // The address BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE has
646 // been taken.
647 continue;
648 }
649
650 // Occupy the mmap image address first (No matter allocation
651 // success or not. Keep occupying if succeed; otherwise,
652 // keep occupying as a mark of failure.)
653 Compiler::BccMmapImgAddrTaken[i] = true;
654
655 void *currMmapImgAddr =
656 reinterpret_cast<void *>(BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE);
657
658 mpCodeMem = mmap(currMmapImgAddr, BCC_MMAP_IMG_SIZE,
Loganad7e8e12010-11-22 20:43:43 +0800659 PROT_READ | PROT_EXEC | PROT_WRITE,
660 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
661 -1, 0);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800662
Loganad7e8e12010-11-22 20:43:43 +0800663 if (mpCodeMem == MAP_FAILED) {
Loganc0b9f652010-11-24 22:33:16 +0800664 LOGE("Mmap mpCodeMem at %p failed with reason: %s. Retrying ..\n",
665 currMmapImgAddr, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800666 } else {
Loganc0b9f652010-11-24 22:33:16 +0800667 // Good, we have got one mmap image address.
668 break;
Loganad7e8e12010-11-22 20:43:43 +0800669 }
670 }
671
Loganc0b9f652010-11-24 22:33:16 +0800672 if (!mpCodeMem || mpCodeMem == MAP_FAILED) {
673 LOGE("Try to allocate mpCodeMem at arbitary address.\n");
Loganad7e8e12010-11-22 20:43:43 +0800674
Loganc0b9f652010-11-24 22:33:16 +0800675 mpCodeMem = mmap(NULL, BCC_MMAP_IMG_SIZE,
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800676 PROT_READ | PROT_EXEC | PROT_WRITE,
677 MAP_PRIVATE | MAP_ANON,
Loganad7e8e12010-11-22 20:43:43 +0800678 -1, 0);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800679
Loganad7e8e12010-11-22 20:43:43 +0800680 if (mpCodeMem == MAP_FAILED) {
681 LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
682 llvm::report_fatal_error("Failed to allocate memory for emitting "
683 "codes\n" + ErrMsg);
684 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800685 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800686
Loganc0b9f652010-11-24 22:33:16 +0800687 LOGE("Mmap mpCodeMem at %p successfully.\n", mpCodeMem);
688
Loganad7e8e12010-11-22 20:43:43 +0800689 // Set global variable pool
690 mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
691
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700692 return;
693 }
694
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800695 inline uint8_t *getCodeMemBase() const {
696 return reinterpret_cast<uint8_t*>(mpCodeMem);
697 }
698
Zonr Chang932648d2010-10-13 22:23:56 +0800699 // setMemoryWritable - When code generation is in progress, the code pages
700 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700701 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700702 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700703 return;
704 }
705
Zonr Chang932648d2010-10-13 22:23:56 +0800706 // When code generation is done and we're ready to start execution, the
707 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700708 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700709 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700710 return;
711 }
712
Zonr Chang932648d2010-10-13 22:23:56 +0800713 // Setting this flag to true makes the memory manager garbage values over
714 // freed memory. This is useful for testing and debugging, and is to be
715 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700716 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800717 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700718 return;
719 }
720
Zonr Chang932648d2010-10-13 22:23:56 +0800721 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700722
Zonr Chang932648d2010-10-13 22:23:56 +0800723 // If the current table requires a Global Offset Table, this method is
724 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700725 void AllocateGOT() {
726 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700727 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700728 HasGOT = true;
729 return;
730 }
731
Zonr Chang932648d2010-10-13 22:23:56 +0800732 // If this is managing a Global Offset Table, this method should return a
733 // pointer to its base.
734 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700735 return mpGOTBase;
736 }
737
Zonr Chang932648d2010-10-13 22:23:56 +0800738 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700739
Zonr Chang932648d2010-10-13 22:23:56 +0800740 // When we start JITing a function, the JIT calls this method to allocate a
741 // block of free RWX memory, which returns a pointer to it. If the JIT wants
742 // to request a block of memory of at least a certain size, it passes that
743 // value as ActualSize, and this method returns a block with at least that
744 // much space. If the JIT doesn't know ahead of time how much space it will
745 // need to emit the function, it passes 0 for the ActualSize. In either
746 // case, this method is required to pass back the size of the allocated
747 // block through ActualSize. The JIT will be careful to not write more than
748 // the returned ActualSize bytes of memory.
749 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
750 intptr_t FreeMemSize = getFreeCodeMemSize();
751 if ((FreeMemSize < 0) ||
752 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
753 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700754 return NULL;
755
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700756 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700757 return (getCodeMemBase() + mCurFuncMemIdx);
758 }
759
Zonr Chang932648d2010-10-13 22:23:56 +0800760 // This method is called by the JIT to allocate space for a function stub
761 // (used to handle limited branch displacements) while it is JIT compiling a
762 // function. For example, if foo calls bar, and if bar either needs to be
763 // lazily compiled or is a native function that exists too far away from the
764 // call site to work, this method will be used to make a thunk for it. The
765 // stub should be "close" to the current function body, but should not be
766 // included in the 'actualsize' returned by startFunctionBody.
767 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700768 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700769 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700770 }
771
Zonr Chang932648d2010-10-13 22:23:56 +0800772 // This method is called when the JIT is done codegen'ing the specified
773 // function. At this point we know the size of the JIT compiled function.
774 // This passes in FunctionStart (which was returned by the startFunctionBody
775 // method) and FunctionEnd which is a pointer to the actual end of the
776 // function. This method should mark the space allocated and remember where
777 // it is in case the client wants to deallocate it.
778 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
779 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700780 assert(FunctionEnd > FunctionStart);
781 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
782 "Mismatched function start/end!");
783
Zonr Chang932648d2010-10-13 22:23:56 +0800784 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700785 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700786 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700787 "Code size excess the limitation!");
788 mCurFuncMemIdx += FunctionCodeSize;
789
Zonr Chang932648d2010-10-13 22:23:56 +0800790 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700791 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
792 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800793 mFunctionMap.insert(
794 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
795 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700796
797 return;
798 }
799
Zonr Chang932648d2010-10-13 22:23:56 +0800800 // Allocate a (function code) memory block of the given size. This method
801 // cannot be called between calls to startFunctionBody and endFunctionBody.
802 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
803 if (getFreeCodeMemSize() < Size)
804 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700805 return NULL;
806
Zonr Chang932648d2010-10-13 22:23:56 +0800807 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700808 Alignment = 1;
809
Zonr Chang932648d2010-10-13 22:23:56 +0800810 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700811 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800812 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700813
814 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
815
816 return result;
817 }
818
Zonr Chang932648d2010-10-13 22:23:56 +0800819 // Allocate memory for a global variable.
820 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700821 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800822 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700823 LOGE("No Global Memory");
824 return NULL;
825 }
826
Zonr Chang932648d2010-10-13 22:23:56 +0800827 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700828 Alignment = 1;
829
Zonr Chang932648d2010-10-13 22:23:56 +0800830 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700831 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800832 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700833
834 mCurGVMemIdx = (result + Size) - getGVMemBase();
835
836 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700837 }
838
Zonr Chang932648d2010-10-13 22:23:56 +0800839 // Free the specified function body. The argument must be the return value
840 // from a call to startFunctionBody() that hasn't been deallocated yet. This
841 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700842 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800843 // linear search
844 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
845 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
846 E = mFunctionMap.end();
847 I != E;
848 I++)
849 if (I->second.first == Body) {
850 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
851 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700852 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800853 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700854
Zonr Chang932648d2010-10-13 22:23:56 +0800855 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700856
Zonr Chang932648d2010-10-13 22:23:56 +0800857 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700858 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
859
860 assert(SizeNeedMove >= 0 &&
861 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
862 " be correctly calculated!");
863
Zonr Chang932648d2010-10-13 22:23:56 +0800864 if (SizeNeedMove > 0)
865 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700866 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
867 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
868
869 return;
870 }
871
Zonr Chang932648d2010-10-13 22:23:56 +0800872 // When we finished JITing the function, if exception handling is set, we
873 // emit the exception table.
874 uint8_t *startExceptionTable(const llvm::Function *F,
875 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700876 assert(false && "Exception is not allowed in our language specification");
877 return NULL;
878 }
879
Zonr Chang932648d2010-10-13 22:23:56 +0800880 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700881 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800882 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700883 assert(false && "Exception is not allowed in our language specification");
884 return;
885 }
886
Zonr Chang932648d2010-10-13 22:23:56 +0800887 // Free the specified exception table's memory. The argument must be the
888 // return value from a call to startExceptionTable() that hasn't been
889 // deallocated yet. This is never called when the JIT is currently emitting
890 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700891 void deallocateExceptionTable(void *ET) {
892 assert(false && "Exception is not allowed in our language specification");
893 return;
894 }
895
Zonr Chang932648d2010-10-13 22:23:56 +0800896 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700897 void reset() {
898 mpGOTBase = NULL;
899 HasGOT = false;
900
901 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700902 mCurSGMemIdx = MaxCodeSize - 1;
903 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700904
905 mFunctionMap.clear();
906
907 return;
908 }
909
910 ~CodeMemoryManager() {
Logan82e67012010-11-25 00:29:34 +0800911 if (mpCodeMem && mpCodeMem != MAP_FAILED) {
912 munmap(mpCodeMem, BCC_MMAP_IMG_SIZE);
Loganc0b9f652010-11-24 22:33:16 +0800913
914 // TODO(logan): Reset Compiler::BccMmapImgAddrTaken[i] to false, so
915 // that the address can be reused.
916 }
Logan82e67012010-11-25 00:29:34 +0800917
918 mpCodeMem = 0;
919 mpGVMem = 0;
920
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700921 return;
922 }
Zonr Chang932648d2010-10-13 22:23:56 +0800923 };
924 // End of class CodeMemoryManager
925 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700926
Zonr Chang932648d2010-10-13 22:23:56 +0800927 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700928 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800929 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700930 mCodeMemMgr.reset(new CodeMemoryManager());
931 return mCodeMemMgr.get();
932 }
933
Zonr Chang932648d2010-10-13 22:23:56 +0800934 //////////////////////////////////////////////////////////////////////////////
935 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700936 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700937 public:
938 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
939 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
940
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800941 GlobalAddressMapTy mGlobalAddressMap;
942
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700943 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800944 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700945
Zonr Chang932648d2010-10-13 22:23:56 +0800946 // The JITInfo for the target we are compiling to
947 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700948
Zonr Chang932648d2010-10-13 22:23:56 +0800949 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700950
Zonr Chang932648d2010-10-13 22:23:56 +0800951 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700952
Zonr Chang932648d2010-10-13 22:23:56 +0800953 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700954
Zonr Chang932648d2010-10-13 22:23:56 +0800955 typedef std::map<const std::string,
956 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700957 EmittedFunctionsMapTy mEmittedFunctions;
958
Zonr Chang932648d2010-10-13 22:23:56 +0800959 // This vector is a mapping from MBB ID's to their address. It is filled in
960 // by the StartMachineBasicBlock callback and queried by the
961 // getMachineBasicBlockAddress callback.
962 std::vector<uintptr_t> mMBBLocations;
963
964 // The constant pool for the current function.
965 llvm::MachineConstantPool *mpConstantPool;
966
967 // A pointer to the first entry in the constant pool.
968 void *mpConstantPoolBase;
969
970 // Addresses of individual constant pool entries.
971 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
972
973 // The jump tables for the current function.
974 llvm::MachineJumpTableInfo *mpJumpTable;
975
976 // A pointer to the first entry in the jump table.
977 void *mpJumpTableBase;
978
979 // When outputting a function stub in the context of some other function, we
980 // save BufferBegin/BufferEnd/CurBufferPtr here.
981 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
982
983 // These are the relocations that the function needs, as emitted.
984 std::vector<llvm::MachineRelocation> mRelocations;
985
Logan824dd0a2010-11-20 01:45:54 +0800986 std::vector<oBCCRelocEntry> mCachingRelocations;
987
Zonr Chang932648d2010-10-13 22:23:56 +0800988 // This vector is a mapping from Label ID's to their address.
989 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
990
991 // Machine module info for exception informations
992 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700993
Zonr Chang932648d2010-10-13 22:23:56 +0800994 // Replace an existing mapping for GV with a new address. This updates both
995 // maps as required. If Addr is null, the entry for the global is removed
996 // from the mappings.
997 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
998 if (Addr == NULL) {
999 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001000 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
1001 void *OldVal;
1002
Zonr Chang932648d2010-10-13 22:23:56 +08001003 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001004 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001005 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001006 OldVal = I->second;
1007 mGlobalAddressMap.erase(I);
1008 }
1009
1010 return OldVal;
1011 }
1012
Zonr Chang932648d2010-10-13 22:23:56 +08001013 void *&CurVal = mGlobalAddressMap[GV];
1014 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001015
1016 CurVal = Addr;
1017
1018 return OldVal;
1019 }
1020
Zonr Chang932648d2010-10-13 22:23:56 +08001021 // Tell the execution engine that the specified global is at the specified
1022 // location. This is used internally as functions are JIT'd and as global
1023 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001024 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001025 void *&CurVal = mGlobalAddressMap[GV];
1026 assert((CurVal == 0 || Addr == 0) &&
1027 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001028 CurVal = Addr;
1029 return;
1030 }
1031
Zonr Chang932648d2010-10-13 22:23:56 +08001032 // This returns the address of the specified global value if it is has
1033 // already been codegen'd, otherwise it returns null.
1034 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001035 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001036 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
1037 }
1038
Zonr Chang932648d2010-10-13 22:23:56 +08001039 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
1040 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001041 MCP->getConstants();
1042
Zonr Chang932648d2010-10-13 22:23:56 +08001043 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001044 return 0;
1045
1046 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001047 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001048 llvm::MachineConstantPoolEntry CPE = Constants[i];
1049 unsigned int AlignMask = CPE.getAlignment() - 1;
1050 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +08001051 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001052 Size += mpTD->getTypeAllocSize(Ty);
1053 }
1054
1055 return Size;
1056 }
1057
Zonr Chang932648d2010-10-13 22:23:56 +08001058 // This function converts a Constant* into a GenericValue. The interesting
1059 // part is if C is a ConstantExpr.
1060 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
1061 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001062 return;
Zonr Chang932648d2010-10-13 22:23:56 +08001063 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
1064 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
1065 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001066
Zonr Chang932648d2010-10-13 22:23:56 +08001067 switch (CE->getOpcode()) {
1068 case llvm::Instruction::GetElementPtr: {
1069 // Compute the index
1070 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
1071 CE->op_end());
1072 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
1073 &Indices[0],
1074 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001075
Zonr Chang932648d2010-10-13 22:23:56 +08001076 GetConstantValue(Op0, Result);
1077 Result.PointerVal =
1078 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001079
Zonr Chang932648d2010-10-13 22:23:56 +08001080 return;
1081 }
1082 case llvm::Instruction::Trunc: {
1083 uint32_t BitWidth =
1084 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1085
1086 GetConstantValue(Op0, Result);
1087 Result.IntVal = Result.IntVal.trunc(BitWidth);
1088
1089 return;
1090 }
1091 case llvm::Instruction::ZExt: {
1092 uint32_t BitWidth =
1093 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1094
1095 GetConstantValue(Op0, Result);
1096 Result.IntVal = Result.IntVal.zext(BitWidth);
1097
1098 return;
1099 }
1100 case llvm::Instruction::SExt: {
1101 uint32_t BitWidth =
1102 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1103
1104 GetConstantValue(Op0, Result);
1105 Result.IntVal = Result.IntVal.sext(BitWidth);
1106
1107 return;
1108 }
1109 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001110 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001111 GetConstantValue(Op0, Result);
1112 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1113 return;
1114 }
1115 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001116 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001117 GetConstantValue(Op0, Result);
1118 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1119 return;
1120 }
1121 case llvm::Instruction::UIToFP: {
1122 GetConstantValue(Op0, Result);
1123 if (CE->getType()->isFloatTy())
1124 Result.FloatVal =
1125 static_cast<float>(Result.IntVal.roundToDouble());
1126 else if (CE->getType()->isDoubleTy())
1127 Result.DoubleVal = Result.IntVal.roundToDouble();
1128 else if (CE->getType()->isX86_FP80Ty()) {
1129 const uint64_t zero[] = { 0, 0 };
1130 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1131 apf.convertFromAPInt(Result.IntVal,
1132 false,
1133 llvm::APFloat::rmNearestTiesToEven);
1134 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001135 }
Zonr Chang932648d2010-10-13 22:23:56 +08001136 return;
1137 }
1138 case llvm::Instruction::SIToFP: {
1139 GetConstantValue(Op0, Result);
1140 if (CE->getType()->isFloatTy())
1141 Result.FloatVal =
1142 static_cast<float>(Result.IntVal.signedRoundToDouble());
1143 else if (CE->getType()->isDoubleTy())
1144 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1145 else if (CE->getType()->isX86_FP80Ty()) {
1146 const uint64_t zero[] = { 0, 0 };
1147 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1148 apf.convertFromAPInt(Result.IntVal,
1149 true,
1150 llvm::APFloat::rmNearestTiesToEven);
1151 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001152 }
Zonr Chang932648d2010-10-13 22:23:56 +08001153 return;
1154 }
1155 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001156 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001157 case llvm::Instruction::FPToSI: {
1158 uint32_t BitWidth =
1159 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001160
Zonr Chang932648d2010-10-13 22:23:56 +08001161 GetConstantValue(Op0, Result);
1162 if (Op0->getType()->isFloatTy())
1163 Result.IntVal =
1164 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1165 else if (Op0->getType()->isDoubleTy())
1166 Result.IntVal =
1167 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1168 BitWidth);
1169 else if (Op0->getType()->isX86_FP80Ty()) {
1170 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1171 uint64_t V;
1172 bool Ignored;
1173 apf.convertToInteger(&V,
1174 BitWidth,
1175 CE->getOpcode() == llvm::Instruction::FPToSI,
1176 llvm::APFloat::rmTowardZero,
1177 &Ignored);
1178 Result.IntVal = V; // endian?
1179 }
1180 return;
1181 }
1182 case llvm::Instruction::PtrToInt: {
1183 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1184
1185 GetConstantValue(Op0, Result);
1186 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1187 (Result.PointerVal));
1188
1189 return;
1190 }
1191 case llvm::Instruction::IntToPtr: {
1192 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1193
1194 GetConstantValue(Op0, Result);
1195 if (PtrWidth != Result.IntVal.getBitWidth())
1196 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1197 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1198
1199 Result.PointerVal =
1200 llvm::PointerTy(
1201 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1202
1203 return;
1204 }
1205 case llvm::Instruction::BitCast: {
1206 GetConstantValue(Op0, Result);
1207 const llvm::Type *DestTy = CE->getType();
1208
1209 switch (Op0->getType()->getTypeID()) {
1210 case llvm::Type::IntegerTyID: {
1211 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1212 if (DestTy->isFloatTy())
1213 Result.FloatVal = Result.IntVal.bitsToFloat();
1214 else if (DestTy->isDoubleTy())
1215 Result.DoubleVal = Result.IntVal.bitsToDouble();
1216 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001217 }
Zonr Chang932648d2010-10-13 22:23:56 +08001218 case llvm::Type::FloatTyID: {
1219 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1220 Result.IntVal.floatToBits(Result.FloatVal);
1221 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001222 }
Zonr Chang932648d2010-10-13 22:23:56 +08001223 case llvm::Type::DoubleTyID: {
1224 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1225 Result.IntVal.doubleToBits(Result.DoubleVal);
1226 break;
1227 }
1228 case llvm::Type::PointerTyID: {
1229 assert(DestTy->isPointerTy() && "Invalid bitcast");
1230 break; // getConstantValue(Op0) above already converted it
1231 }
1232 default: {
1233 llvm_unreachable("Invalid bitcast operand");
1234 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001235 }
Zonr Chang932648d2010-10-13 22:23:56 +08001236 return;
1237 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001238 case llvm::Instruction::Add:
1239 case llvm::Instruction::FAdd:
1240 case llvm::Instruction::Sub:
1241 case llvm::Instruction::FSub:
1242 case llvm::Instruction::Mul:
1243 case llvm::Instruction::FMul:
1244 case llvm::Instruction::UDiv:
1245 case llvm::Instruction::SDiv:
1246 case llvm::Instruction::URem:
1247 case llvm::Instruction::SRem:
1248 case llvm::Instruction::And:
1249 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001250 case llvm::Instruction::Xor: {
1251 llvm::GenericValue LHS, RHS;
1252 GetConstantValue(Op0, LHS);
1253 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001254
Zonr Chang932648d2010-10-13 22:23:56 +08001255 switch (Op0->getType()->getTypeID()) {
1256 case llvm::Type::IntegerTyID: {
1257 switch (CE->getOpcode()) {
1258 case llvm::Instruction::Add: {
1259 Result.IntVal = LHS.IntVal + RHS.IntVal;
1260 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001261 }
Zonr Chang932648d2010-10-13 22:23:56 +08001262 case llvm::Instruction::Sub: {
1263 Result.IntVal = LHS.IntVal - RHS.IntVal;
1264 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001265 }
Zonr Chang932648d2010-10-13 22:23:56 +08001266 case llvm::Instruction::Mul: {
1267 Result.IntVal = LHS.IntVal * RHS.IntVal;
1268 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001269 }
Zonr Chang932648d2010-10-13 22:23:56 +08001270 case llvm::Instruction::UDiv: {
1271 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1272 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001273 }
Zonr Chang932648d2010-10-13 22:23:56 +08001274 case llvm::Instruction::SDiv: {
1275 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1276 break;
1277 }
1278 case llvm::Instruction::URem: {
1279 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1280 break;
1281 }
1282 case llvm::Instruction::SRem: {
1283 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1284 break;
1285 }
1286 case llvm::Instruction::And: {
1287 Result.IntVal = LHS.IntVal & RHS.IntVal;
1288 break;
1289 }
1290 case llvm::Instruction::Or: {
1291 Result.IntVal = LHS.IntVal | RHS.IntVal;
1292 break;
1293 }
1294 case llvm::Instruction::Xor: {
1295 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1296 break;
1297 }
1298 default: {
1299 llvm_unreachable("Invalid integer opcode");
1300 }
1301 }
1302 break;
1303 }
1304 case llvm::Type::FloatTyID: {
1305 switch (CE->getOpcode()) {
1306 case llvm::Instruction::FAdd: {
1307 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1308 break;
1309 }
1310 case llvm::Instruction::FSub: {
1311 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1312 break;
1313 }
1314 case llvm::Instruction::FMul: {
1315 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1316 break;
1317 }
1318 case llvm::Instruction::FDiv: {
1319 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1320 break;
1321 }
1322 case llvm::Instruction::FRem: {
1323 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1324 break;
1325 }
1326 default: {
1327 llvm_unreachable("Invalid float opcode");
1328 }
1329 }
1330 break;
1331 }
1332 case llvm::Type::DoubleTyID: {
1333 switch (CE->getOpcode()) {
1334 case llvm::Instruction::FAdd: {
1335 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1336 break;
1337 }
1338 case llvm::Instruction::FSub: {
1339 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1340 break;
1341 }
1342 case llvm::Instruction::FMul: {
1343 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1344 break;
1345 }
1346 case llvm::Instruction::FDiv: {
1347 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1348 break;
1349 }
1350 case llvm::Instruction::FRem: {
1351 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1352 break;
1353 }
1354 default: {
1355 llvm_unreachable("Invalid double opcode");
1356 }
1357 }
1358 break;
1359 }
1360 case llvm::Type::X86_FP80TyID:
1361 case llvm::Type::PPC_FP128TyID:
1362 case llvm::Type::FP128TyID: {
1363 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1364 switch (CE->getOpcode()) {
1365 case llvm::Instruction::FAdd: {
1366 apfLHS.add(llvm::APFloat(RHS.IntVal),
1367 llvm::APFloat::rmNearestTiesToEven);
1368 break;
1369 }
1370 case llvm::Instruction::FSub: {
1371 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1372 llvm::APFloat::rmNearestTiesToEven);
1373 break;
1374 }
1375 case llvm::Instruction::FMul: {
1376 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1377 llvm::APFloat::rmNearestTiesToEven);
1378 break;
1379 }
1380 case llvm::Instruction::FDiv: {
1381 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1382 llvm::APFloat::rmNearestTiesToEven);
1383 break;
1384 }
1385 case llvm::Instruction::FRem: {
1386 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1387 llvm::APFloat::rmNearestTiesToEven);
1388 break;
1389 }
1390 default: {
1391 llvm_unreachable("Invalid long double opcode");
1392 }
1393 }
1394 Result.IntVal = apfLHS.bitcastToAPInt();
1395 break;
1396 }
1397 default: {
1398 llvm_unreachable("Bad add type!");
1399 }
1400 } // End switch (Op0->getType()->getTypeID())
1401 return;
1402 }
1403 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001404 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001405 }
1406 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001407
1408 std::string msg;
1409 llvm::raw_string_ostream Msg(msg);
1410 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001411 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001412 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001413
1414 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001415 case llvm::Type::FloatTyID: {
1416 Result.FloatVal =
1417 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001418 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001419 }
1420 case llvm::Type::DoubleTyID: {
1421 Result.DoubleVal =
1422 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001423 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001424 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001425 case llvm::Type::X86_FP80TyID:
1426 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001427 case llvm::Type::PPC_FP128TyID: {
1428 Result.IntVal =
1429 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001430 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001431 }
1432 case llvm::Type::IntegerTyID: {
1433 Result.IntVal =
1434 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001435 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001436 }
1437 case llvm::Type::PointerTyID: {
1438 switch (C->getValueID()) {
1439 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001440 Result.PointerVal = NULL;
1441 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001442 }
1443 case llvm::Value::FunctionVal: {
1444 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1445 Result.PointerVal =
1446 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001447 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001448 }
1449 case llvm::Value::GlobalVariableVal: {
1450 const llvm::GlobalVariable *GV =
1451 static_cast<const llvm::GlobalVariable*>(C);
1452 Result.PointerVal =
1453 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001454 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001455 }
1456 case llvm::Value::BlockAddressVal: {
1457 assert(false && "JIT does not support address-of-label yet!");
1458 }
1459 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001460 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001461 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001462 }
1463 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001464 }
1465 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001466 std::string msg;
1467 llvm::raw_string_ostream Msg(msg);
1468 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001469 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001470 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001471 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001472 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001473 return;
1474 }
1475
Zonr Chang932648d2010-10-13 22:23:56 +08001476 // Stores the data in @Val of type @Ty at address @Addr.
1477 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001478 const llvm::Type *Ty) {
1479 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1480
Zonr Chang932648d2010-10-13 22:23:56 +08001481 switch (Ty->getTypeID()) {
1482 case llvm::Type::IntegerTyID: {
1483 const llvm::APInt &IntVal = Val.IntVal;
1484 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1485 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001486
Zonr Chang932648d2010-10-13 22:23:56 +08001487 const uint8_t *Src =
1488 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001489
Zonr Chang932648d2010-10-13 22:23:56 +08001490 if (llvm::sys::isLittleEndianHost()) {
1491 // Little-endian host - the source is ordered from LSB to MSB.
1492 // Order the destination from LSB to MSB: Do a straight copy.
1493 memcpy(Addr, Src, StoreBytes);
1494 } else {
1495 // Big-endian host - the source is an array of 64 bit words
1496 // ordered from LSW to MSW.
1497 //
1498 // Each word is ordered from MSB to LSB.
1499 //
1500 // Order the destination from MSB to LSB:
1501 // Reverse the word order, but not the bytes in a word.
1502 unsigned int i = StoreBytes;
1503 while (i > sizeof(uint64_t)) {
1504 i -= sizeof(uint64_t);
1505 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1506 Src,
1507 sizeof(uint64_t));
1508 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001509 }
Zonr Chang932648d2010-10-13 22:23:56 +08001510 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001511 }
1512 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001513 }
1514 case llvm::Type::FloatTyID: {
1515 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001516 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001517 }
1518 case llvm::Type::DoubleTyID: {
1519 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001520 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001521 }
1522 case llvm::Type::X86_FP80TyID: {
1523 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001524 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001525 }
1526 case llvm::Type::PointerTyID: {
1527 // Ensure 64 bit target pointers are fully initialized on 32 bit
1528 // hosts.
1529 if (StoreBytes != sizeof(llvm::PointerTy))
1530 memset(Addr, 0, StoreBytes);
1531 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001532 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001533 }
1534 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001535 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001536 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001537 }
1538
Zonr Chang932648d2010-10-13 22:23:56 +08001539 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1540 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1541 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001542
1543 return;
1544 }
1545
Zonr Chang932648d2010-10-13 22:23:56 +08001546 // Recursive function to apply a @Constant value into the specified memory
1547 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001548 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001549 switch (C->getValueID()) {
1550 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001551 // Nothing to do
1552 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001553 }
1554 case llvm::Value::ConstantVectorVal: {
1555 // dynamic cast may hurt performance
1556 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001557
Zonr Chang932648d2010-10-13 22:23:56 +08001558 unsigned int ElementSize = mpTD->getTypeAllocSize
1559 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001560
Zonr Chang932648d2010-10-13 22:23:56 +08001561 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1562 InitializeConstantToMemory(
1563 CP->getOperand(i),
1564 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001565 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001566 }
1567 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001568 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1569 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001570 }
1571 case llvm::Value::ConstantArrayVal: {
1572 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1573 unsigned int ElementSize = mpTD->getTypeAllocSize
1574 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001575
Zonr Chang932648d2010-10-13 22:23:56 +08001576 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1577 InitializeConstantToMemory(
1578 CPA->getOperand(i),
1579 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1580 break;
1581 }
1582 case llvm::Value::ConstantStructVal: {
1583 const llvm::ConstantStruct *CPS =
1584 static_cast<const llvm::ConstantStruct*>(C);
1585 const llvm::StructLayout *SL = mpTD->getStructLayout
1586 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001587
Zonr Chang932648d2010-10-13 22:23:56 +08001588 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1589 InitializeConstantToMemory(
1590 CPS->getOperand(i),
1591 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1592 break;
1593 }
1594 default: {
1595 if (C->getType()->isFirstClassType()) {
1596 llvm::GenericValue Val;
1597 GetConstantValue(C, Val);
1598 StoreValueToMemory(Val, Addr, C->getType());
1599 } else {
1600 llvm_unreachable("Unknown constant type to initialize memory "
1601 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001602 }
1603 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001604 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001605 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001606 return;
1607 }
1608
1609 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001610 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001611 return;
1612
Zonr Chang932648d2010-10-13 22:23:56 +08001613 // Constant pool address resolution is handled by the target itself in ARM
1614 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001615#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001616 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1617 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001618
Zonr Chang932648d2010-10-13 22:23:56 +08001619 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001620 return;
1621
1622 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1623 unsigned Align = MCP->getConstantPoolAlignment();
1624
1625 mpConstantPoolBase = allocateSpace(Size, Align);
1626 mpConstantPool = MCP;
1627
Zonr Chang932648d2010-10-13 22:23:56 +08001628 if (mpConstantPoolBase == NULL)
1629 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001630
1631 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001632 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001633 llvm::MachineConstantPoolEntry CPE = Constants[i];
1634 unsigned AlignMask = CPE.getAlignment() - 1;
1635 Offset = (Offset + AlignMask) & ~AlignMask;
1636
1637 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1638 mConstPoolAddresses.push_back(CAddr);
1639
Zonr Chang932648d2010-10-13 22:23:56 +08001640 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001641 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001642 ("Initialize memory with machine specific constant pool"
1643 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001644
1645 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1646
1647 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1648 Offset += mpTD->getTypeAllocSize(Ty);
1649 }
1650#endif
1651 return;
1652 }
1653
1654 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001655 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001656 return;
1657
Zonr Chang932648d2010-10-13 22:23:56 +08001658 const std::vector<llvm::MachineJumpTableEntry> &JT =
1659 MJTI->getJumpTables();
1660 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001661 return;
1662
1663 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001664 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001665 NumEntries += JT[i].MBBs.size();
1666
1667 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1668
Zonr Chang932648d2010-10-13 22:23:56 +08001669 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001670 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001671 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001672
1673 return;
1674 }
1675
1676 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001677 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001678 return;
1679
Zonr Chang932648d2010-10-13 22:23:56 +08001680 const std::vector<llvm::MachineJumpTableEntry> &JT =
1681 MJTI->getJumpTables();
1682 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001683 return;
1684
Zonr Chang932648d2010-10-13 22:23:56 +08001685 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1686 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1687 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001688
Zonr Chang932648d2010-10-13 22:23:56 +08001689 // For each jump table, map each target in the jump table to the
1690 // address of an emitted MachineBasicBlock.
1691 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1692 for (int i = 0, ie = JT.size(); i != ie; i++) {
1693 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1694 // Store the address of the basic block for this jump table slot in the
1695 // memory we allocated for the jump table in 'initJumpTableInfo'
1696 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001697 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1698 }
1699 }
1700
Zonr Chang932648d2010-10-13 22:23:56 +08001701 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1702 bool MayNeedFarStub) {
1703 switch (V->getValueID()) {
1704 case llvm::Value::FunctionVal: {
1705 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001706
Zonr Chang932648d2010-10-13 22:23:56 +08001707 // If we have code, go ahead and return that.
1708 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1709 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001710
Zonr Chang932648d2010-10-13 22:23:56 +08001711 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1712 // Return the function stub if it's already created.
1713 // We do this first so that:
1714 // we're returning the same address for the function as any
1715 // previous call.
1716 //
1717 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1718 // guaranteed to be close enough to call.
1719 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001720
Zonr Chang932648d2010-10-13 22:23:56 +08001721 // If we know the target can handle arbitrary-distance calls, try to
1722 // return a direct pointer.
1723 if (!MayNeedFarStub) {
1724 //
1725 // x86_64 architecture may encounter the bug:
1726 // http://llvm.org/bugs/show_bug.cgi?id=5201
1727 // which generate instruction "call" instead of "callq".
1728 //
1729 // And once the real address of stub is greater than 64-bit
1730 // long, the replacement will truncate to 32-bit resulting a
1731 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001732#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001733 // If this is an external function pointer, we can force the JIT
1734 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001735 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1736 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1737 // Changing to false because wanting to allow later calls to
1738 // mpTJI->relocate() without aborting. For caching purpose
1739 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001740#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001741 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001742
Zonr Chang932648d2010-10-13 22:23:56 +08001743 // Otherwise, we may need a to emit a stub, and, conservatively, we
1744 // always do so.
1745 return GetLazyFunctionStub(F);
1746 break;
1747 }
1748 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001749 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1750 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001751 }
1752 case llvm::Value::GlobalAliasVal: {
1753 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1754 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001755
Zonr Chang932648d2010-10-13 22:23:56 +08001756 switch (GV->getValueID()) {
1757 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001758 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001759 // code-gen'd?
1760 return GetPointerToFunction(
1761 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001762 /* AbortOnFailure = */false);
1763 // Changing to false because wanting to allow later calls to
1764 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001765 break;
1766 }
1767 case llvm::Value::GlobalVariableVal: {
1768 if (void *P = mGlobalAddressMap[GV])
1769 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001770
Zonr Chang932648d2010-10-13 22:23:56 +08001771 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1772 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001773
Zonr Chang932648d2010-10-13 22:23:56 +08001774 return mGlobalAddressMap[GV];
1775 break;
1776 }
1777 case llvm::Value::GlobalAliasVal: {
1778 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001779 }
1780 }
1781 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001782 }
1783 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001784 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001785 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001786 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001787 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001788 }
1789
Zonr Chang932648d2010-10-13 22:23:56 +08001790 // If the specified function has been code-gen'd, return a pointer to the
1791 // function. If not, compile it, or use a stub to implement lazy compilation
1792 // if available.
1793 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1794 // If we have already code generated the function, just return the
1795 // address.
1796 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001797 return Addr;
1798
Zonr Chang932648d2010-10-13 22:23:56 +08001799 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001800 return GetLazyFunctionStub(F);
1801 }
1802
Zonr Chang932648d2010-10-13 22:23:56 +08001803 typedef llvm::DenseMap<const llvm::Function*,
1804 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001805 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1806
Zonr Chang932648d2010-10-13 22:23:56 +08001807 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001808 return mFunctionToLazyStubMap.lookup(F);
1809 }
1810
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001811 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001812 void *GetLazyFunctionStub(llvm::Function *F) {
1813 // If we already have a lazy stub for this function, recycle it.
1814 void *&Stub = mFunctionToLazyStubMap[F];
1815 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001816 return Stub;
1817
Zonr Chang932648d2010-10-13 22:23:56 +08001818 // In any cases, we should NOT resolve function at runtime (though we are
1819 // able to). We resolve this right now.
1820 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001821 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1822 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1823 // Changing to false because wanting to allow later calls to
1824 // mpTJI->relocate() without aborting. For caching purpose
1825 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001826
Zonr Chang932648d2010-10-13 22:23:56 +08001827 // Codegen a new stub, calling the actual address of the external
1828 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001829 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1830 startGVStub(F, SL.Size, SL.Alignment);
1831 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1832 finishGVStub();
1833
Zonr Chang932648d2010-10-13 22:23:56 +08001834 // We really want the address of the stub in the GlobalAddressMap for the
1835 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001836 UpdateGlobalMapping(F, Stub);
1837
Zonr Chang932648d2010-10-13 22:23:56 +08001838 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001839 PendingFunctions.insert(F);
1840 else
Zonr Chang932648d2010-10-13 22:23:56 +08001841 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1842 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001843
1844 return Stub;
1845 }
1846
Zonr Chang932648d2010-10-13 22:23:56 +08001847 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1848 void *Addr = GetPointerToGlobalIfAvailable(F);
1849 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001850 return Addr;
1851
1852 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1853 "Internal error: only external defined function routes here!");
1854
Zonr Chang932648d2010-10-13 22:23:56 +08001855 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001856 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001857 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001858
Zonr Chang932648d2010-10-13 22:23:56 +08001859 // If we resolved the symbol to a null address (eg. a weak external)
1860 // return a null pointer let the application handle it.
1861 if (Addr == NULL) {
1862 if (AbortOnFailure)
1863 llvm::report_fatal_error("Could not resolve external function "
1864 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001865 else
1866 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001867 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001868
1869 AddGlobalMapping(F, Addr);
1870
1871 return Addr;
1872 }
1873
Zonr Chang932648d2010-10-13 22:23:56 +08001874 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001875 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001876 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001877 return Addr;
1878
Zonr Chang932648d2010-10-13 22:23:56 +08001879 if (mpSymbolLookupFn)
1880 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001881 return Addr;
1882
Zonr Chang932648d2010-10-13 22:23:56 +08001883 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001884 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001885 "' which could not be resolved!");
1886
1887 return NULL;
1888 }
1889
Zonr Chang932648d2010-10-13 22:23:56 +08001890 // Return the address of the specified global variable, possibly emitting it
1891 // to memory if needed. This is used by the Emitter.
1892 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1893 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1894 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001895 return Ptr;
1896
Zonr Chang932648d2010-10-13 22:23:56 +08001897 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1898 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001899 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1900 AddGlobalMapping(GV, Ptr);
1901 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001902 // If the global hasn't been emitted to memory yet, allocate space and
1903 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001904 Ptr = GetMemoryForGV(GV);
1905 AddGlobalMapping(GV, Ptr);
1906 EmitGlobalVariable(GV);
1907 }
1908
1909 return Ptr;
1910 }
1911
Zonr Chang932648d2010-10-13 22:23:56 +08001912 // This method abstracts memory allocation of global variable so that the
1913 // JIT can allocate thread local variables depending on the target.
1914 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1915 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001916
Zonr Chang932648d2010-10-13 22:23:56 +08001917 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001918 size_t S = mpTD->getTypeAllocSize(GlobalType);
1919 size_t A = mpTD->getPreferredAlignment(GV);
1920
Zonr Chang932648d2010-10-13 22:23:56 +08001921 if (GV->isThreadLocal()) {
1922 // We can support TLS by
1923 //
1924 // Ptr = TJI.allocateThreadLocalMemory(S);
1925 //
1926 // But I tend not to.
1927 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001928 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001929 ("Compilation of Thread Local Storage (TLS) is disabled!");
1930
Zonr Chang932648d2010-10-13 22:23:56 +08001931 } else if (mpTJI->allocateSeparateGVMemory()) {
1932 if (A <= 8) {
1933 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001934 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001935 // Allocate (S + A) bytes of memory, then use an aligned pointer
1936 // within that space.
1937 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001938 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001939 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1940 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001941 }
1942 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001943 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001944 }
1945
1946 return Ptr;
1947 }
1948
1949 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001950 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001951
Zonr Chang932648d2010-10-13 22:23:56 +08001952 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001953 llvm::report_fatal_error
1954 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001955
Zonr Chang932648d2010-10-13 22:23:56 +08001956 if (GA == NULL) {
1957 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001958 GA = GetMemoryForGV(GV);
1959 AddGlobalMapping(GV, GA);
1960 }
1961
1962 InitializeConstantToMemory(GV->getInitializer(), GA);
1963
Zonr Chang932648d2010-10-13 22:23:56 +08001964 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001965 return;
1966 }
1967
1968 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1969 > GlobalToIndirectSymMapTy;
1970 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1971
Zonr Chang932648d2010-10-13 22:23:56 +08001972 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1973 // Make sure GV is emitted first, and create a stub containing the fully
1974 // resolved address.
1975 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001976
Zonr Chang932648d2010-10-13 22:23:56 +08001977 // If we already have a stub for this global variable, recycle it.
1978 void *&IndirectSym = GlobalToIndirectSymMap[V];
1979 // Otherwise, codegen a new indirect symbol.
1980 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001981 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1982
1983 return IndirectSym;
1984 }
1985
Zonr Chang932648d2010-10-13 22:23:56 +08001986 // This is the equivalent of FunctionToLazyStubMap for external functions.
1987 //
1988 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1989 // It's actually here to make it more likely that far calls
1990 // succeed, but no single stub can guarantee that. I'll
1991 // remove this in a subsequent checkin when I actually fix
1992 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001993 std::map<void*, void*> ExternalFnToStubMap;
1994
Zonr Chang932648d2010-10-13 22:23:56 +08001995 // Return a stub for the function at the specified address.
1996 void *GetExternalFunctionStub(void *FnAddr) {
1997 void *&Stub = ExternalFnToStubMap[FnAddr];
1998 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001999 return Stub;
2000
2001 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2002 startGVStub(0, SL.Size, SL.Alignment);
2003 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
2004 finishGVStub();
2005
2006 return Stub;
2007 }
2008
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002009#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002010 const llvm::MCAsmInfo *mpAsmInfo;
2011 const llvm::MCDisassembler *mpDisassmbler;
2012 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002013
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002014 class BufferMemoryObject : public llvm::MemoryObject {
2015 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002016 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002017 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002018
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002019 public:
2020 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
2021 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002022
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002023 uint64_t getBase() const { return 0; }
2024 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002025
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002026 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002027 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002028 return -1;
2029 *Byte = mBytes[Addr];
2030 return 0;
2031 }
2032 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002033
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002034 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002035 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002036 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08002037 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002038#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002039 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08002040 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
2041 ErrorInfo,
2042 llvm::raw_fd_ostream::F_Append);
2043 if (!ErrorInfo.empty()) { // some errors occurred
2044 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002045 delete OS;
2046 return;
2047 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002048#else
2049 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002050#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002051 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
2052 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002053
Zonr Chang932648d2010-10-13 22:23:56 +08002054 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002055 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08002056 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002057 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08002058 if (mpIP == NULL)
2059 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
2060 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002061
Zonr Chang932648d2010-10-13 22:23:56 +08002062 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
2063 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002064 uint64_t Size;
2065 uint64_t Index;
2066
Zonr Chang932648d2010-10-13 22:23:56 +08002067 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002068 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002069
Zonr Chang932648d2010-10-13 22:23:56 +08002070 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2071 /* REMOVED */ llvm::nulls())) {
2072 (*OS).indent(4)
2073 .write("0x", 2)
2074 .write_hex((uint32_t) Start + Index)
2075 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002076 mpIP->printInst(&Inst, *OS);
2077 *OS << "\n";
2078 } else {
2079 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002080 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002081 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002082 }
2083
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002084 *OS << "\n";
2085 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002086
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002087#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002088 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002089 OS->close();
2090 delete OS;
2091#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002092 return;
2093 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002094#else
Zonr Chang932648d2010-10-13 22:23:56 +08002095 inline void Disassemble(const std::string &Name, uint8_t *Start,
2096 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002097 return;
2098 }
Zonr Chang932648d2010-10-13 22:23:56 +08002099#endif // defined(USE_DISASSEMBLER)
2100
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002101 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002102 // Resolver to undefined symbol in CodeEmitter
2103 BCCSymbolLookupFn mpSymbolLookupFn;
2104 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002105
2106 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002107 // Will take the ownership of @MemMgr
2108 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2109 : mpMemMgr(pMemMgr),
2110 mpTarget(NULL),
2111 mpTJI(NULL),
2112 mpTD(NULL),
2113 mpCurEmitFunction(NULL),
2114 mpConstantPool(NULL),
2115 mpJumpTable(NULL),
2116 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002117#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002118 mpAsmInfo(NULL),
2119 mpDisassmbler(NULL),
2120 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002121#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002122 mpSymbolLookupFn(NULL),
2123 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002124 return;
2125 }
2126
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002127 inline global_addresses_const_iterator global_address_begin() const {
2128 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002129 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002130 inline global_addresses_const_iterator global_address_end() const {
2131 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002132 }
2133
Logan824dd0a2010-11-20 01:45:54 +08002134 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2135 return mCachingRelocations;
2136 }
2137
Zonr Chang932648d2010-10-13 22:23:56 +08002138 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002139 mpSymbolLookupFn = pFn;
2140 mpSymbolLookupContext = pContext;
2141 return;
2142 }
2143
Zonr Chang932648d2010-10-13 22:23:56 +08002144 void setTargetMachine(llvm::TargetMachine &TM) {
2145 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002146 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002147 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002148 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002149 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002150 mpTD = TM.getTargetData();
2151
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002152 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2153
2154 return;
2155 }
2156
Zonr Chang932648d2010-10-13 22:23:56 +08002157 // This callback is invoked when the specified function is about to be code
2158 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002159 void startFunction(llvm::MachineFunction &F) {
2160 uintptr_t ActualSize = 0;
2161
2162 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002163
2164 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2165 // MachineCodeEmitter, which is the super class of the class
2166 // JITCodeEmitter.
2167 //
2168 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2169 // allocated for this code buffer.
2170 //
2171 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2172 // code. This is guranteed to be in the range
2173 // [BufferBegin, BufferEnd]. If this pointer is at
2174 // BufferEnd, it will never move due to code emission, and
2175 // all code emission requests will be ignored (this is the
2176 // buffer overflow condition).
2177 BufferBegin = CurBufferPtr =
2178 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002179 BufferEnd = BufferBegin + ActualSize;
2180
Zonr Chang932648d2010-10-13 22:23:56 +08002181 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002182 mpCurEmitFunction = new EmittedFunctionCode();
2183 mpCurEmitFunction->FunctionBody = BufferBegin;
2184
Zonr Chang932648d2010-10-13 22:23:56 +08002185 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002186 emitAlignment(16);
2187
2188 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002189 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002190 initJumpTableInfo(MJTI);
2191
Zonr Chang932648d2010-10-13 22:23:56 +08002192 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002193 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2194
2195 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2196
2197 mpCurEmitFunction->Code = CurBufferPtr;
2198
2199 mMBBLocations.clear();
2200
2201 return;
2202 }
2203
Zonr Chang932648d2010-10-13 22:23:56 +08002204 // This callback is invoked when the specified function has finished code
2205 // generation. If a buffer overflow has occurred, this method returns true
2206 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002207 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002208 if (CurBufferPtr == BufferEnd) {
2209 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002210 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2211 return false;
2212 }
2213
Zonr Chang932648d2010-10-13 22:23:56 +08002214 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002215 emitJumpTableInfo(MJTI);
2216
Zonr Chang932648d2010-10-13 22:23:56 +08002217 // FnStart is the start of the text, not the start of the constant pool
2218 // and other per-function data.
2219 uint8_t *FnStart =
2220 reinterpret_cast<uint8_t*>(
2221 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002222
Zonr Chang932648d2010-10-13 22:23:56 +08002223 // FnEnd is the end of the function's machine code.
2224 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002225
Zonr Chang932648d2010-10-13 22:23:56 +08002226 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002227 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2228
Zonr Chang932648d2010-10-13 22:23:56 +08002229 // Resolve the relocations to concrete pointers.
2230 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2231 llvm::MachineRelocation &MR = mRelocations[i];
2232 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002233
Zonr Chang932648d2010-10-13 22:23:56 +08002234 if (!MR.letTargetResolve()) {
2235 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002236 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002237
2238 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002239 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002240 }
2241
Zonr Chang932648d2010-10-13 22:23:56 +08002242 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002243 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2244 BufferBegin
2245 + MR.getMachineCodeOffset(),
2246 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002247 } else if (MR.isIndirectSymbol()) {
2248 ResultPtr =
2249 GetPointerToGVIndirectSym(
2250 MR.getGlobalValue(),
2251 BufferBegin + MR.getMachineCodeOffset());
2252 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002253 ResultPtr =
2254 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002255 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002256 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002257 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002258 } else {
2259 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2260 ResultPtr =
2261 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2262 }
2263
Logan824dd0a2010-11-20 01:45:54 +08002264 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2265 // TODO(logan): Cache external symbol relocation entry.
2266 // Currently, we are not caching them. But since Android
2267 // system is using prelink, it is not a problem.
2268
2269 // Cache the relocation result address
2270 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002271 oBCCRelocEntry(MR.getRelocationType(),
2272 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002273 ResultPtr));
2274 }
2275
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002276 MR.setResultPointer(ResultPtr);
2277 }
2278 }
2279
2280 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2281 mpMemMgr->getGOTBase());
2282 }
2283
2284 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002285 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2286 // global variables that were referenced in the relocations.
2287 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002288 return false;
2289
Zonr Chang932648d2010-10-13 22:23:56 +08002290 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002291 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2292 BufferBegin = CurBufferPtr = 0;
2293
Zonr Chang932648d2010-10-13 22:23:56 +08002294 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002295 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2296 mpCurEmitFunction = NULL;
2297
2298 mRelocations.clear();
2299 mConstPoolAddresses.clear();
2300
Zonr Chang932648d2010-10-13 22:23:56 +08002301 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002302 mpMMI->EndFunction();
2303
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002304 updateFunctionStub(F.getFunction());
2305
Zonr Chang932648d2010-10-13 22:23:56 +08002306 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002307 mpMemMgr->setMemoryExecutable();
2308
2309 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2310
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002311 return false;
2312 }
2313
Zonr Chang932648d2010-10-13 22:23:56 +08002314 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002315 unsigned Alignment) {
2316 mpSavedBufferBegin = BufferBegin;
2317 mpSavedBufferEnd = BufferEnd;
2318 mpSavedCurBufferPtr = CurBufferPtr;
2319
2320 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2321 Alignment);
2322 BufferEnd = BufferBegin + StubSize + 1;
2323
2324 return;
2325 }
2326
Zonr Chang932648d2010-10-13 22:23:56 +08002327 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002328 mpSavedBufferBegin = BufferBegin;
2329 mpSavedBufferEnd = BufferEnd;
2330 mpSavedCurBufferPtr = CurBufferPtr;
2331
Zonr Chang932648d2010-10-13 22:23:56 +08002332 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002333 BufferEnd = BufferBegin + StubSize + 1;
2334
2335 return;
2336 }
2337
2338 void finishGVStub() {
2339 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2340
Zonr Chang932648d2010-10-13 22:23:56 +08002341 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002342 BufferBegin = mpSavedBufferBegin;
2343 BufferEnd = mpSavedBufferEnd;
2344 CurBufferPtr = mpSavedCurBufferPtr;
2345
2346 return;
2347 }
2348
Zonr Chang932648d2010-10-13 22:23:56 +08002349 // Allocates and fills storage for an indirect GlobalValue, and returns the
2350 // address.
2351 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002352 const uint8_t *Buffer, size_t Size,
2353 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002354 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002355 memcpy(IndGV, Buffer, Size);
2356 return IndGV;
2357 }
2358
Zonr Chang932648d2010-10-13 22:23:56 +08002359 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002360 void emitLabel(llvm::MCSymbol *Label) {
2361 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002362 return;
2363 }
2364
Zonr Chang932648d2010-10-13 22:23:56 +08002365 // Allocate memory for a global. Unlike allocateSpace, this method does not
2366 // allocate memory in the current output buffer, because a global may live
2367 // longer than the current function.
2368 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2369 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002370 return mpMemMgr->allocateGlobal(Size, Alignment);
2371 }
2372
Zonr Chang932648d2010-10-13 22:23:56 +08002373 // This should be called by the target when a new basic block is about to be
2374 // emitted. This way the MCE knows where the start of the block is, and can
2375 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002376 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002377 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002378 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2379 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2380 return;
2381 }
2382
Zonr Chang932648d2010-10-13 22:23:56 +08002383 // Whenever a relocatable address is needed, it should be noted with this
2384 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002385 void addRelocation(const llvm::MachineRelocation &MR) {
2386 mRelocations.push_back(MR);
2387 return;
2388 }
2389
Zonr Chang932648d2010-10-13 22:23:56 +08002390 // Return the address of the @Index entry in the constant pool that was
2391 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002392 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2393 assert(Index < mpConstantPool->getConstants().size() &&
2394 "Invalid constant pool index!");
2395 return mConstPoolAddresses[Index];
2396 }
2397
Zonr Chang932648d2010-10-13 22:23:56 +08002398 // Return the address of the jump table with index @Index in the function
2399 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002400 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002401 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002402 mpJumpTable->getJumpTables();
2403
Zonr Chang932648d2010-10-13 22:23:56 +08002404 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002405
2406 unsigned int Offset = 0;
2407 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2408
Zonr Chang932648d2010-10-13 22:23:56 +08002409 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002410 Offset += JT[i].MBBs.size();
2411 Offset *= EntrySize;
2412
Zonr Chang932648d2010-10-13 22:23:56 +08002413 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002414 }
2415
Zonr Chang932648d2010-10-13 22:23:56 +08002416 // Return the address of the specified MachineBasicBlock, only usable after
2417 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002418 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2419 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002420 mMBBLocations[MBB->getNumber()] &&
2421 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002422 return mMBBLocations[MBB->getNumber()];
2423 }
2424
Zonr Chang932648d2010-10-13 22:23:56 +08002425 // Return the address of the specified LabelID, only usable after the
2426 // LabelID has been emitted.
2427 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002428 assert(mLabelLocations.count(Label) && "Label not emitted!");
2429 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002430 }
2431
Zonr Chang932648d2010-10-13 22:23:56 +08002432 // Specifies the MachineModuleInfo object. This is used for exception
2433 // handling purposes.
2434 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002435 mpMMI = Info;
2436 return;
2437 }
2438
Zonr Chang932648d2010-10-13 22:23:56 +08002439 void updateFunctionStub(const llvm::Function *F) {
2440 // Get the empty stub we generated earlier.
2441 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002442 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002443 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002444 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002445 else
2446 return;
2447
Zonr Chang932648d2010-10-13 22:23:56 +08002448 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002449
2450 assert(Addr != Stub &&
2451 "Function must have non-stub address to be updated.");
2452
Zonr Chang932648d2010-10-13 22:23:56 +08002453 // Tell the target jit info to rewrite the stub at the specified address,
2454 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002455 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2456 startGVStub(Stub, SL.Size);
2457 mpTJI->emitFunctionStub(F, Addr, *this);
2458 finishGVStub();
2459
Zonr Chang932648d2010-10-13 22:23:56 +08002460 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2461 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002462
2463 PendingFunctions.erase(I);
2464
2465 return;
2466 }
2467
Zonr Chang932648d2010-10-13 22:23:56 +08002468 // Once you finish the compilation on a translation unit, you can call this
2469 // function to recycle the memory (which is used at compilation time and not
2470 // needed for runtime).
2471 //
2472 // NOTE: You should not call this funtion until the code-gen passes for a
2473 // given module is done. Otherwise, the results is undefined and may
2474 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002475 void releaseUnnecessary() {
2476 mMBBLocations.clear();
2477 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002478 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002479 mFunctionToLazyStubMap.clear();
2480 GlobalToIndirectSymMap.clear();
2481 ExternalFnToStubMap.clear();
2482 PendingFunctions.clear();
2483
2484 return;
2485 }
2486
2487 void reset() {
2488 releaseUnnecessary();
2489
2490 mpSymbolLookupFn = NULL;
2491 mpSymbolLookupContext = NULL;
2492
2493 mpTJI = NULL;
2494 mpTD = NULL;
2495
Zonr Chang932648d2010-10-13 22:23:56 +08002496 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2497 E = mEmittedFunctions.end();
2498 I != E;
2499 I++)
2500 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002501 delete I->second;
2502 mEmittedFunctions.clear();
2503
2504 mpMemMgr->reset();
2505
2506 return;
2507 }
2508
Zonr Chang932648d2010-10-13 22:23:56 +08002509 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002510 return lookup( llvm::StringRef(Name) );
2511 }
2512
Zonr Chang932648d2010-10-13 22:23:56 +08002513 void *lookup(const llvm::StringRef &Name) {
2514 EmittedFunctionsMapTy::const_iterator I =
2515 mEmittedFunctions.find(Name.str());
2516 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002517 return NULL;
2518 else
2519 return I->second->Code;
2520 }
2521
Zonr Chang932648d2010-10-13 22:23:56 +08002522 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002523 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002524 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002525 int functionCount = mEmittedFunctions.size();
2526
Zonr Chang932648d2010-10-13 22:23:56 +08002527 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002528 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002529 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002530 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002531 if (functions)
2532 for (EmittedFunctionsMapTy::const_iterator
2533 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2534 (I != E) && (functionCount > 0);
2535 I++, functionCount--)
2536 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002537
2538 return;
2539 }
2540
Zonr Chang932648d2010-10-13 22:23:56 +08002541 void getFunctionBinary(BCCchar *label,
2542 BCCvoid **base,
2543 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002544 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002545 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002546 *base = NULL;
2547 *length = 0;
2548 } else {
2549 *base = I->second->Code;
2550 *length = I->second->Size;
2551 }
2552 return;
2553 }
2554
2555 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002556 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002557#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002558 delete mpAsmInfo;
2559 delete mpDisassmbler;
2560 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002561#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002562 return;
2563 }
Zonr Chang932648d2010-10-13 22:23:56 +08002564 };
2565 // End of Class CodeEmitter
2566 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002567
Zonr Chang932648d2010-10-13 22:23:56 +08002568 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002569 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002570 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002571 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2572 return mCodeEmitter.get();
2573 }
2574
2575 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002576 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002577
Zonr Chang932648d2010-10-13 22:23:56 +08002578 llvm::LLVMContext *mContext;
2579 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002580
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002581 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002582
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002583 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002584 Compiler()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002585 : mUseCache(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002586 mCacheNew(false),
2587 mCacheFd(-1),
2588 mCacheMapAddr(NULL),
2589 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002590 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002591 mCacheDiff(0),
2592 mCodeDataAddr(NULL),
2593 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002594 mpSymbolLookupContext(NULL),
2595 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002596 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002597 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002598 llvm::remove_fatal_error_handler();
2599 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002600 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002601 return;
2602 }
2603
Zonr Chang932648d2010-10-13 22:23:56 +08002604 // interface for BCCscript::registerSymbolCallback()
2605 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002606 mpSymbolLookupFn = pFn;
2607 mpSymbolLookupContext = pContext;
2608 return;
2609 }
2610
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002611 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002612 GlobalInitialization();
2613 mModule = module;
2614 return hasError();
2615 }
2616
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002617 int readBC(const char *bitcode,
Loganc0b9f652010-11-24 22:33:16 +08002618 size_t bitcodeSize,
2619 const BCCchar *resName) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002620 GlobalInitialization();
2621
Loganc0b9f652010-11-24 22:33:16 +08002622 if (resName) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002623 // Turn on mUseCache mode iff
2624 // 1. Has resName
2625 // and, assuming USE_RELOCATE is false:
2626 // 2. Later running code doesn't violate the following condition:
2627 // mCodeDataAddr (set in loadCacheFile()) ==
2628 // mCacheHdr->cachedCodeDataAddr
2629 //
2630 // BTW, this condition is achievable only when in the earlier
2631 // cache-generating run,
2632 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
2633 // which means the mmap'ed is in the reserved area,
2634 //
2635 // Note: Upon violation, mUseCache will be set back to false.
2636 mUseCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002637
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002638 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2639 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2640 return -mCacheFd;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002641 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002642 }
2643
2644 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002645
Zonr Chang932648d2010-10-13 22:23:56 +08002646 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002647 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002648
Zonr Chang932648d2010-10-13 22:23:56 +08002649 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002650 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002651 llvm::StringRef(bitcode, bitcodeSize)));
2652
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002653 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002654 setError("Error reading input program bitcode into memory");
2655 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002656 }
2657
Zonr Chang932648d2010-10-13 22:23:56 +08002658 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002659 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2660 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002661 return hasError();
2662 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002663
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002664 int linkBC(const char *bitcode, size_t bitcodeSize) {
2665 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002666
2667 if (bitcode == NULL || bitcodeSize <= 0)
2668 return 0;
2669
2670 if (mModule == NULL) {
2671 setError("No module presents for linking");
2672 return hasError();
2673 }
2674
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002675 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002676 llvm::StringRef(bitcode, bitcodeSize)));
2677
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002678 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002679 setError("Error reading input library bitcode into memory");
2680 return hasError();
2681 }
2682
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002683 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002684 *mContext,
2685 &mError));
2686 if (Lib.get() == NULL)
2687 return hasError();
2688
2689 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2690 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002691
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002692 // Everything for linking should be settled down here with no error occurs
2693 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002694 return hasError();
2695 }
2696
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002697 // interface for bccLoadBinary()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002698 int loadCacheFile() {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002699 // Check File Descriptor
2700 if (mCacheFd < 0) {
2701 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2702 goto giveup;
2703 }
2704
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002705 // Check File Size
2706 struct stat statCacheFd;
2707 if (fstat(mCacheFd, &statCacheFd) < 0) {
2708 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2709 goto giveup;
2710 }
2711
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002712 mCacheSize = statCacheFd.st_size;
2713
2714 if (mCacheSize < sizeof(oBCCHeader) ||
2715 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002716 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2717 goto giveup;
2718 }
2719
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002720 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2721 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2722 goto giveup;
2723 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002724
Loganc0b9f652010-11-24 22:33:16 +08002725 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002726 {
Loganc0b9f652010-11-24 22:33:16 +08002727 // Read cached file and perform quick integrity check
2728
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002729 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002730 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
Loganad7e8e12010-11-22 20:43:43 +08002731 (unsigned int)mCacheSize,
2732 (unsigned long long int)heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002733
2734 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002735 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002736 flock(mCacheFd, LOCK_UN);
2737 LOGE("allocation failed.\n");
2738 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002739 }
2740
2741 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2742 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002743 if (nread != (size_t)heuristicCodeOffset) {
2744 LOGE("read(mCacheFd) failed\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002745 goto bail;
2746 }
2747
2748 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002749 // Sanity check
2750 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2751 LOGE("assertion failed: heuristic code offset is not correct.\n");
2752 goto bail;
2753 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002754 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2755 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2756 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2757 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2758 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002759
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002760 // Verify the Cache File
2761 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2762 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002763 goto bail;
2764 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002765
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002766 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2767 LOGE("bad oBCC version 0x%08x\n",
2768 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2769 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002770 }
2771
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002772 if (mCacheSize < mCacheHdr->relocOffset +
2773 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2774 LOGE("relocate table overflow\n");
2775 goto bail;
2776 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002777
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002778 if (mCacheSize < mCacheHdr->exportVarsOffset +
2779 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2780 LOGE("export variables table overflow\n");
2781 goto bail;
2782 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002783
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002784 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2785 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2786 LOGE("export functions table overflow\n");
2787 goto bail;
2788 }
2789
2790 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2791 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2792 LOGE("export pragmas table overflow\n");
2793 goto bail;
2794 }
2795
2796 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2797 LOGE("code cache overflow\n");
2798 goto bail;
2799 }
2800
2801 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2802 LOGE("data (global variable) cache overflow\n");
2803 goto bail;
2804 }
Loganefd637b2010-11-25 01:21:03 +08002805
2806 long pagesize = sysconf(_SC_PAGESIZE);
2807 if (mCacheHdr->codeOffset % pagesize != 0) {
2808 LOGE("code offset must aligned to pagesize\n");
2809 goto bail;
2810 }
Loganc0b9f652010-11-24 22:33:16 +08002811 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002812
Loganc0b9f652010-11-24 22:33:16 +08002813 // Part 2. Deal with the codedata section
2814 {
Loganefd637b2010-11-25 01:21:03 +08002815 long pagesize = sysconf(_SC_PAGESIZE);
Loganc0b9f652010-11-24 22:33:16 +08002816
Loganefd637b2010-11-25 01:21:03 +08002817 if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
2818 void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002819
Loganefd637b2010-11-25 01:21:03 +08002820 // Try to mmap at cached address directly.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002821 mCodeDataAddr = (char *) mmap(addr,
2822 BCC_MMAP_IMG_SIZE,
Loganefd637b2010-11-25 01:21:03 +08002823 PROT_READ | PROT_EXEC | PROT_WRITE,
2824 MAP_PRIVATE | MAP_FIXED,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002825 mCacheFd,
2826 mCacheHdr->codeOffset);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002827
Loganefd637b2010-11-25 01:21:03 +08002828 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
2829 // Cheers! Mapped at the cached address successfully.
Loganc0b9f652010-11-24 22:33:16 +08002830
Logan2ad855d2010-11-25 19:53:06 +08002831 // Update the BccMmapImgAddrTaken table (if required)
Loganefd637b2010-11-25 01:21:03 +08002832 if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
2833 size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
2834
2835 if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
2836 (offset / BCC_MMAP_IMG_SIZE) < BCC_MMAP_IMG_COUNT) {
Loganefd637b2010-11-25 01:21:03 +08002837 Compiler::BccMmapImgAddrTaken[offset / BCC_MMAP_IMG_SIZE] = true;
2838 }
Loganc0b9f652010-11-24 22:33:16 +08002839 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002840
Logan2ad855d2010-11-25 19:53:06 +08002841#if 1
2842 // Check the checksum of code and data
2843 {
2844 uint32_t sum = mCacheHdr->checksum;
2845 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
2846
2847 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
2848 sum ^= *ptr++;
2849 }
2850
2851 if (sum != 0) {
2852 LOGE("Checksum check failed\n");
2853 goto bail;
2854 }
Logan9f6a10d2010-11-25 23:40:47 +08002855
2856 LOGE("Passed checksum even parity verification.\n");
Logan2ad855d2010-11-25 19:53:06 +08002857 }
2858#endif
2859
Loganefd637b2010-11-25 01:21:03 +08002860 flock(mCacheFd, LOCK_UN);
2861 return 0; // loadCacheFile succeed!
2862 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002863 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002864 }
2865
Loganc0b9f652010-11-24 22:33:16 +08002866#if !USE_RELOCATE
2867 // Note: Since this build does not support relocation, we have no
2868 // choose but give up to load the cached file, and recompile the
2869 // code.
2870
2871 flock(mCacheFd, LOCK_UN);
2872 goto bail;
2873#else
2874
2875 // Note: Currently, relocation code is not working. Give up now.
2876 flock(mCacheFd, LOCK_UN);
2877 goto bail;
2878
2879 // TODO(logan): Following code is not working. Don't use them.
2880 // And rewrite them asap.
2881#if 0
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002882 {
Loganc0b9f652010-11-24 22:33:16 +08002883 // Try to allocate at arbitary address. And perform relocation.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002884 mCacheMapAddr = (char *) mmap(0,
2885 mCacheSize,
Loganc0b9f652010-11-24 22:33:16 +08002886 PROT_READ | PROT_EXEC | PROT_WRITE,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002887 MAP_PRIVATE,
2888 mCacheFd,
2889 0);
Loganc0b9f652010-11-24 22:33:16 +08002890
2891 if (mCacheMapAddr == MAP_FAILED) {
2892 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2893 flock(mCacheFd, LOCK_UN);
2894 goto giveup;
2895 }
2896
2897 flock(mCacheFd, LOCK_UN);
2898 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2899
2900 // Relocate
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002901 mCacheDiff = mCodeDataAddr -
2902 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2903
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002904 if (mCacheDiff) { // To relocate
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002905 if (mCacheHdr->rootAddr) {
2906 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002907 }
2908
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002909 if (mCacheHdr->initAddr) {
2910 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002911 }
2912
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002913 oBCCRelocEntry *cachedRelocTable =
2914 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2915 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002916
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002917 std::vector<llvm::MachineRelocation> relocations;
2918
2919 // Read in the relocs
2920 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2921 oBCCRelocEntry *entry = &cachedRelocTable[i];
2922
2923 llvm::MachineRelocation reloc =
2924 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2925 (unsigned)entry->relocType, 0, 0);
2926
2927 reloc.setResultPointer(
2928 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2929
2930 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002931 }
2932
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002933 // Rewrite machine code using llvm::TargetJITInfo relocate
2934 {
2935 llvm::TargetMachine *TM = NULL;
2936 const llvm::Target *Target;
2937 std::string FeaturesStr;
2938
2939 // Create TargetMachine
2940 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2941 if (hasError())
2942 goto bail;
2943
2944 if (!CPU.empty() || !Features.empty()) {
2945 llvm::SubtargetFeatures F;
2946 F.setCPU(CPU);
2947 for (std::vector<std::string>::const_iterator I = Features.begin(),
2948 E = Features.end(); I != E; I++)
2949 F.AddFeature(*I);
2950 FeaturesStr = F.getString();
2951 }
2952
2953 TM = Target->createTargetMachine(Triple, FeaturesStr);
2954 if (TM == NULL) {
2955 setError("Failed to create target machine implementation for the"
2956 " specified triple '" + Triple + "'");
2957 goto bail;
2958 }
2959
2960 TM->getJITInfo()->relocate(mCodeDataAddr,
2961 &relocations[0], relocations.size(),
2962 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2963
2964 if (mCodeEmitter.get()) {
2965 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2966 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2967 2 * 1024 /*MaxCodeSize*/,
2968 false);
2969 }
2970
2971 delete TM;
2972 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002973 } // End of if (mCacheDiff)
Loganc0b9f652010-11-24 22:33:16 +08002974
2975 return 0; // Success!
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002976 }
Loganc0b9f652010-11-24 22:33:16 +08002977#endif
2978#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002979
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002980 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002981 if (mCacheMapAddr) {
2982 free(mCacheMapAddr);
2983 }
Loganad7e8e12010-11-22 20:43:43 +08002984
Loganc0b9f652010-11-24 22:33:16 +08002985 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +08002986 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
Loganc0b9f652010-11-24 22:33:16 +08002987 LOGE("munmap failed: %s\n", strerror(errno));
2988 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002989 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002990
Logan43830d52010-11-25 19:27:29 +08002991 mCacheMapAddr = NULL;
2992 mCacheHdr = NULL;
2993 mCodeDataAddr = NULL;
Logan82e67012010-11-25 00:29:34 +08002994
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002995 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002996 return 1;
2997 }
2998
2999 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003000 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08003001 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003002
Zonr Chang932648d2010-10-13 22:23:56 +08003003 llvm::TargetMachine *TM = NULL;
3004 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003005 std::string FeaturesStr;
3006
Zonr Chang932648d2010-10-13 22:23:56 +08003007 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003008
Zonr Chang932648d2010-10-13 22:23:56 +08003009 const llvm::NamedMDNode *PragmaMetadata;
3010 const llvm::NamedMDNode *ExportVarMetadata;
3011 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003012
Zonr Chang932648d2010-10-13 22:23:56 +08003013 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003014 return 0;
3015
Zonr Chang932648d2010-10-13 22:23:56 +08003016 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003017 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08003018 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003019 goto on_bcc_compile_error;
3020
Zonr Chang932648d2010-10-13 22:23:56 +08003021 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003022 llvm::SubtargetFeatures F;
3023 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08003024 for (std::vector<std::string>::const_iterator I = Features.begin(),
3025 E = Features.end();
3026 I != E;
3027 I++)
3028 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003029 FeaturesStr = F.getString();
3030 }
3031
3032 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08003033 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003034 setError("Failed to create target machine implementation for the"
3035 " specified triple '" + Triple + "'");
3036 goto on_bcc_compile_error;
3037 }
3038
Zonr Chang932648d2010-10-13 22:23:56 +08003039 // Create memory manager for creation of code emitter later.
3040 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003041 setError("Failed to startup memory management for further compilation");
3042 goto on_bcc_compile_error;
3043 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003044 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003045
Zonr Chang932648d2010-10-13 22:23:56 +08003046 // Create code emitter
3047 if (!mCodeEmitter.get()) {
3048 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003049 setError("Failed to create machine code emitter to complete"
3050 " the compilation");
3051 goto on_bcc_compile_error;
3052 }
3053 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08003054 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003055 mCodeEmitter->reset();
3056 }
3057
3058 mCodeEmitter->setTargetMachine(*TM);
3059 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
3060 mpSymbolLookupContext);
3061
Zonr Chang932648d2010-10-13 22:23:56 +08003062 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003063 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003064
Zonr Chang5d35b972010-10-23 14:36:47 +08003065 // Load named metadata
3066 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
3067 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
3068 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
3069
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003070 // Create LTO passes and run them on the mModule
3071 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003072 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003073 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08003074 LTOPasses.add(new llvm::TargetData(*TD));
3075
3076 std::vector<const char*> ExportSymbols;
3077
3078 // A workaround for getting export variable and function name. Will refine
3079 // it soon.
3080 if (ExportVarMetadata) {
3081 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3082 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3083 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3084 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3085 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
3086 llvm::StringRef ExportVarName =
3087 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
3088 ExportSymbols.push_back(ExportVarName.data());
3089 }
3090 }
3091 }
3092 }
3093
3094 if (ExportFuncMetadata) {
3095 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3096 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3097 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3098 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3099 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
3100 llvm::StringRef ExportFuncName =
3101 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3102 ExportSymbols.push_back(ExportFuncName.data());
3103 }
3104 }
3105 }
3106 }
3107 // root() and init() are born to be exported
3108 ExportSymbols.push_back("root");
3109 ExportSymbols.push_back("init");
3110
Zonr Change5c7a542010-10-24 01:07:27 +08003111 // We now create passes list performing LTO. These are copied from
3112 // (including comments) llvm::createStandardLTOPasses().
3113
3114 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08003115 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003116
Zonr Change5c7a542010-10-24 01:07:27 +08003117 // Propagate constants at call sites into the functions they call. This
3118 // opens opportunities for globalopt (and inlining) by substituting
3119 // function pointers passed as arguments to direct uses of functions.
3120 LTOPasses.add(llvm::createIPSCCPPass());
3121
3122 // Now that we internalized some globals, see if we can hack on them!
3123 LTOPasses.add(llvm::createGlobalOptimizerPass());
3124
3125 // Linking modules together can lead to duplicated global constants, only
3126 // keep one copy of each constant...
3127 LTOPasses.add(llvm::createConstantMergePass());
3128
3129 // Remove unused arguments from functions...
3130 LTOPasses.add(llvm::createDeadArgEliminationPass());
3131
3132 // Reduce the code after globalopt and ipsccp. Both can open up
3133 // significant simplification opportunities, and both can propagate
3134 // functions through function pointers. When this happens, we often have
3135 // to resolve varargs calls, etc, so let instcombine do this.
3136 LTOPasses.add(llvm::createInstructionCombiningPass());
3137
3138 // Inline small functions
3139 LTOPasses.add(llvm::createFunctionInliningPass());
3140
3141 // Remove dead EH info.
3142 LTOPasses.add(llvm::createPruneEHPass());
3143
3144 // Internalize the globals again after inlining
3145 LTOPasses.add(llvm::createGlobalOptimizerPass());
3146
3147 // Remove dead functions.
3148 LTOPasses.add(llvm::createGlobalDCEPass());
3149
3150 // If we didn't decide to inline a function, check to see if we can
3151 // transform it to pass arguments by value instead of by reference.
3152 LTOPasses.add(llvm::createArgumentPromotionPass());
3153
3154 // The IPO passes may leave cruft around. Clean up after them.
3155 LTOPasses.add(llvm::createInstructionCombiningPass());
3156 LTOPasses.add(llvm::createJumpThreadingPass());
3157
3158 // Break up allocas
3159 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3160
3161 // Run a few AA driven optimizations here and now, to cleanup the code.
3162 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3163 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3164
3165 // Hoist loop invariants.
3166 LTOPasses.add(llvm::createLICMPass());
3167
3168 // Remove redundancies.
3169 LTOPasses.add(llvm::createGVNPass());
3170
3171 // Remove dead memcpys.
3172 LTOPasses.add(llvm::createMemCpyOptPass());
3173
3174 // Nuke dead stores.
3175 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3176
3177 // Cleanup and simplify the code after the scalar optimizations.
3178 LTOPasses.add(llvm::createInstructionCombiningPass());
3179
3180 LTOPasses.add(llvm::createJumpThreadingPass());
3181
3182 // Delete basic blocks, which optimization passes may have killed.
3183 LTOPasses.add(llvm::createCFGSimplificationPass());
3184
3185 // Now that we have optimized the program, discard unreachable functions.
3186 LTOPasses.add(llvm::createGlobalDCEPass());
3187
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003188 LTOPasses.run(*mModule);
3189 }
3190
Zonr Chang932648d2010-10-13 22:23:56 +08003191 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003192 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003193 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003194
Zonr Chang932648d2010-10-13 22:23:56 +08003195 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3196 *mCodeEmitter,
3197 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003198 setError("The machine code emission is not supported by BCC on target '"
3199 + Triple + "'");
3200 goto on_bcc_compile_error;
3201 }
3202
Zonr Chang932648d2010-10-13 22:23:56 +08003203 // Run the pass (the code emitter) on every non-declaration function in the
3204 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003205 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003206 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3207 I != E;
3208 I++)
3209 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003210 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003211
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003212 CodeGenPasses->doFinalization();
3213
Zonr Chang932648d2010-10-13 22:23:56 +08003214 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003215 if (ExportVarMetadata) {
3216 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3217 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3218 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3219 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3220 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003221 llvm::StringRef ExportVarName =
3222 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003223 CodeEmitter::global_addresses_const_iterator I, E;
3224 for (I = mCodeEmitter->global_address_begin(),
3225 E = mCodeEmitter->global_address_end();
3226 I != E;
3227 I++) {
3228 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003229 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003230 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003231 mExportVars.push_back(I->second);
3232 break;
3233 }
3234 }
Zonr Chang932648d2010-10-13 22:23:56 +08003235 if (I != mCodeEmitter->global_address_end())
3236 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003237 }
3238 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003239 // if reaching here, we know the global variable record in metadata is
3240 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003241 mExportVars.push_back(NULL);
3242 }
3243 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3244 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003245 }
3246
Zonr Chang932648d2010-10-13 22:23:56 +08003247 if (ExportFuncMetadata) {
3248 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3249 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3250 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3251 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3252 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003253 llvm::StringRef ExportFuncName =
3254 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3255 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3256 }
3257 }
3258 }
3259 }
3260
Zonr Chang932648d2010-10-13 22:23:56 +08003261 // Tell code emitter now can release the memory using during the JIT since
3262 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003263 mCodeEmitter->releaseUnnecessary();
3264
Zonr Chang932648d2010-10-13 22:23:56 +08003265 // Finally, read pragma information from the metadata node of the @Module if
3266 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003267 if (PragmaMetadata)
3268 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3269 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3270 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003271 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003272 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3273 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003274
Zonr Chang932648d2010-10-13 22:23:56 +08003275 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003276 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3277 llvm::StringRef PragmaName =
3278 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3279 llvm::StringRef PragmaValue =
3280 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3281
Zonr Chang932648d2010-10-13 22:23:56 +08003282 mPragmas.push_back(
3283 std::make_pair(std::string(PragmaName.data(),
3284 PragmaName.size()),
3285 std::string(PragmaValue.data(),
3286 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003287 }
3288 }
3289 }
3290
3291 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003292 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003293 if (CodeGenPasses) {
3294 delete CodeGenPasses;
3295 } else if (TD) {
3296 delete TD;
3297 }
3298 if (TM)
3299 delete TM;
3300
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003301 if (mError.empty()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003302 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003303 genCacheFile();
3304 flock(mCacheFd, LOCK_UN);
3305 }
Loganc0b9f652010-11-24 22:33:16 +08003306
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003307 return false;
3308 }
3309
Zonr Chang932648d2010-10-13 22:23:56 +08003310 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003311 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003312 }
3313
Zonr Chang932648d2010-10-13 22:23:56 +08003314 // interface for bccGetScriptInfoLog()
3315 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003316 return const_cast<char*>(mError.c_str());
3317 }
3318
Zonr Chang932648d2010-10-13 22:23:56 +08003319 // interface for bccGetScriptLabel()
3320 void *lookup(const char *name) {
3321 void *addr = NULL;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003322 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003323 if (!strcmp(name, "root")) {
3324 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3325 } else if (!strcmp(name, "init")) {
3326 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3327 }
3328 return addr;
3329 }
3330
Zonr Chang932648d2010-10-13 22:23:56 +08003331 if (mCodeEmitter.get())
3332 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003333 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003334 return addr;
3335 }
3336
Zonr Chang932648d2010-10-13 22:23:56 +08003337 // Interface for bccGetExportVars()
3338 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003339 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003340 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003341 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003342
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003343 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003344 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3345 if (actualVarCount)
3346 *actualVarCount = varCount;
3347 if (varCount > maxVarCount)
3348 varCount = maxVarCount;
3349 if (vars) {
3350 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3351 mCacheHdr->exportVarsOffset);
3352
3353 for (int i = 0; i < varCount; i++) {
3354 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3355 mCacheDiff);
3356 cachedVars++;
3357 }
3358 }
3359 return;
3360 }
3361
3362 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003363 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003364 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003365 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003366 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003367 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003368 for (ExportVarList::const_iterator I = mExportVars.begin(),
3369 E = mExportVars.end();
3370 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003371 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003372 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003373 }
3374 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003375
3376 return;
3377 }
3378
Zonr Chang932648d2010-10-13 22:23:56 +08003379 // Interface for bccGetExportFuncs()
3380 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003381 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003382 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003383 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003384
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003385 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003386 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3387 if (actualFuncCount)
3388 *actualFuncCount = funcCount;
3389 if (funcCount > maxFuncCount)
3390 funcCount = maxFuncCount;
3391 if (funcs) {
3392 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3393 mCacheHdr->exportFuncsOffset);
3394
3395 for (int i = 0; i < funcCount; i++) {
3396 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3397 mCacheDiff);
3398 cachedFuncs++;
3399 }
3400 }
3401 return;
3402 }
3403
3404 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003405 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003406 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003407 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003408 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003409 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003410 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3411 E = mExportFuncs.end();
3412 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003413 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003414 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003415 }
3416 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003417
3418 return;
3419 }
3420
Zonr Chang932648d2010-10-13 22:23:56 +08003421 // Interface for bccGetPragmas()
3422 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003423 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003424 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003425 int stringCount;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003426 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003427 if (actualStringCount)
3428 *actualStringCount = 0; // XXX
3429 return;
3430 }
3431
3432 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003433
Zonr Chang932648d2010-10-13 22:23:56 +08003434 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003435 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003436 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003437 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003438 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003439 for (PragmaList::const_iterator it = mPragmas.begin();
3440 stringCount > 0;
3441 stringCount -= 2, it++) {
3442 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3443 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003444 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003445 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003446
3447 return;
3448 }
3449
Zonr Chang932648d2010-10-13 22:23:56 +08003450 // Interface for bccGetFunctions()
3451 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003452 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003453 BCCchar **functions) {
3454 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003455 mCodeEmitter->getFunctionNames(actualFunctionCount,
3456 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003457 functions);
3458 else
3459 *actualFunctionCount = 0;
3460
3461 return;
3462 }
3463
Zonr Chang932648d2010-10-13 22:23:56 +08003464 // Interface for bccGetFunctionBinary()
3465 void getFunctionBinary(BCCchar *function,
3466 BCCvoid **base,
3467 BCCsizei *length) {
3468 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003469 mCodeEmitter->getFunctionBinary(function, base, length);
3470 } else {
3471 *base = NULL;
3472 *length = 0;
3473 }
3474 return;
3475 }
3476
Zonr Chang932648d2010-10-13 22:23:56 +08003477 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003478 return mModule;
3479 }
3480
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003481 ~Compiler() {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003482 if (!mCodeMemMgr.get()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003483 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003484 // managed by CodeMemoryManager.
3485
3486 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +08003487 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003488 LOGE("munmap failed while releasing mCodeDataAddr\n");
3489 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003490 }
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003491
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003492 if (mCacheMapAddr) {
3493 free(mCacheMapAddr);
3494 }
Logan82e67012010-11-25 00:29:34 +08003495
3496 mCodeDataAddr = 0;
3497 mCacheMapAddr = 0;
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003498 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003499
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003500 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003501 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003502 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003503 return;
3504 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003505
3506 private:
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003507 // Note: loadCacheFile() and genCacheFile() go hand in hand
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003508 void genCacheFile() {
3509 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3510 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3511 return;
3512 }
3513
3514 bool codeOffsetNeedPadding = false;
3515
3516 uint32_t offset = sizeof(oBCCHeader);
3517
3518 // BCC Cache File Header
3519 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3520
3521 if (!hdr) {
3522 LOGE("Unable to allocate oBCCHeader.\n");
3523 return;
3524 }
3525
3526 // Magic Words
3527 memcpy(hdr->magic, OBCC_MAGIC, 4);
3528 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3529
3530 // Timestamp
3531 hdr->sourceWhen = 0; // TODO(all)
3532 hdr->rslibWhen = 0; // TODO(all)
3533 hdr->libRSWhen = 0; // TODO(all)
3534 hdr->libbccWhen = 0; // TODO(all)
3535
3536 // Current Memory Address (Saved for Recalculation)
3537 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3538 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3539 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3540
3541 // Relocation Table Offset and Entry Count
3542 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003543 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003544
Logan824dd0a2010-11-20 01:45:54 +08003545 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003546
3547 // Export Variable Table Offset and Entry Count
3548 hdr->exportVarsOffset = offset;
3549 hdr->exportVarsCount = mExportVars.size();
3550
3551 offset += hdr->exportVarsCount * sizeof(uint32_t);
3552
3553 // Export Function Table Offset and Entry Count
3554 hdr->exportFuncsOffset = offset;
3555 hdr->exportFuncsCount = mExportFuncs.size();
3556
3557 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3558
3559 // Export Pragmas Table Offset and Entry Count
3560 hdr->exportPragmasOffset = offset;
3561 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3562
3563 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3564
3565 // Code Offset and Size
3566
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003567 //#ifdef BCC_CODE_ADDR
3568 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003569 long pagesize = sysconf(_SC_PAGESIZE);
3570
3571 if (offset % pagesize > 0) {
3572 codeOffsetNeedPadding = true;
3573 offset += pagesize - (offset % pagesize);
3574 }
3575 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003576 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003577 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3578 codeOffsetNeedPadding = true;
3579 offset += 0x08 - (offset & 0x07);
3580 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003581 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003582
3583 hdr->codeOffset = offset;
3584 hdr->codeSize = MaxCodeSize;
3585
3586 offset += hdr->codeSize;
3587
3588 // Data (Global Variable) Offset and Size
3589 hdr->dataOffset = offset;
3590 hdr->dataSize = MaxGlobalVarSize;
3591
3592 offset += hdr->dataSize;
3593
3594 // Checksum
Logan2ad855d2010-11-25 19:53:06 +08003595#if 1
3596 {
3597 // Note: This is an simple checksum implementation that are using xor
3598 // to calculate even parity (for code and data only).
3599
3600 uint32_t sum = 0;
3601 uint32_t *ptr = (uint32_t *)mCodeDataAddr;
3602
3603 for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
3604 sum ^= *ptr++;
3605 }
3606
3607 hdr->checksum = sum;
3608 }
3609#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003610 hdr->checksum = 0; // Set Field checksum. TODO(all)
Logan2ad855d2010-11-25 19:53:06 +08003611#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003612
3613 // Write Header
3614 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3615 sizeof(oBCCHeader), "Write oBCC header");
3616
Logan824dd0a2010-11-20 01:45:54 +08003617 // Write Relocation Entry Table
3618 {
3619 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003620
Logan824dd0a2010-11-20 01:45:54 +08003621 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3622
3623 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3624 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003625 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003626
3627 // Write Export Variables Table
3628 {
3629 uint32_t *record, *ptr;
3630
3631 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3632 ptr = record;
3633
3634 if (!record) {
3635 goto bail;
3636 }
3637
3638 for (ExportVarList::const_iterator I = mExportVars.begin(),
3639 E = mExportVars.end(); I != E; I++) {
3640 *ptr++ = reinterpret_cast<uint32_t>(*I);
3641 }
3642
3643 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3644 hdr->exportVarsCount * sizeof(uint32_t),
3645 "Write ExportVars");
3646
3647 free(record);
3648 }
3649
3650 // Write Export Functions Table
3651 {
3652 uint32_t *record, *ptr;
3653
3654 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3655 ptr = record;
3656
3657 if (!record) {
3658 goto bail;
3659 }
3660
3661 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3662 E = mExportFuncs.end(); I != E; I++) {
3663 *ptr++ = reinterpret_cast<uint32_t>(*I);
3664 }
3665
3666 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3667 hdr->exportFuncsCount * sizeof(uint32_t),
3668 "Write ExportFuncs");
3669
3670 free(record);
3671 }
3672
3673
3674 // TODO(all): Write Export Pragmas Table
3675#if 0
3676#else
3677 // Note: As long as we have comment out export pragmas table code,
3678 // we have to seek the position to correct offset.
3679
3680 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3681#endif
3682
3683 if (codeOffsetNeedPadding) {
3684 // requires additional padding
3685 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3686 }
3687
3688 // Write Generated Code and Global Variable
3689 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3690 "Write code and global variable");
3691
3692 goto close_return;
3693
3694 bail:
3695 if (ftruncate(mCacheFd, 0) != 0) {
3696 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3697 }
3698
3699 close_return:
3700 free(hdr);
3701 close(mCacheFd);
3702 mCacheFd = -1;
3703 return;
3704 }
3705
3706 // OpenCacheFile() returns fd of the cache file.
3707 // Input:
3708 // BCCchar *resName: Used to genCacheFileName()
3709 // bool createIfMissing: If false, turn off caching
3710 // Output:
3711 // returns fd: If -1: Failed
3712 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3713 // cache file's file descriptor
3714 // Note: openCacheFile() will check the cache file's validity,
3715 // such as Magic number, sourceWhen... dependencies.
3716 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3717 int fd, cc;
3718 struct stat fdStat, fileStat;
3719 bool readOnly = false;
3720
3721 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3722
3723 mCacheNew = false;
3724
3725 retry:
3726 /*
3727 * Try to open the cache file. If we've been asked to,
3728 * create it if it doesn't exist.
3729 */
3730 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3731 if (fd < 0) {
3732 fd = open(cacheFileName, O_RDONLY, 0);
3733 if (fd < 0) {
3734 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08003735 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003736 cacheFileName, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003737 mUseCache = false;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003738 }
3739 return fd;
3740 }
3741 readOnly = true;
3742 }
3743
3744 /*
3745 * Grab an exclusive lock on the cache file. If somebody else is
3746 * working on it, we'll block here until they complete.
3747 */
3748 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3749 cacheFileName, fd);
3750
3751 cc = flock(fd, LOCK_EX | LOCK_NB);
3752 if (cc != 0) {
3753 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3754 cc = flock(fd, LOCK_EX);
3755 }
3756
3757 if (cc != 0) {
3758 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3759 close(fd);
3760 return -1;
3761 }
3762 LOGV("bcc: locked cache file\n");
3763
3764 /*
3765 * Check to see if the fd we opened and locked matches the file in
3766 * the filesystem. If they don't, then somebody else unlinked ours
3767 * and created a new file, and we need to use that one instead. (If
3768 * we caught them between the unlink and the create, we'll get an
3769 * ENOENT from the file stat.)
3770 */
3771 cc = fstat(fd, &fdStat);
3772 if (cc != 0) {
3773 LOGE("Can't stat open file '%s'\n", cacheFileName);
3774 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3775 goto close_fail;
3776 }
3777 cc = stat(cacheFileName, &fileStat);
3778 if (cc != 0 ||
3779 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3780 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3781 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3782 flock(fd, LOCK_UN);
3783 close(fd);
3784 usleep(250 * 1000); // if something is hosed, don't peg machine
3785 goto retry;
3786 }
3787
3788 /*
3789 * We have the correct file open and locked. If the file size is zero,
3790 * then it was just created by us, and we want to fill in some fields
3791 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3792 * verify that the fields in the header match our expectations, and
3793 * reset the file if they don't.
3794 */
3795 if (fdStat.st_size == 0) {
3796 if (readOnly) { // The device is readOnly --> close_fail
3797 LOGW("bcc: file has zero length and isn't writable\n");
3798 goto close_fail;
3799 }
3800 /*cc = createEmptyHeader(fd);
3801 if (cc != 0)
3802 goto close_fail;
3803 */
3804 mCacheNew = true;
3805 LOGV("bcc: successfully initialized new cache file\n");
3806 } else {
3807 // Calculate sourceWhen
3808 // XXX
3809 uint32_t sourceWhen = 0;
3810 uint32_t rslibWhen = 0;
3811 uint32_t libRSWhen = 0;
3812 uint32_t libbccWhen = 0;
3813 if (!checkHeaderAndDependencies(fd,
3814 sourceWhen,
3815 rslibWhen,
3816 libRSWhen,
3817 libbccWhen)) {
3818 // If checkHeaderAndDependencies returns 0: FAILED
3819 // Will truncate the file and retry to createIfMissing the file
3820
3821 if (readOnly) { // Shouldn't be readonly.
3822 /*
3823 * We could unlink and rewrite the file if we own it or
3824 * the "sticky" bit isn't set on the directory. However,
3825 * we're not able to truncate it, which spoils things. So,
3826 * give up now.
3827 */
3828 if (createIfMissing) {
3829 LOGW("Cached file %s is stale and not writable\n",
3830 cacheFileName);
3831 }
3832 goto close_fail;
3833 }
3834
3835 /*
3836 * If we truncate the existing file before unlinking it, any
3837 * process that has it mapped will fail when it tries to touch
3838 * the pages? Probably OK because we use MAP_PRIVATE.
3839 */
3840 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3841 cacheFileName);
3842 if (ftruncate(fd, 0) != 0) {
3843 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3844 cacheFileName, strerror(errno));
3845 /* keep going */
3846 }
3847 if (unlink(cacheFileName) != 0) {
3848 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3849 cacheFileName, errno, strerror(errno));
3850 /* keep going; permission failure should probably be fatal */
3851 }
3852 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3853 flock(fd, LOCK_UN);
3854 close(fd);
3855 goto retry;
3856 } else {
3857 // Got cacheFile! Good to go.
3858 LOGV("Good cache file\n");
3859 }
3860 }
3861
3862 assert(fd >= 0);
3863 return fd;
3864
3865 close_fail:
3866 flock(fd, LOCK_UN);
3867 close(fd);
3868 return -1;
3869 } // End of openCacheFile()
3870
3871 char *genCacheFileName(const char *fileName, const char *subFileName) {
3872 char nameBuf[512];
3873 static const char kCachePath[] = "bcc-cache";
3874 char absoluteFile[sizeof(nameBuf)];
3875 const size_t kBufLen = sizeof(nameBuf) - 1;
3876 const char *dataRoot;
3877 char *cp;
3878
3879 // Get the absolute path of the raw/***.bc file.
3880 absoluteFile[0] = '\0';
3881 if (fileName[0] != '/') {
3882 /*
3883 * Generate the absolute path. This doesn't do everything it
3884 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3885 * the leading "./" out, but it'll do.
3886 */
3887 if (getcwd(absoluteFile, kBufLen) == NULL) {
3888 LOGE("Can't get CWD while opening raw/***.bc file\n");
3889 return NULL;
3890 }
3891 // TODO(srhines): strncat() is a bit dangerous
3892 strncat(absoluteFile, "/", kBufLen);
3893 }
3894 strncat(absoluteFile, fileName, kBufLen);
3895
3896 if (subFileName != NULL) {
3897 strncat(absoluteFile, "/", kBufLen);
3898 strncat(absoluteFile, subFileName, kBufLen);
3899 }
3900
3901 /* Turn the path into a flat filename by replacing
3902 * any slashes after the first one with '@' characters.
3903 */
3904 cp = absoluteFile + 1;
3905 while (*cp != '\0') {
3906 if (*cp == '/') {
3907 *cp = '@';
3908 }
3909 cp++;
3910 }
3911
3912 /* Build the name of the cache directory.
3913 */
3914 dataRoot = getenv("ANDROID_DATA");
3915 if (dataRoot == NULL)
3916 dataRoot = "/data";
3917 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3918
3919 /* Tack on the file name for the actual cache file path.
3920 */
3921 strncat(nameBuf, absoluteFile, kBufLen);
3922
3923 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3924 return strdup(nameBuf);
3925 }
3926
3927 /*
3928 * Read the oBCC header, verify it, then read the dependent section
3929 * and verify that data as well.
3930 *
3931 * On successful return, the file will be seeked immediately past the
3932 * oBCC header.
3933 */
3934 bool checkHeaderAndDependencies(int fd,
3935 uint32_t sourceWhen,
3936 uint32_t rslibWhen,
3937 uint32_t libRSWhen,
3938 uint32_t libbccWhen) {
3939 ssize_t actual;
3940 oBCCHeader optHdr;
3941 uint32_t val;
3942 uint8_t const *magic, *magicVer;
3943
3944 /*
3945 * Start at the start. The "bcc" header, when present, will always be
3946 * the first thing in the file.
3947 */
3948 if (lseek(fd, 0, SEEK_SET) != 0) {
3949 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3950 goto bail;
3951 }
3952
3953 /*
3954 * Read and do trivial verification on the bcc header. The header is
3955 * always in host byte order.
3956 */
3957 actual = read(fd, &optHdr, sizeof(optHdr));
3958 if (actual < 0) {
3959 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3960 goto bail;
3961 } else if (actual != sizeof(optHdr)) {
3962 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3963 (int) actual, sizeof(optHdr));
3964 goto bail;
3965 }
3966
3967 magic = optHdr.magic;
3968 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3969 /* not an oBCC file, or previous attempt was interrupted */
3970 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3971 magic[0], magic[1], magic[2], magic[3]);
3972 goto bail;
3973 }
3974
3975 magicVer = optHdr.magicVersion;
3976 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3977 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3978 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3979 goto bail;
3980 }
3981
3982 /*
3983 * Do the header flags match up with what we want?
3984 *
3985 * This is useful because it allows us to automatically regenerate
3986 * a file when settings change (e.g. verification is now mandatory),
3987 * but can cause difficulties if the thing we depend upon
3988 * were handled differently than the current options specify.
3989 *
3990 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3991 * by limiting the match mask.
3992 *
3993 * The only thing we really can't handle is incorrect byte-ordering.
3994 */
3995
3996 val = optHdr.sourceWhen;
3997 if (val && (val != sourceWhen)) {
3998 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3999 val, sourceWhen);
4000 goto bail;
4001 }
4002 val = optHdr.rslibWhen;
4003 if (val && (val != rslibWhen)) {
4004 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
4005 val, rslibWhen);
4006 goto bail;
4007 }
4008 val = optHdr.libRSWhen;
4009 if (val && (val != libRSWhen)) {
4010 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
4011 val, libRSWhen);
4012 goto bail;
4013 }
4014 val = optHdr.libbccWhen;
4015 if (val && (val != libbccWhen)) {
4016 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
4017 val, libbccWhen);
4018 goto bail;
4019 }
4020
4021 return true;
4022
4023 bail:
4024 return false;
4025 }
4026
Zonr Chang932648d2010-10-13 22:23:56 +08004027};
4028// End of Class Compiler
4029////////////////////////////////////////////////////////////////////////////////
4030
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004031
4032bool Compiler::GlobalInitialized = false;
4033
Loganc0b9f652010-11-24 22:33:16 +08004034bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Loganad7e8e12010-11-22 20:43:43 +08004035
Zonr Chang932648d2010-10-13 22:23:56 +08004036// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004037llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
4038
4039std::string Compiler::Triple;
4040
4041std::string Compiler::CPU;
4042
4043std::vector<std::string> Compiler::Features;
4044
Zonr Chang932648d2010-10-13 22:23:56 +08004045// The named of metadata node that pragma resides (should be synced with
4046// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004047const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
4048
Zonr Chang932648d2010-10-13 22:23:56 +08004049// The named of metadata node that export variable name resides (should be
4050// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004051const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
4052
Zonr Chang932648d2010-10-13 22:23:56 +08004053// The named of metadata node that export function name resides (should be
4054// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004055const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
4056
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004057struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08004058 //////////////////////////////////////////////////////////////////////////////
4059 // Part I. Compiler
4060 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004061 Compiler compiler;
4062
Zonr Chang932648d2010-10-13 22:23:56 +08004063 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004064 compiler.registerSymbolCallback(pFn, pContext);
4065 }
4066
Zonr Chang932648d2010-10-13 22:23:56 +08004067 //////////////////////////////////////////////////////////////////////////////
4068 // Part II. Logistics & Error handling
4069 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004070 BCCscript() {
4071 bccError = BCC_NO_ERROR;
4072 }
4073
4074 ~BCCscript() {
4075 }
4076
4077 void setError(BCCenum error) {
4078 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
4079 bccError = error;
4080 }
4081 }
4082
4083 BCCenum getError() {
4084 BCCenum result = bccError;
4085 bccError = BCC_NO_ERROR;
4086 return result;
4087 }
4088
4089 BCCenum bccError;
4090};
4091
4092
4093extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004094BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004095 return new BCCscript();
4096}
4097
4098extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004099BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004100 return script->getError();
4101}
4102
4103extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004104void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004105 delete script;
4106}
4107
4108extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004109void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004110 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08004111 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004112 script->registerSymbolCallback(pFn, pContext);
4113}
4114
4115extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004116int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08004117 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004118 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08004119}
4120
4121extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004122int bccReadBC(BCCscript *script,
4123 const BCCchar *bitcode,
4124 BCCint size,
4125 const BCCchar *resName) {
4126 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004127}
4128
4129extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004130void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08004131 const BCCchar *bitcode,
4132 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004133 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08004134}
4135
4136extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004137void bccLoadBinary(BCCscript *script) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08004138 int result = script->compiler.loadCacheFile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004139 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004140 script->setError(BCC_INVALID_OPERATION);
4141}
4142
4143extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004144void bccCompileBC(BCCscript *script) {
4145 {
4146#if defined(__arm__)
4147 android::StopWatch compileTimer("RenderScript compile time");
4148#endif
4149 int result = script->compiler.compile();
4150 if (result)
4151 script->setError(BCC_INVALID_OPERATION);
4152 }
4153}
4154
4155extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004156void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004157 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08004158 BCCsizei *length,
4159 BCCchar *infoLog) {
4160 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004161 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004162 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004163 *length = messageLength;
4164
4165 if (infoLog && maxLength > 0) {
4166 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4167 memcpy(infoLog, message, trimmedLength);
4168 infoLog[trimmedLength] = 0;
4169 }
4170}
4171
4172extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004173void bccGetScriptLabel(BCCscript *script,
4174 const BCCchar *name,
4175 BCCvoid **address) {
4176 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004177 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004178 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004179 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004180 script->setError(BCC_INVALID_VALUE);
4181}
4182
4183extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004184void bccGetExportVars(BCCscript *script,
4185 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004186 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004187 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004188 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4189}
4190
4191extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004192void bccGetExportFuncs(BCCscript *script,
4193 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004194 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004195 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004196 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4197}
4198
4199extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004200void bccGetPragmas(BCCscript *script,
4201 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004202 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004203 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004204 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4205}
4206
4207extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004208void bccGetFunctions(BCCscript *script,
4209 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004210 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004211 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004212 script->compiler.getFunctions(actualFunctionCount,
4213 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004214 functions);
4215}
4216
4217extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004218void bccGetFunctionBinary(BCCscript *script,
4219 BCCchar *function,
4220 BCCvoid **base,
4221 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004222 script->compiler.getFunctionBinary(function, base, length);
4223}
4224
4225struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004226 const Compiler *compiler;
4227 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004228};
4229
Zonr Chang932648d2010-10-13 22:23:56 +08004230} // namespace bcc