blob: 9235601b8fba0abd93bc049e9ae097b3b29be8d4 [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"
157
Zonr Chang932648d2010-10-13 22:23:56 +0800158#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700159// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
160
Zonr Chang932648d2010-10-13 22:23:56 +0800161#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700162// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
163
164// #define PROVIDE_TRACE_CODEGEN
165
166#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +0800167# include "llvm/MC/MCInst.h"
168# include "llvm/MC/MCAsmInfo.h"
169# include "llvm/MC/MCInstPrinter.h"
170# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700171// If you want the disassemble results written to file, define this:
172# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700173#endif
174
175#include <set>
176#include <map>
177#include <list>
178#include <cmath>
179#include <string>
180#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800181#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700182
Zonr Chang932648d2010-10-13 22:23:56 +0800183// VMCore
184#include "llvm/Use.h"
185#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800186#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800187#include "llvm/Module.h"
188#include "llvm/Function.h"
189#include "llvm/Constant.h"
190#include "llvm/Constants.h"
191#include "llvm/Instruction.h"
192#include "llvm/PassManager.h"
193#include "llvm/LLVMContext.h"
194#include "llvm/GlobalValue.h"
195#include "llvm/Instructions.h"
196#include "llvm/OperandTraits.h"
197#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700198
199// System
Zonr Chang932648d2010-10-13 22:23:56 +0800200#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700201
202// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800203#include "llvm/ADT/APInt.h"
204#include "llvm/ADT/APFloat.h"
205#include "llvm/ADT/DenseMap.h"
206#include "llvm/ADT/ValueMap.h"
207#include "llvm/ADT/StringMap.h"
208#include "llvm/ADT/OwningPtr.h"
209#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700210
211// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800212#include "llvm/Target/TargetData.h"
213#include "llvm/Target/TargetSelect.h"
214#include "llvm/Target/TargetOptions.h"
215#include "llvm/Target/TargetMachine.h"
216#include "llvm/Target/TargetJITInfo.h"
217#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700218#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700219
220// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800221#include "llvm/Support/Casting.h"
222#include "llvm/Support/raw_ostream.h"
223#include "llvm/Support/ValueHandle.h"
224#include "llvm/Support/MemoryBuffer.h"
225#include "llvm/Support/MemoryObject.h"
226#include "llvm/Support/ManagedStatic.h"
227#include "llvm/Support/ErrorHandling.h"
228#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700229#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700230
231// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800232#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700233
234// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800235#include "llvm/CodeGen/Passes.h"
236#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700237#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700238#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700239#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700240#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700241#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700242#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700243#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700244#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700245
246// ExecutionEngine
247#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700248#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700249
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700250extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700251
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800252// For caching
253struct oBCCHeader {
254 uint8_t magic[4]; // includes version number
255 uint8_t magicVersion[4];
256
257 uint32_t sourceWhen;
258 uint32_t rslibWhen;
259 uint32_t libRSWhen;
260 uint32_t libbccWhen;
261
262 uint32_t cachedCodeDataAddr;
263 uint32_t rootAddr;
264 uint32_t initAddr;
265
266 uint32_t relocOffset; // offset of reloc table.
267 uint32_t relocCount;
268 uint32_t exportVarsOffset; // offset of export var table
269 uint32_t exportVarsCount;
270 uint32_t exportFuncsOffset; // offset of export func table
271 uint32_t exportFuncsCount;
272 uint32_t exportPragmasOffset; // offset of export pragma table
273 uint32_t exportPragmasCount;
274
275 uint32_t codeOffset; // offset of code: 64-bit alignment
276 uint32_t codeSize;
277 uint32_t dataOffset; // offset of data section
278 uint32_t dataSize;
279
280 // uint32_t flags; // some info flags
281 uint32_t checksum; // adler32 checksum covering deps/opt
282};
283
Logan824dd0a2010-11-20 01:45:54 +0800284struct oBCCRelocEntry {
285 uint32_t relocType; // target instruction relocation type
286 uint32_t relocOffset; // offset of hole (holeAddr - codeAddr)
287 uint32_t cachedResultAddr; // address resolved at compile time
288
Logan634bd832010-11-20 09:00:36 +0800289 oBCCRelocEntry(uint32_t ty, uintptr_t off, void *addr)
Logan824dd0a2010-11-20 01:45:54 +0800290 : relocType(ty),
291 relocOffset(static_cast<uint32_t>(off)),
292 cachedResultAddr(reinterpret_cast<uint32_t>(addr)) {
293 }
294};
295
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800296/* oBCCHeader Offset Table */
297#define k_magic offsetof(oBCCHeader, magic)
298#define k_magicVersion offsetof(oBCCHeader, magicVersion)
299#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
300#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
301#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
302#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
303#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
304#define k_rootAddr offsetof(oBCCHeader, rootAddr)
305#define k_initAddr offsetof(oBCCHeader, initAddr)
306#define k_relocOffset offsetof(oBCCHeader, relocOffset)
307#define k_relocCount offsetof(oBCCHeader, relocCount)
308#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
309#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
310#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
311#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
312#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
313#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
314#define k_codeOffset offsetof(oBCCHeader, codeOffset)
315#define k_codeSize offsetof(oBCCHeader, codeSize)
316#define k_dataOffset offsetof(oBCCHeader, dataOffset)
317#define k_dataSize offsetof(oBCCHeader, dataSize)
318#define k_checksum offsetof(oBCCHeader, checksum)
319
320/* oBCC file magic number */
321#define OBCC_MAGIC "bcc\n"
322/* version, encoded in 4 bytes of ASCII */
323#define OBCC_MAGIC_VERS "001\0"
324
325#define TEMP_FAILURE_RETRY1(exp) ({ \
326 typeof (exp) _rc; \
327 do { \
328 _rc = (exp); \
329 } while (_rc == -1 && errno == EINTR); \
330 _rc; })
331
332static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
333{
334 while (count != 0) {
335 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
336 if (actual < 0) {
337 int err = errno;
338 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
339 return err;
340 } else if (actual != (ssize_t) count) {
341 LOGD("%s: partial write (will retry): (%d of %zd)\n",
342 logMsg, (int) actual, count);
343 buf = (const void*) (((const uint8_t*) buf) + actual);
344 }
345 count -= actual;
346 }
347
348 return 0;
349}
350
Zonr Chang932648d2010-10-13 22:23:56 +0800351//
352// Compilation class that suits Android's needs.
353// (Support: no argument passed, ...)
354//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700355namespace bcc {
356
357class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800358 // This part is designed to be orthogonal to those exported bcc*() functions
359 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700360
Zonr Chang932648d2010-10-13 22:23:56 +0800361 //////////////////////////////////////////////////////////////////////////////
362 // The variable section below (e.g., Triple, CodeGenOptLevel)
363 // is initialized in GlobalInitialization()
364 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700365 static bool GlobalInitialized;
Loganc0b9f652010-11-24 22:33:16 +0800366 static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700367
Zonr Chang932648d2010-10-13 22:23:56 +0800368 // If given, this will be the name of the target triple to compile for.
369 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700370 static std::string Triple;
371
372 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700373
Zonr Chang932648d2010-10-13 22:23:56 +0800374 // End of section of GlobalInitializing variables
375 //////////////////////////////////////////////////////////////////////////////
376
377 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700378 static std::string CPU;
379
Zonr Chang932648d2010-10-13 22:23:56 +0800380 // The list of target specific features to enable or disable -- this should
381 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700382 static std::vector<std::string> Features;
383
384 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800385 const char *mName;
386 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700387 };
388 static struct Runtime Runtimes[];
389
390 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800391 if (GlobalInitialized)
392 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700393
Zonr Chang932648d2010-10-13 22:23:56 +0800394 // if (!llvm::llvm_is_multithreaded())
395 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700396
Zonr Chang932648d2010-10-13 22:23:56 +0800397 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700398 Triple = TARGET_TRIPLE_STRING;
399
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800400 // TODO(sliao): NEON for JIT
Zonr Chang932648d2010-10-13 22:23:56 +0800401 // Features.push_back("+neon");
402 // Features.push_back("+vmlx");
403 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700404 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700405 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700406
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700407#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
408 LLVMInitializeARMTargetInfo();
409 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700410#if defined(USE_DISASSEMBLER)
411 LLVMInitializeARMDisassembler();
412 LLVMInitializeARMAsmPrinter();
413#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700414#endif
415
416#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
417 LLVMInitializeX86TargetInfo();
418 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700419#if defined(USE_DISASSEMBLER)
420 LLVMInitializeX86Disassembler();
421 LLVMInitializeX86AsmPrinter();
422#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700423#endif
424
425#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
426 LLVMInitializeX86TargetInfo();
427 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700428#if defined(USE_DISASSEMBLER)
429 LLVMInitializeX86Disassembler();
430 LLVMInitializeX86AsmPrinter();
431#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700432#endif
433
Zonr Chang932648d2010-10-13 22:23:56 +0800434 // -O0: llvm::CodeGenOpt::None
435 // -O1: llvm::CodeGenOpt::Less
436 // -O2: llvm::CodeGenOpt::Default
437 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700438 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700439
Zonr Chang932648d2010-10-13 22:23:56 +0800440 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700441
Zonr Chang932648d2010-10-13 22:23:56 +0800442 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700443 llvm::NoFramePointerElim = false;
444
Zonr Chang932648d2010-10-13 22:23:56 +0800445 // Use hardfloat ABI
446 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800447 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800448 // softfp. To use softfp, change following 2 lines to
449 //
450 // llvm::FloatABIType = llvm::FloatABI::Soft;
451 // llvm::UseSoftFloat = true;
452 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700453 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700454 llvm::UseSoftFloat = false;
455
Zonr Chang932648d2010-10-13 22:23:56 +0800456 // BCC needs all unknown symbols resolved at JIT/compilation time.
457 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700458 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
459
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700460#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800461 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700462 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
463#else
Zonr Chang932648d2010-10-13 22:23:56 +0800464 // This is set for the linker (specify how large of the virtual addresses
465 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700466 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
467#endif
468
Zonr Chang932648d2010-10-13 22:23:56 +0800469 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700470 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
471
Zonr Chang932648d2010-10-13 22:23:56 +0800472 // Register allocation policy:
473 // createFastRegisterAllocator: fast but bad quality
474 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700475 llvm::RegisterRegAlloc::setDefault
476 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700477 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700478 llvm::createLinearScanRegisterAllocator);
479
480 GlobalInitialized = true;
481 return;
482 }
483
484 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800485 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700486 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700487 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800488 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700489 }
490
491 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700492 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700493 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700494
495 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700496 std::string mError;
497
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700498 inline bool hasError() const {
499 return !mError.empty();
500 }
Zonr Chang932648d2010-10-13 22:23:56 +0800501 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700502 mError.assign(Error); // Copying
503 return;
504 }
Zonr Chang932648d2010-10-13 22:23:56 +0800505 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700506 mError = Error;
507 return;
508 }
509
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800510 bool mUseCache; // Set by readBC()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800511 bool mCacheNew; // Set by readBC()
512 int mCacheFd; // Set by readBC()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800513 char *mCacheMapAddr; // Set by loadCacheFile() if mCacheNew is false
514 oBCCHeader *mCacheHdr; // Set by loadCacheFile()
515 size_t mCacheSize; // Set by loadCacheFile()
516 ptrdiff_t mCacheDiff; // Set by loadCacheFile()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800517 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
518 // Used by genCacheFile() for dumping
519
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700520 typedef std::list< std::pair<std::string, std::string> > PragmaList;
521 PragmaList mPragmas;
522
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700523 typedef std::list<void*> ExportVarList;
524 ExportVarList mExportVars;
525
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700526 typedef std::list<void*> ExportFuncList;
527 ExportFuncList mExportFuncs;
528
Zonr Chang932648d2010-10-13 22:23:56 +0800529 //////////////////////////////////////////////////////////////////////////////
530 // Memory manager for the code reside in memory
531 //
532 // The memory for our code emitter is very simple and is conforming to the
533 // design decisions of Android RenderScript's Exection Environment:
534 // The code, data, and symbol sizes are limited (currently 100KB.)
535 //
536 // It's very different from typical compiler, which has no limitation
537 // on the code size. How does code emitter know the size of the code
538 // it is about to emit? It does not know beforehand. We want to solve
539 // this without complicating the code emitter too much.
540 //
541 // We solve this by pre-allocating a certain amount of memory,
542 // and then start the code emission. Once the buffer overflows, the emitter
543 // simply discards all the subsequent emission but still has a counter
544 // on how many bytes have been emitted.
545 //
546 // So once the whole emission is done, if there's a buffer overflow,
547 // it re-allocates the buffer with enough size (based on the
548 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800549
550 // 128 KiB for code
Loganc0b9f652010-11-24 22:33:16 +0800551 static const unsigned int MaxCodeSize = BCC_MMAP_IMG_CODE_SIZE;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800552 // 1 KiB for global offset table (GOT)
553 static const unsigned int MaxGOTSize = 1 * 1024;
554 // 128 KiB for global variable
Loganc0b9f652010-11-24 22:33:16 +0800555 static const unsigned int MaxGlobalVarSize = BCC_MMAP_IMG_DATA_SIZE;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800556
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700557 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700558 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800559 //
560 // Our memory layout is as follows:
561 //
562 // The direction of arrows (-> and <-) shows memory's growth direction
563 // when more space is needed.
564 //
565 // @mpCodeMem:
566 // +--------------------------------------------------------------+
567 // | Function Memory ... -> <- ... Stub/GOT |
568 // +--------------------------------------------------------------+
569 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
570 //
571 // Where size of GOT is @MaxGOTSize KiB.
572 //
573 // @mpGVMem:
574 // +--------------------------------------------------------------+
575 // | Global variable ... -> |
576 // +--------------------------------------------------------------+
577 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
578 //
579 //
580 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
581 // of function code's memory usage
582 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
583 // of stub/GOT's memory usage
584 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
585 // of global variable's memory usage
586 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700587 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700588 uintptr_t mCurSGMemIdx;
589 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800590 void *mpCodeMem;
591 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700592
Zonr Chang932648d2010-10-13 22:23:56 +0800593 // GOT Base
594 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700595
596 typedef std::map<const llvm::Function*, pair<void* /* start address */,
597 void* /* end address */>
598 > FunctionMapTy;
599 FunctionMapTy mFunctionMap;
600
Zonr Chang932648d2010-10-13 22:23:56 +0800601 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700602 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700603 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700604
Zonr Chang932648d2010-10-13 22:23:56 +0800605 uint8_t *allocateSGMemory(uintptr_t Size,
606 unsigned Alignment = 1 /* no alignment */) {
607 intptr_t FreeMemSize = getFreeCodeMemSize();
608 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
609 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700610 return NULL;
611
Zonr Chang932648d2010-10-13 22:23:56 +0800612 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700613 Alignment = 1;
614
Zonr Chang932648d2010-10-13 22:23:56 +0800615 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700616 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
617
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700618 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700619
620 return result;
621 }
622
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700623 inline uintptr_t getFreeGVMemSize() const {
624 return MaxGlobalVarSize - mCurGVMemIdx;
625 }
Zonr Chang932648d2010-10-13 22:23:56 +0800626 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700627 return reinterpret_cast<uint8_t*>(mpGVMem);
628 }
629
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700630 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700631 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700632 reset();
633 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700634
Loganc0b9f652010-11-24 22:33:16 +0800635 // Try to use fixed address
636
637 // Note: If we failed to allocate mpCodeMem at fixed address,
638 // the caching mechanism has to either perform relocation or
639 // give up. If the caching mechanism gives up, then we have to
640 // recompile the bitcode and wasting a lot of time.
641
642 for (size_t i = 0; i < BCC_MMAP_IMG_COUNT; ++i) {
643 if (Compiler::BccMmapImgAddrTaken[i]) {
644 // The address BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE has
645 // been taken.
646 continue;
647 }
648
649 // Occupy the mmap image address first (No matter allocation
650 // success or not. Keep occupying if succeed; otherwise,
651 // keep occupying as a mark of failure.)
652 Compiler::BccMmapImgAddrTaken[i] = true;
653
654 void *currMmapImgAddr =
655 reinterpret_cast<void *>(BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE);
656
657 mpCodeMem = mmap(currMmapImgAddr, BCC_MMAP_IMG_SIZE,
Loganad7e8e12010-11-22 20:43:43 +0800658 PROT_READ | PROT_EXEC | PROT_WRITE,
659 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
660 -1, 0);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800661
Loganad7e8e12010-11-22 20:43:43 +0800662 if (mpCodeMem == MAP_FAILED) {
Loganc0b9f652010-11-24 22:33:16 +0800663 LOGE("Mmap mpCodeMem at %p failed with reason: %s. Retrying ..\n",
664 currMmapImgAddr, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800665 } else {
Loganc0b9f652010-11-24 22:33:16 +0800666 // Good, we have got one mmap image address.
667 break;
Loganad7e8e12010-11-22 20:43:43 +0800668 }
669 }
670
Loganc0b9f652010-11-24 22:33:16 +0800671 if (!mpCodeMem || mpCodeMem == MAP_FAILED) {
672 LOGE("Try to allocate mpCodeMem at arbitary address.\n");
Loganad7e8e12010-11-22 20:43:43 +0800673
Loganc0b9f652010-11-24 22:33:16 +0800674 mpCodeMem = mmap(NULL, BCC_MMAP_IMG_SIZE,
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800675 PROT_READ | PROT_EXEC | PROT_WRITE,
676 MAP_PRIVATE | MAP_ANON,
Loganad7e8e12010-11-22 20:43:43 +0800677 -1, 0);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800678
Loganad7e8e12010-11-22 20:43:43 +0800679 if (mpCodeMem == MAP_FAILED) {
680 LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
681 llvm::report_fatal_error("Failed to allocate memory for emitting "
682 "codes\n" + ErrMsg);
683 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800684 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800685
Loganc0b9f652010-11-24 22:33:16 +0800686 LOGE("Mmap mpCodeMem at %p successfully.\n", mpCodeMem);
687
Loganad7e8e12010-11-22 20:43:43 +0800688 // Set global variable pool
689 mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
690
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700691 return;
692 }
693
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800694 inline uint8_t *getCodeMemBase() const {
695 return reinterpret_cast<uint8_t*>(mpCodeMem);
696 }
697
Zonr Chang932648d2010-10-13 22:23:56 +0800698 // setMemoryWritable - When code generation is in progress, the code pages
699 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700700 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700701 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700702 return;
703 }
704
Zonr Chang932648d2010-10-13 22:23:56 +0800705 // When code generation is done and we're ready to start execution, the
706 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700707 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700708 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700709 return;
710 }
711
Zonr Chang932648d2010-10-13 22:23:56 +0800712 // Setting this flag to true makes the memory manager garbage values over
713 // freed memory. This is useful for testing and debugging, and is to be
714 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700715 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800716 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700717 return;
718 }
719
Zonr Chang932648d2010-10-13 22:23:56 +0800720 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700721
Zonr Chang932648d2010-10-13 22:23:56 +0800722 // If the current table requires a Global Offset Table, this method is
723 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700724 void AllocateGOT() {
725 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700726 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700727 HasGOT = true;
728 return;
729 }
730
Zonr Chang932648d2010-10-13 22:23:56 +0800731 // If this is managing a Global Offset Table, this method should return a
732 // pointer to its base.
733 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700734 return mpGOTBase;
735 }
736
Zonr Chang932648d2010-10-13 22:23:56 +0800737 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700738
Zonr Chang932648d2010-10-13 22:23:56 +0800739 // When we start JITing a function, the JIT calls this method to allocate a
740 // block of free RWX memory, which returns a pointer to it. If the JIT wants
741 // to request a block of memory of at least a certain size, it passes that
742 // value as ActualSize, and this method returns a block with at least that
743 // much space. If the JIT doesn't know ahead of time how much space it will
744 // need to emit the function, it passes 0 for the ActualSize. In either
745 // case, this method is required to pass back the size of the allocated
746 // block through ActualSize. The JIT will be careful to not write more than
747 // the returned ActualSize bytes of memory.
748 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
749 intptr_t FreeMemSize = getFreeCodeMemSize();
750 if ((FreeMemSize < 0) ||
751 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
752 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700753 return NULL;
754
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700755 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700756 return (getCodeMemBase() + mCurFuncMemIdx);
757 }
758
Zonr Chang932648d2010-10-13 22:23:56 +0800759 // This method is called by the JIT to allocate space for a function stub
760 // (used to handle limited branch displacements) while it is JIT compiling a
761 // function. For example, if foo calls bar, and if bar either needs to be
762 // lazily compiled or is a native function that exists too far away from the
763 // call site to work, this method will be used to make a thunk for it. The
764 // stub should be "close" to the current function body, but should not be
765 // included in the 'actualsize' returned by startFunctionBody.
766 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700767 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700768 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700769 }
770
Zonr Chang932648d2010-10-13 22:23:56 +0800771 // This method is called when the JIT is done codegen'ing the specified
772 // function. At this point we know the size of the JIT compiled function.
773 // This passes in FunctionStart (which was returned by the startFunctionBody
774 // method) and FunctionEnd which is a pointer to the actual end of the
775 // function. This method should mark the space allocated and remember where
776 // it is in case the client wants to deallocate it.
777 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
778 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700779 assert(FunctionEnd > FunctionStart);
780 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
781 "Mismatched function start/end!");
782
Zonr Chang932648d2010-10-13 22:23:56 +0800783 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700784 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700785 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700786 "Code size excess the limitation!");
787 mCurFuncMemIdx += FunctionCodeSize;
788
Zonr Chang932648d2010-10-13 22:23:56 +0800789 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700790 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
791 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800792 mFunctionMap.insert(
793 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
794 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700795
796 return;
797 }
798
Zonr Chang932648d2010-10-13 22:23:56 +0800799 // Allocate a (function code) memory block of the given size. This method
800 // cannot be called between calls to startFunctionBody and endFunctionBody.
801 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
802 if (getFreeCodeMemSize() < Size)
803 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700804 return NULL;
805
Zonr Chang932648d2010-10-13 22:23:56 +0800806 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700807 Alignment = 1;
808
Zonr Chang932648d2010-10-13 22:23:56 +0800809 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700810 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800811 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700812
813 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
814
815 return result;
816 }
817
Zonr Chang932648d2010-10-13 22:23:56 +0800818 // Allocate memory for a global variable.
819 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700820 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800821 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700822 LOGE("No Global Memory");
823 return NULL;
824 }
825
Zonr Chang932648d2010-10-13 22:23:56 +0800826 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700827 Alignment = 1;
828
Zonr Chang932648d2010-10-13 22:23:56 +0800829 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700830 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800831 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700832
833 mCurGVMemIdx = (result + Size) - getGVMemBase();
834
835 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700836 }
837
Zonr Chang932648d2010-10-13 22:23:56 +0800838 // Free the specified function body. The argument must be the return value
839 // from a call to startFunctionBody() that hasn't been deallocated yet. This
840 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700841 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800842 // linear search
843 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
844 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
845 E = mFunctionMap.end();
846 I != E;
847 I++)
848 if (I->second.first == Body) {
849 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
850 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700851 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800852 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700853
Zonr Chang932648d2010-10-13 22:23:56 +0800854 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700855
Zonr Chang932648d2010-10-13 22:23:56 +0800856 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700857 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
858
859 assert(SizeNeedMove >= 0 &&
860 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
861 " be correctly calculated!");
862
Zonr Chang932648d2010-10-13 22:23:56 +0800863 if (SizeNeedMove > 0)
864 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700865 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
866 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
867
868 return;
869 }
870
Zonr Chang932648d2010-10-13 22:23:56 +0800871 // When we finished JITing the function, if exception handling is set, we
872 // emit the exception table.
873 uint8_t *startExceptionTable(const llvm::Function *F,
874 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700875 assert(false && "Exception is not allowed in our language specification");
876 return NULL;
877 }
878
Zonr Chang932648d2010-10-13 22:23:56 +0800879 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700880 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800881 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700882 assert(false && "Exception is not allowed in our language specification");
883 return;
884 }
885
Zonr Chang932648d2010-10-13 22:23:56 +0800886 // Free the specified exception table's memory. The argument must be the
887 // return value from a call to startExceptionTable() that hasn't been
888 // deallocated yet. This is never called when the JIT is currently emitting
889 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700890 void deallocateExceptionTable(void *ET) {
891 assert(false && "Exception is not allowed in our language specification");
892 return;
893 }
894
Zonr Chang932648d2010-10-13 22:23:56 +0800895 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700896 void reset() {
897 mpGOTBase = NULL;
898 HasGOT = false;
899
900 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700901 mCurSGMemIdx = MaxCodeSize - 1;
902 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700903
904 mFunctionMap.clear();
905
906 return;
907 }
908
909 ~CodeMemoryManager() {
Loganc0b9f652010-11-24 22:33:16 +0800910 if (mpCodeMem != NULL && mpCodeMem != MAP_FAILED) {
Loganad7e8e12010-11-22 20:43:43 +0800911 munmap(mpCodeMem, MaxCodeSize + MaxGlobalVarSize);
Loganc0b9f652010-11-24 22:33:16 +0800912
913 // TODO(logan): Reset Compiler::BccMmapImgAddrTaken[i] to false, so
914 // that the address can be reused.
915 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700916 return;
917 }
Zonr Chang932648d2010-10-13 22:23:56 +0800918 };
919 // End of class CodeMemoryManager
920 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700921
Zonr Chang932648d2010-10-13 22:23:56 +0800922 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700923 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800924 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700925 mCodeMemMgr.reset(new CodeMemoryManager());
926 return mCodeMemMgr.get();
927 }
928
Zonr Chang932648d2010-10-13 22:23:56 +0800929 //////////////////////////////////////////////////////////////////////////////
930 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700931 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700932 public:
933 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
934 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
935
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800936 GlobalAddressMapTy mGlobalAddressMap;
937
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700938 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800939 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700940
Zonr Chang932648d2010-10-13 22:23:56 +0800941 // The JITInfo for the target we are compiling to
942 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700943
Zonr Chang932648d2010-10-13 22:23:56 +0800944 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700945
Zonr Chang932648d2010-10-13 22:23:56 +0800946 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700947
948 class EmittedFunctionCode {
949 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800950 // Beginning of the function's allocation.
951 void *FunctionBody;
952
953 // The address the function's code actually starts at.
954 void *Code;
955
956 // The size of the function code
957 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700958
959 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
960 };
Zonr Chang932648d2010-10-13 22:23:56 +0800961 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700962
Zonr Chang932648d2010-10-13 22:23:56 +0800963 typedef std::map<const std::string,
964 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700965 EmittedFunctionsMapTy mEmittedFunctions;
966
Zonr Chang932648d2010-10-13 22:23:56 +0800967 // This vector is a mapping from MBB ID's to their address. It is filled in
968 // by the StartMachineBasicBlock callback and queried by the
969 // getMachineBasicBlockAddress callback.
970 std::vector<uintptr_t> mMBBLocations;
971
972 // The constant pool for the current function.
973 llvm::MachineConstantPool *mpConstantPool;
974
975 // A pointer to the first entry in the constant pool.
976 void *mpConstantPoolBase;
977
978 // Addresses of individual constant pool entries.
979 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
980
981 // The jump tables for the current function.
982 llvm::MachineJumpTableInfo *mpJumpTable;
983
984 // A pointer to the first entry in the jump table.
985 void *mpJumpTableBase;
986
987 // When outputting a function stub in the context of some other function, we
988 // save BufferBegin/BufferEnd/CurBufferPtr here.
989 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
990
991 // These are the relocations that the function needs, as emitted.
992 std::vector<llvm::MachineRelocation> mRelocations;
993
Logan824dd0a2010-11-20 01:45:54 +0800994 std::vector<oBCCRelocEntry> mCachingRelocations;
995
Zonr Chang932648d2010-10-13 22:23:56 +0800996 // This vector is a mapping from Label ID's to their address.
997 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
998
999 // Machine module info for exception informations
1000 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001001
Zonr Chang932648d2010-10-13 22:23:56 +08001002 // Replace an existing mapping for GV with a new address. This updates both
1003 // maps as required. If Addr is null, the entry for the global is removed
1004 // from the mappings.
1005 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
1006 if (Addr == NULL) {
1007 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001008 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
1009 void *OldVal;
1010
Zonr Chang932648d2010-10-13 22:23:56 +08001011 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001012 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001013 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001014 OldVal = I->second;
1015 mGlobalAddressMap.erase(I);
1016 }
1017
1018 return OldVal;
1019 }
1020
Zonr Chang932648d2010-10-13 22:23:56 +08001021 void *&CurVal = mGlobalAddressMap[GV];
1022 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001023
1024 CurVal = Addr;
1025
1026 return OldVal;
1027 }
1028
Zonr Chang932648d2010-10-13 22:23:56 +08001029 // Tell the execution engine that the specified global is at the specified
1030 // location. This is used internally as functions are JIT'd and as global
1031 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001032 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001033 void *&CurVal = mGlobalAddressMap[GV];
1034 assert((CurVal == 0 || Addr == 0) &&
1035 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001036 CurVal = Addr;
1037 return;
1038 }
1039
Zonr Chang932648d2010-10-13 22:23:56 +08001040 // This returns the address of the specified global value if it is has
1041 // already been codegen'd, otherwise it returns null.
1042 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001043 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001044 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
1045 }
1046
Zonr Chang932648d2010-10-13 22:23:56 +08001047 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
1048 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001049 MCP->getConstants();
1050
Zonr Chang932648d2010-10-13 22:23:56 +08001051 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001052 return 0;
1053
1054 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001055 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001056 llvm::MachineConstantPoolEntry CPE = Constants[i];
1057 unsigned int AlignMask = CPE.getAlignment() - 1;
1058 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +08001059 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001060 Size += mpTD->getTypeAllocSize(Ty);
1061 }
1062
1063 return Size;
1064 }
1065
Zonr Chang932648d2010-10-13 22:23:56 +08001066 // This function converts a Constant* into a GenericValue. The interesting
1067 // part is if C is a ConstantExpr.
1068 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
1069 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001070 return;
Zonr Chang932648d2010-10-13 22:23:56 +08001071 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
1072 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
1073 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001074
Zonr Chang932648d2010-10-13 22:23:56 +08001075 switch (CE->getOpcode()) {
1076 case llvm::Instruction::GetElementPtr: {
1077 // Compute the index
1078 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
1079 CE->op_end());
1080 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
1081 &Indices[0],
1082 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001083
Zonr Chang932648d2010-10-13 22:23:56 +08001084 GetConstantValue(Op0, Result);
1085 Result.PointerVal =
1086 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001087
Zonr Chang932648d2010-10-13 22:23:56 +08001088 return;
1089 }
1090 case llvm::Instruction::Trunc: {
1091 uint32_t BitWidth =
1092 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1093
1094 GetConstantValue(Op0, Result);
1095 Result.IntVal = Result.IntVal.trunc(BitWidth);
1096
1097 return;
1098 }
1099 case llvm::Instruction::ZExt: {
1100 uint32_t BitWidth =
1101 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1102
1103 GetConstantValue(Op0, Result);
1104 Result.IntVal = Result.IntVal.zext(BitWidth);
1105
1106 return;
1107 }
1108 case llvm::Instruction::SExt: {
1109 uint32_t BitWidth =
1110 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1111
1112 GetConstantValue(Op0, Result);
1113 Result.IntVal = Result.IntVal.sext(BitWidth);
1114
1115 return;
1116 }
1117 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001118 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001119 GetConstantValue(Op0, Result);
1120 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1121 return;
1122 }
1123 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001124 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001125 GetConstantValue(Op0, Result);
1126 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1127 return;
1128 }
1129 case llvm::Instruction::UIToFP: {
1130 GetConstantValue(Op0, Result);
1131 if (CE->getType()->isFloatTy())
1132 Result.FloatVal =
1133 static_cast<float>(Result.IntVal.roundToDouble());
1134 else if (CE->getType()->isDoubleTy())
1135 Result.DoubleVal = Result.IntVal.roundToDouble();
1136 else if (CE->getType()->isX86_FP80Ty()) {
1137 const uint64_t zero[] = { 0, 0 };
1138 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1139 apf.convertFromAPInt(Result.IntVal,
1140 false,
1141 llvm::APFloat::rmNearestTiesToEven);
1142 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001143 }
Zonr Chang932648d2010-10-13 22:23:56 +08001144 return;
1145 }
1146 case llvm::Instruction::SIToFP: {
1147 GetConstantValue(Op0, Result);
1148 if (CE->getType()->isFloatTy())
1149 Result.FloatVal =
1150 static_cast<float>(Result.IntVal.signedRoundToDouble());
1151 else if (CE->getType()->isDoubleTy())
1152 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1153 else if (CE->getType()->isX86_FP80Ty()) {
1154 const uint64_t zero[] = { 0, 0 };
1155 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1156 apf.convertFromAPInt(Result.IntVal,
1157 true,
1158 llvm::APFloat::rmNearestTiesToEven);
1159 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001160 }
Zonr Chang932648d2010-10-13 22:23:56 +08001161 return;
1162 }
1163 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001164 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001165 case llvm::Instruction::FPToSI: {
1166 uint32_t BitWidth =
1167 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001168
Zonr Chang932648d2010-10-13 22:23:56 +08001169 GetConstantValue(Op0, Result);
1170 if (Op0->getType()->isFloatTy())
1171 Result.IntVal =
1172 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1173 else if (Op0->getType()->isDoubleTy())
1174 Result.IntVal =
1175 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1176 BitWidth);
1177 else if (Op0->getType()->isX86_FP80Ty()) {
1178 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1179 uint64_t V;
1180 bool Ignored;
1181 apf.convertToInteger(&V,
1182 BitWidth,
1183 CE->getOpcode() == llvm::Instruction::FPToSI,
1184 llvm::APFloat::rmTowardZero,
1185 &Ignored);
1186 Result.IntVal = V; // endian?
1187 }
1188 return;
1189 }
1190 case llvm::Instruction::PtrToInt: {
1191 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1192
1193 GetConstantValue(Op0, Result);
1194 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1195 (Result.PointerVal));
1196
1197 return;
1198 }
1199 case llvm::Instruction::IntToPtr: {
1200 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1201
1202 GetConstantValue(Op0, Result);
1203 if (PtrWidth != Result.IntVal.getBitWidth())
1204 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1205 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1206
1207 Result.PointerVal =
1208 llvm::PointerTy(
1209 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1210
1211 return;
1212 }
1213 case llvm::Instruction::BitCast: {
1214 GetConstantValue(Op0, Result);
1215 const llvm::Type *DestTy = CE->getType();
1216
1217 switch (Op0->getType()->getTypeID()) {
1218 case llvm::Type::IntegerTyID: {
1219 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1220 if (DestTy->isFloatTy())
1221 Result.FloatVal = Result.IntVal.bitsToFloat();
1222 else if (DestTy->isDoubleTy())
1223 Result.DoubleVal = Result.IntVal.bitsToDouble();
1224 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001225 }
Zonr Chang932648d2010-10-13 22:23:56 +08001226 case llvm::Type::FloatTyID: {
1227 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1228 Result.IntVal.floatToBits(Result.FloatVal);
1229 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001230 }
Zonr Chang932648d2010-10-13 22:23:56 +08001231 case llvm::Type::DoubleTyID: {
1232 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1233 Result.IntVal.doubleToBits(Result.DoubleVal);
1234 break;
1235 }
1236 case llvm::Type::PointerTyID: {
1237 assert(DestTy->isPointerTy() && "Invalid bitcast");
1238 break; // getConstantValue(Op0) above already converted it
1239 }
1240 default: {
1241 llvm_unreachable("Invalid bitcast operand");
1242 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001243 }
Zonr Chang932648d2010-10-13 22:23:56 +08001244 return;
1245 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001246 case llvm::Instruction::Add:
1247 case llvm::Instruction::FAdd:
1248 case llvm::Instruction::Sub:
1249 case llvm::Instruction::FSub:
1250 case llvm::Instruction::Mul:
1251 case llvm::Instruction::FMul:
1252 case llvm::Instruction::UDiv:
1253 case llvm::Instruction::SDiv:
1254 case llvm::Instruction::URem:
1255 case llvm::Instruction::SRem:
1256 case llvm::Instruction::And:
1257 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001258 case llvm::Instruction::Xor: {
1259 llvm::GenericValue LHS, RHS;
1260 GetConstantValue(Op0, LHS);
1261 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001262
Zonr Chang932648d2010-10-13 22:23:56 +08001263 switch (Op0->getType()->getTypeID()) {
1264 case llvm::Type::IntegerTyID: {
1265 switch (CE->getOpcode()) {
1266 case llvm::Instruction::Add: {
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::Sub: {
1271 Result.IntVal = LHS.IntVal - RHS.IntVal;
1272 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001273 }
Zonr Chang932648d2010-10-13 22:23:56 +08001274 case llvm::Instruction::Mul: {
1275 Result.IntVal = LHS.IntVal * RHS.IntVal;
1276 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001277 }
Zonr Chang932648d2010-10-13 22:23:56 +08001278 case llvm::Instruction::UDiv: {
1279 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1280 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001281 }
Zonr Chang932648d2010-10-13 22:23:56 +08001282 case llvm::Instruction::SDiv: {
1283 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1284 break;
1285 }
1286 case llvm::Instruction::URem: {
1287 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1288 break;
1289 }
1290 case llvm::Instruction::SRem: {
1291 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1292 break;
1293 }
1294 case llvm::Instruction::And: {
1295 Result.IntVal = LHS.IntVal & RHS.IntVal;
1296 break;
1297 }
1298 case llvm::Instruction::Or: {
1299 Result.IntVal = LHS.IntVal | RHS.IntVal;
1300 break;
1301 }
1302 case llvm::Instruction::Xor: {
1303 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1304 break;
1305 }
1306 default: {
1307 llvm_unreachable("Invalid integer opcode");
1308 }
1309 }
1310 break;
1311 }
1312 case llvm::Type::FloatTyID: {
1313 switch (CE->getOpcode()) {
1314 case llvm::Instruction::FAdd: {
1315 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1316 break;
1317 }
1318 case llvm::Instruction::FSub: {
1319 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1320 break;
1321 }
1322 case llvm::Instruction::FMul: {
1323 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1324 break;
1325 }
1326 case llvm::Instruction::FDiv: {
1327 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1328 break;
1329 }
1330 case llvm::Instruction::FRem: {
1331 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1332 break;
1333 }
1334 default: {
1335 llvm_unreachable("Invalid float opcode");
1336 }
1337 }
1338 break;
1339 }
1340 case llvm::Type::DoubleTyID: {
1341 switch (CE->getOpcode()) {
1342 case llvm::Instruction::FAdd: {
1343 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1344 break;
1345 }
1346 case llvm::Instruction::FSub: {
1347 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1348 break;
1349 }
1350 case llvm::Instruction::FMul: {
1351 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1352 break;
1353 }
1354 case llvm::Instruction::FDiv: {
1355 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1356 break;
1357 }
1358 case llvm::Instruction::FRem: {
1359 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1360 break;
1361 }
1362 default: {
1363 llvm_unreachable("Invalid double opcode");
1364 }
1365 }
1366 break;
1367 }
1368 case llvm::Type::X86_FP80TyID:
1369 case llvm::Type::PPC_FP128TyID:
1370 case llvm::Type::FP128TyID: {
1371 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1372 switch (CE->getOpcode()) {
1373 case llvm::Instruction::FAdd: {
1374 apfLHS.add(llvm::APFloat(RHS.IntVal),
1375 llvm::APFloat::rmNearestTiesToEven);
1376 break;
1377 }
1378 case llvm::Instruction::FSub: {
1379 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1380 llvm::APFloat::rmNearestTiesToEven);
1381 break;
1382 }
1383 case llvm::Instruction::FMul: {
1384 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1385 llvm::APFloat::rmNearestTiesToEven);
1386 break;
1387 }
1388 case llvm::Instruction::FDiv: {
1389 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1390 llvm::APFloat::rmNearestTiesToEven);
1391 break;
1392 }
1393 case llvm::Instruction::FRem: {
1394 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1395 llvm::APFloat::rmNearestTiesToEven);
1396 break;
1397 }
1398 default: {
1399 llvm_unreachable("Invalid long double opcode");
1400 }
1401 }
1402 Result.IntVal = apfLHS.bitcastToAPInt();
1403 break;
1404 }
1405 default: {
1406 llvm_unreachable("Bad add type!");
1407 }
1408 } // End switch (Op0->getType()->getTypeID())
1409 return;
1410 }
1411 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001412 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001413 }
1414 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001415
1416 std::string msg;
1417 llvm::raw_string_ostream Msg(msg);
1418 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001419 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001420 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001421
1422 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001423 case llvm::Type::FloatTyID: {
1424 Result.FloatVal =
1425 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001426 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001427 }
1428 case llvm::Type::DoubleTyID: {
1429 Result.DoubleVal =
1430 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001431 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001432 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001433 case llvm::Type::X86_FP80TyID:
1434 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001435 case llvm::Type::PPC_FP128TyID: {
1436 Result.IntVal =
1437 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001438 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001439 }
1440 case llvm::Type::IntegerTyID: {
1441 Result.IntVal =
1442 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001443 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001444 }
1445 case llvm::Type::PointerTyID: {
1446 switch (C->getValueID()) {
1447 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001448 Result.PointerVal = NULL;
1449 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001450 }
1451 case llvm::Value::FunctionVal: {
1452 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1453 Result.PointerVal =
1454 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001455 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001456 }
1457 case llvm::Value::GlobalVariableVal: {
1458 const llvm::GlobalVariable *GV =
1459 static_cast<const llvm::GlobalVariable*>(C);
1460 Result.PointerVal =
1461 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001462 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001463 }
1464 case llvm::Value::BlockAddressVal: {
1465 assert(false && "JIT does not support address-of-label yet!");
1466 }
1467 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001468 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001469 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001470 }
1471 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001472 }
1473 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001474 std::string msg;
1475 llvm::raw_string_ostream Msg(msg);
1476 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001477 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001478 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001479 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001480 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001481 return;
1482 }
1483
Zonr Chang932648d2010-10-13 22:23:56 +08001484 // Stores the data in @Val of type @Ty at address @Addr.
1485 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001486 const llvm::Type *Ty) {
1487 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1488
Zonr Chang932648d2010-10-13 22:23:56 +08001489 switch (Ty->getTypeID()) {
1490 case llvm::Type::IntegerTyID: {
1491 const llvm::APInt &IntVal = Val.IntVal;
1492 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1493 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001494
Zonr Chang932648d2010-10-13 22:23:56 +08001495 const uint8_t *Src =
1496 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001497
Zonr Chang932648d2010-10-13 22:23:56 +08001498 if (llvm::sys::isLittleEndianHost()) {
1499 // Little-endian host - the source is ordered from LSB to MSB.
1500 // Order the destination from LSB to MSB: Do a straight copy.
1501 memcpy(Addr, Src, StoreBytes);
1502 } else {
1503 // Big-endian host - the source is an array of 64 bit words
1504 // ordered from LSW to MSW.
1505 //
1506 // Each word is ordered from MSB to LSB.
1507 //
1508 // Order the destination from MSB to LSB:
1509 // Reverse the word order, but not the bytes in a word.
1510 unsigned int i = StoreBytes;
1511 while (i > sizeof(uint64_t)) {
1512 i -= sizeof(uint64_t);
1513 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1514 Src,
1515 sizeof(uint64_t));
1516 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001517 }
Zonr Chang932648d2010-10-13 22:23:56 +08001518 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001519 }
1520 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001521 }
1522 case llvm::Type::FloatTyID: {
1523 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001524 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001525 }
1526 case llvm::Type::DoubleTyID: {
1527 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001528 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001529 }
1530 case llvm::Type::X86_FP80TyID: {
1531 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001532 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001533 }
1534 case llvm::Type::PointerTyID: {
1535 // Ensure 64 bit target pointers are fully initialized on 32 bit
1536 // hosts.
1537 if (StoreBytes != sizeof(llvm::PointerTy))
1538 memset(Addr, 0, StoreBytes);
1539 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001540 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001541 }
1542 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001543 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001544 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001545 }
1546
Zonr Chang932648d2010-10-13 22:23:56 +08001547 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1548 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1549 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001550
1551 return;
1552 }
1553
Zonr Chang932648d2010-10-13 22:23:56 +08001554 // Recursive function to apply a @Constant value into the specified memory
1555 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001556 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001557 switch (C->getValueID()) {
1558 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001559 // Nothing to do
1560 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001561 }
1562 case llvm::Value::ConstantVectorVal: {
1563 // dynamic cast may hurt performance
1564 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001565
Zonr Chang932648d2010-10-13 22:23:56 +08001566 unsigned int ElementSize = mpTD->getTypeAllocSize
1567 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001568
Zonr Chang932648d2010-10-13 22:23:56 +08001569 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1570 InitializeConstantToMemory(
1571 CP->getOperand(i),
1572 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001573 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001574 }
1575 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001576 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1577 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001578 }
1579 case llvm::Value::ConstantArrayVal: {
1580 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1581 unsigned int ElementSize = mpTD->getTypeAllocSize
1582 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001583
Zonr Chang932648d2010-10-13 22:23:56 +08001584 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1585 InitializeConstantToMemory(
1586 CPA->getOperand(i),
1587 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1588 break;
1589 }
1590 case llvm::Value::ConstantStructVal: {
1591 const llvm::ConstantStruct *CPS =
1592 static_cast<const llvm::ConstantStruct*>(C);
1593 const llvm::StructLayout *SL = mpTD->getStructLayout
1594 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001595
Zonr Chang932648d2010-10-13 22:23:56 +08001596 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1597 InitializeConstantToMemory(
1598 CPS->getOperand(i),
1599 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1600 break;
1601 }
1602 default: {
1603 if (C->getType()->isFirstClassType()) {
1604 llvm::GenericValue Val;
1605 GetConstantValue(C, Val);
1606 StoreValueToMemory(Val, Addr, C->getType());
1607 } else {
1608 llvm_unreachable("Unknown constant type to initialize memory "
1609 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001610 }
1611 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001612 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001613 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001614 return;
1615 }
1616
1617 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001618 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001619 return;
1620
Zonr Chang932648d2010-10-13 22:23:56 +08001621 // Constant pool address resolution is handled by the target itself in ARM
1622 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001623#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001624 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1625 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001626
Zonr Chang932648d2010-10-13 22:23:56 +08001627 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001628 return;
1629
1630 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1631 unsigned Align = MCP->getConstantPoolAlignment();
1632
1633 mpConstantPoolBase = allocateSpace(Size, Align);
1634 mpConstantPool = MCP;
1635
Zonr Chang932648d2010-10-13 22:23:56 +08001636 if (mpConstantPoolBase == NULL)
1637 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001638
1639 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001640 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001641 llvm::MachineConstantPoolEntry CPE = Constants[i];
1642 unsigned AlignMask = CPE.getAlignment() - 1;
1643 Offset = (Offset + AlignMask) & ~AlignMask;
1644
1645 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1646 mConstPoolAddresses.push_back(CAddr);
1647
Zonr Chang932648d2010-10-13 22:23:56 +08001648 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001649 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001650 ("Initialize memory with machine specific constant pool"
1651 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001652
1653 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1654
1655 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1656 Offset += mpTD->getTypeAllocSize(Ty);
1657 }
1658#endif
1659 return;
1660 }
1661
1662 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001663 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001664 return;
1665
Zonr Chang932648d2010-10-13 22:23:56 +08001666 const std::vector<llvm::MachineJumpTableEntry> &JT =
1667 MJTI->getJumpTables();
1668 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001669 return;
1670
1671 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001672 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001673 NumEntries += JT[i].MBBs.size();
1674
1675 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1676
Zonr Chang932648d2010-10-13 22:23:56 +08001677 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001678 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001679 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001680
1681 return;
1682 }
1683
1684 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001685 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001686 return;
1687
Zonr Chang932648d2010-10-13 22:23:56 +08001688 const std::vector<llvm::MachineJumpTableEntry> &JT =
1689 MJTI->getJumpTables();
1690 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001691 return;
1692
Zonr Chang932648d2010-10-13 22:23:56 +08001693 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1694 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1695 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001696
Zonr Chang932648d2010-10-13 22:23:56 +08001697 // For each jump table, map each target in the jump table to the
1698 // address of an emitted MachineBasicBlock.
1699 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1700 for (int i = 0, ie = JT.size(); i != ie; i++) {
1701 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1702 // Store the address of the basic block for this jump table slot in the
1703 // memory we allocated for the jump table in 'initJumpTableInfo'
1704 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001705 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1706 }
1707 }
1708
Zonr Chang932648d2010-10-13 22:23:56 +08001709 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1710 bool MayNeedFarStub) {
1711 switch (V->getValueID()) {
1712 case llvm::Value::FunctionVal: {
1713 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001714
Zonr Chang932648d2010-10-13 22:23:56 +08001715 // If we have code, go ahead and return that.
1716 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1717 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001718
Zonr Chang932648d2010-10-13 22:23:56 +08001719 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1720 // Return the function stub if it's already created.
1721 // We do this first so that:
1722 // we're returning the same address for the function as any
1723 // previous call.
1724 //
1725 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1726 // guaranteed to be close enough to call.
1727 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001728
Zonr Chang932648d2010-10-13 22:23:56 +08001729 // If we know the target can handle arbitrary-distance calls, try to
1730 // return a direct pointer.
1731 if (!MayNeedFarStub) {
1732 //
1733 // x86_64 architecture may encounter the bug:
1734 // http://llvm.org/bugs/show_bug.cgi?id=5201
1735 // which generate instruction "call" instead of "callq".
1736 //
1737 // And once the real address of stub is greater than 64-bit
1738 // long, the replacement will truncate to 32-bit resulting a
1739 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001740#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001741 // If this is an external function pointer, we can force the JIT
1742 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001743 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1744 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1745 // Changing to false because wanting to allow later calls to
1746 // mpTJI->relocate() without aborting. For caching purpose
1747 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001748#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001749 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001750
Zonr Chang932648d2010-10-13 22:23:56 +08001751 // Otherwise, we may need a to emit a stub, and, conservatively, we
1752 // always do so.
1753 return GetLazyFunctionStub(F);
1754 break;
1755 }
1756 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001757 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1758 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001759 }
1760 case llvm::Value::GlobalAliasVal: {
1761 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1762 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001763
Zonr Chang932648d2010-10-13 22:23:56 +08001764 switch (GV->getValueID()) {
1765 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001766 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001767 // code-gen'd?
1768 return GetPointerToFunction(
1769 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001770 /* AbortOnFailure = */false);
1771 // Changing to false because wanting to allow later calls to
1772 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001773 break;
1774 }
1775 case llvm::Value::GlobalVariableVal: {
1776 if (void *P = mGlobalAddressMap[GV])
1777 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001778
Zonr Chang932648d2010-10-13 22:23:56 +08001779 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1780 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001781
Zonr Chang932648d2010-10-13 22:23:56 +08001782 return mGlobalAddressMap[GV];
1783 break;
1784 }
1785 case llvm::Value::GlobalAliasVal: {
1786 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001787 }
1788 }
1789 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001790 }
1791 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001792 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001793 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001794 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001795 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001796 }
1797
Zonr Chang932648d2010-10-13 22:23:56 +08001798 // If the specified function has been code-gen'd, return a pointer to the
1799 // function. If not, compile it, or use a stub to implement lazy compilation
1800 // if available.
1801 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1802 // If we have already code generated the function, just return the
1803 // address.
1804 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001805 return Addr;
1806
Zonr Chang932648d2010-10-13 22:23:56 +08001807 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001808 return GetLazyFunctionStub(F);
1809 }
1810
Zonr Chang932648d2010-10-13 22:23:56 +08001811 typedef llvm::DenseMap<const llvm::Function*,
1812 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001813 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1814
Zonr Chang932648d2010-10-13 22:23:56 +08001815 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001816 return mFunctionToLazyStubMap.lookup(F);
1817 }
1818
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001819 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001820 void *GetLazyFunctionStub(llvm::Function *F) {
1821 // If we already have a lazy stub for this function, recycle it.
1822 void *&Stub = mFunctionToLazyStubMap[F];
1823 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001824 return Stub;
1825
Zonr Chang932648d2010-10-13 22:23:56 +08001826 // In any cases, we should NOT resolve function at runtime (though we are
1827 // able to). We resolve this right now.
1828 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001829 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1830 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1831 // Changing to false because wanting to allow later calls to
1832 // mpTJI->relocate() without aborting. For caching purpose
1833 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001834
Zonr Chang932648d2010-10-13 22:23:56 +08001835 // Codegen a new stub, calling the actual address of the external
1836 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001837 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1838 startGVStub(F, SL.Size, SL.Alignment);
1839 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1840 finishGVStub();
1841
Zonr Chang932648d2010-10-13 22:23:56 +08001842 // We really want the address of the stub in the GlobalAddressMap for the
1843 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001844 UpdateGlobalMapping(F, Stub);
1845
Zonr Chang932648d2010-10-13 22:23:56 +08001846 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001847 PendingFunctions.insert(F);
1848 else
Zonr Chang932648d2010-10-13 22:23:56 +08001849 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1850 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001851
1852 return Stub;
1853 }
1854
Zonr Chang932648d2010-10-13 22:23:56 +08001855 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1856 void *Addr = GetPointerToGlobalIfAvailable(F);
1857 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001858 return Addr;
1859
1860 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1861 "Internal error: only external defined function routes here!");
1862
Zonr Chang932648d2010-10-13 22:23:56 +08001863 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001864 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001865 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001866
Zonr Chang932648d2010-10-13 22:23:56 +08001867 // If we resolved the symbol to a null address (eg. a weak external)
1868 // return a null pointer let the application handle it.
1869 if (Addr == NULL) {
1870 if (AbortOnFailure)
1871 llvm::report_fatal_error("Could not resolve external function "
1872 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001873 else
1874 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001875 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001876
1877 AddGlobalMapping(F, Addr);
1878
1879 return Addr;
1880 }
1881
Zonr Chang932648d2010-10-13 22:23:56 +08001882 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001883 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001884 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001885 return Addr;
1886
Zonr Chang932648d2010-10-13 22:23:56 +08001887 if (mpSymbolLookupFn)
1888 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001889 return Addr;
1890
Zonr Chang932648d2010-10-13 22:23:56 +08001891 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001892 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001893 "' which could not be resolved!");
1894
1895 return NULL;
1896 }
1897
Zonr Chang932648d2010-10-13 22:23:56 +08001898 // Return the address of the specified global variable, possibly emitting it
1899 // to memory if needed. This is used by the Emitter.
1900 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1901 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1902 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001903 return Ptr;
1904
Zonr Chang932648d2010-10-13 22:23:56 +08001905 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1906 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001907 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1908 AddGlobalMapping(GV, Ptr);
1909 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001910 // If the global hasn't been emitted to memory yet, allocate space and
1911 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001912 Ptr = GetMemoryForGV(GV);
1913 AddGlobalMapping(GV, Ptr);
1914 EmitGlobalVariable(GV);
1915 }
1916
1917 return Ptr;
1918 }
1919
Zonr Chang932648d2010-10-13 22:23:56 +08001920 // This method abstracts memory allocation of global variable so that the
1921 // JIT can allocate thread local variables depending on the target.
1922 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1923 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001924
Zonr Chang932648d2010-10-13 22:23:56 +08001925 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001926 size_t S = mpTD->getTypeAllocSize(GlobalType);
1927 size_t A = mpTD->getPreferredAlignment(GV);
1928
Zonr Chang932648d2010-10-13 22:23:56 +08001929 if (GV->isThreadLocal()) {
1930 // We can support TLS by
1931 //
1932 // Ptr = TJI.allocateThreadLocalMemory(S);
1933 //
1934 // But I tend not to.
1935 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001936 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001937 ("Compilation of Thread Local Storage (TLS) is disabled!");
1938
Zonr Chang932648d2010-10-13 22:23:56 +08001939 } else if (mpTJI->allocateSeparateGVMemory()) {
1940 if (A <= 8) {
1941 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001942 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001943 // Allocate (S + A) bytes of memory, then use an aligned pointer
1944 // within that space.
1945 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001946 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001947 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1948 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001949 }
1950 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001951 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001952 }
1953
1954 return Ptr;
1955 }
1956
1957 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001958 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001959
Zonr Chang932648d2010-10-13 22:23:56 +08001960 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001961 llvm::report_fatal_error
1962 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001963
Zonr Chang932648d2010-10-13 22:23:56 +08001964 if (GA == NULL) {
1965 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001966 GA = GetMemoryForGV(GV);
1967 AddGlobalMapping(GV, GA);
1968 }
1969
1970 InitializeConstantToMemory(GV->getInitializer(), GA);
1971
Zonr Chang932648d2010-10-13 22:23:56 +08001972 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001973 return;
1974 }
1975
1976 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1977 > GlobalToIndirectSymMapTy;
1978 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1979
Zonr Chang932648d2010-10-13 22:23:56 +08001980 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1981 // Make sure GV is emitted first, and create a stub containing the fully
1982 // resolved address.
1983 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001984
Zonr Chang932648d2010-10-13 22:23:56 +08001985 // If we already have a stub for this global variable, recycle it.
1986 void *&IndirectSym = GlobalToIndirectSymMap[V];
1987 // Otherwise, codegen a new indirect symbol.
1988 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001989 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1990
1991 return IndirectSym;
1992 }
1993
Zonr Chang932648d2010-10-13 22:23:56 +08001994 // This is the equivalent of FunctionToLazyStubMap for external functions.
1995 //
1996 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1997 // It's actually here to make it more likely that far calls
1998 // succeed, but no single stub can guarantee that. I'll
1999 // remove this in a subsequent checkin when I actually fix
2000 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002001 std::map<void*, void*> ExternalFnToStubMap;
2002
Zonr Chang932648d2010-10-13 22:23:56 +08002003 // Return a stub for the function at the specified address.
2004 void *GetExternalFunctionStub(void *FnAddr) {
2005 void *&Stub = ExternalFnToStubMap[FnAddr];
2006 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002007 return Stub;
2008
2009 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2010 startGVStub(0, SL.Size, SL.Alignment);
2011 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
2012 finishGVStub();
2013
2014 return Stub;
2015 }
2016
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002017#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002018 const llvm::MCAsmInfo *mpAsmInfo;
2019 const llvm::MCDisassembler *mpDisassmbler;
2020 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002021
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002022 class BufferMemoryObject : public llvm::MemoryObject {
2023 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002024 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002025 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002026
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002027 public:
2028 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
2029 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002030
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002031 uint64_t getBase() const { return 0; }
2032 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002033
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002034 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002035 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002036 return -1;
2037 *Byte = mBytes[Addr];
2038 return 0;
2039 }
2040 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002041
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002042 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002043 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002044 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08002045 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002046#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002047 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08002048 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
2049 ErrorInfo,
2050 llvm::raw_fd_ostream::F_Append);
2051 if (!ErrorInfo.empty()) { // some errors occurred
2052 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002053 delete OS;
2054 return;
2055 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002056#else
2057 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002058#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002059 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
2060 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002061
Zonr Chang932648d2010-10-13 22:23:56 +08002062 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002063 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08002064 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002065 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08002066 if (mpIP == NULL)
2067 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
2068 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002069
Zonr Chang932648d2010-10-13 22:23:56 +08002070 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
2071 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002072 uint64_t Size;
2073 uint64_t Index;
2074
Zonr Chang932648d2010-10-13 22:23:56 +08002075 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002076 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002077
Zonr Chang932648d2010-10-13 22:23:56 +08002078 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2079 /* REMOVED */ llvm::nulls())) {
2080 (*OS).indent(4)
2081 .write("0x", 2)
2082 .write_hex((uint32_t) Start + Index)
2083 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002084 mpIP->printInst(&Inst, *OS);
2085 *OS << "\n";
2086 } else {
2087 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002088 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002089 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002090 }
2091
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002092 *OS << "\n";
2093 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002094
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002095#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002096 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002097 OS->close();
2098 delete OS;
2099#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002100 return;
2101 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002102#else
Zonr Chang932648d2010-10-13 22:23:56 +08002103 inline void Disassemble(const std::string &Name, uint8_t *Start,
2104 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002105 return;
2106 }
Zonr Chang932648d2010-10-13 22:23:56 +08002107#endif // defined(USE_DISASSEMBLER)
2108
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002109 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002110 // Resolver to undefined symbol in CodeEmitter
2111 BCCSymbolLookupFn mpSymbolLookupFn;
2112 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002113
2114 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002115 // Will take the ownership of @MemMgr
2116 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2117 : mpMemMgr(pMemMgr),
2118 mpTarget(NULL),
2119 mpTJI(NULL),
2120 mpTD(NULL),
2121 mpCurEmitFunction(NULL),
2122 mpConstantPool(NULL),
2123 mpJumpTable(NULL),
2124 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002125#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002126 mpAsmInfo(NULL),
2127 mpDisassmbler(NULL),
2128 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002129#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002130 mpSymbolLookupFn(NULL),
2131 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002132 return;
2133 }
2134
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002135 inline global_addresses_const_iterator global_address_begin() const {
2136 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002137 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002138 inline global_addresses_const_iterator global_address_end() const {
2139 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002140 }
2141
Logan824dd0a2010-11-20 01:45:54 +08002142 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2143 return mCachingRelocations;
2144 }
2145
Zonr Chang932648d2010-10-13 22:23:56 +08002146 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002147 mpSymbolLookupFn = pFn;
2148 mpSymbolLookupContext = pContext;
2149 return;
2150 }
2151
Zonr Chang932648d2010-10-13 22:23:56 +08002152 void setTargetMachine(llvm::TargetMachine &TM) {
2153 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002154 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002155 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002156 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002157 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002158 mpTD = TM.getTargetData();
2159
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002160 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2161
2162 return;
2163 }
2164
Zonr Chang932648d2010-10-13 22:23:56 +08002165 // This callback is invoked when the specified function is about to be code
2166 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002167 void startFunction(llvm::MachineFunction &F) {
2168 uintptr_t ActualSize = 0;
2169
2170 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002171
2172 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2173 // MachineCodeEmitter, which is the super class of the class
2174 // JITCodeEmitter.
2175 //
2176 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2177 // allocated for this code buffer.
2178 //
2179 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2180 // code. This is guranteed to be in the range
2181 // [BufferBegin, BufferEnd]. If this pointer is at
2182 // BufferEnd, it will never move due to code emission, and
2183 // all code emission requests will be ignored (this is the
2184 // buffer overflow condition).
2185 BufferBegin = CurBufferPtr =
2186 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002187 BufferEnd = BufferBegin + ActualSize;
2188
Zonr Chang932648d2010-10-13 22:23:56 +08002189 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002190 mpCurEmitFunction = new EmittedFunctionCode();
2191 mpCurEmitFunction->FunctionBody = BufferBegin;
2192
Zonr Chang932648d2010-10-13 22:23:56 +08002193 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002194 emitAlignment(16);
2195
2196 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002197 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002198 initJumpTableInfo(MJTI);
2199
Zonr Chang932648d2010-10-13 22:23:56 +08002200 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002201 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2202
2203 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2204
2205 mpCurEmitFunction->Code = CurBufferPtr;
2206
2207 mMBBLocations.clear();
2208
2209 return;
2210 }
2211
Zonr Chang932648d2010-10-13 22:23:56 +08002212 // This callback is invoked when the specified function has finished code
2213 // generation. If a buffer overflow has occurred, this method returns true
2214 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002215 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002216 if (CurBufferPtr == BufferEnd) {
2217 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002218 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2219 return false;
2220 }
2221
Zonr Chang932648d2010-10-13 22:23:56 +08002222 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002223 emitJumpTableInfo(MJTI);
2224
Zonr Chang932648d2010-10-13 22:23:56 +08002225 // FnStart is the start of the text, not the start of the constant pool
2226 // and other per-function data.
2227 uint8_t *FnStart =
2228 reinterpret_cast<uint8_t*>(
2229 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002230
Zonr Chang932648d2010-10-13 22:23:56 +08002231 // FnEnd is the end of the function's machine code.
2232 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002233
Zonr Chang932648d2010-10-13 22:23:56 +08002234 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002235 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2236
Zonr Chang932648d2010-10-13 22:23:56 +08002237 // Resolve the relocations to concrete pointers.
2238 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2239 llvm::MachineRelocation &MR = mRelocations[i];
2240 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002241
Zonr Chang932648d2010-10-13 22:23:56 +08002242 if (!MR.letTargetResolve()) {
2243 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002244 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002245
2246 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002247 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002248 }
2249
Zonr Chang932648d2010-10-13 22:23:56 +08002250 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002251 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2252 BufferBegin
2253 + MR.getMachineCodeOffset(),
2254 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002255 } else if (MR.isIndirectSymbol()) {
2256 ResultPtr =
2257 GetPointerToGVIndirectSym(
2258 MR.getGlobalValue(),
2259 BufferBegin + MR.getMachineCodeOffset());
2260 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002261 ResultPtr =
2262 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002263 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002264 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002265 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002266 } else {
2267 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2268 ResultPtr =
2269 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2270 }
2271
Logan824dd0a2010-11-20 01:45:54 +08002272 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2273 // TODO(logan): Cache external symbol relocation entry.
2274 // Currently, we are not caching them. But since Android
2275 // system is using prelink, it is not a problem.
2276
2277 // Cache the relocation result address
2278 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002279 oBCCRelocEntry(MR.getRelocationType(),
2280 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002281 ResultPtr));
2282 }
2283
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002284 MR.setResultPointer(ResultPtr);
2285 }
2286 }
2287
2288 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2289 mpMemMgr->getGOTBase());
2290 }
2291
2292 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002293 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2294 // global variables that were referenced in the relocations.
2295 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002296 return false;
2297
Zonr Chang932648d2010-10-13 22:23:56 +08002298 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002299 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2300 BufferBegin = CurBufferPtr = 0;
2301
Zonr Chang932648d2010-10-13 22:23:56 +08002302 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002303 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2304 mpCurEmitFunction = NULL;
2305
2306 mRelocations.clear();
2307 mConstPoolAddresses.clear();
2308
Zonr Chang932648d2010-10-13 22:23:56 +08002309 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002310 mpMMI->EndFunction();
2311
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002312 updateFunctionStub(F.getFunction());
2313
Zonr Chang932648d2010-10-13 22:23:56 +08002314 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002315 mpMemMgr->setMemoryExecutable();
2316
2317 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2318
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002319 return false;
2320 }
2321
Zonr Chang932648d2010-10-13 22:23:56 +08002322 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002323 unsigned Alignment) {
2324 mpSavedBufferBegin = BufferBegin;
2325 mpSavedBufferEnd = BufferEnd;
2326 mpSavedCurBufferPtr = CurBufferPtr;
2327
2328 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2329 Alignment);
2330 BufferEnd = BufferBegin + StubSize + 1;
2331
2332 return;
2333 }
2334
Zonr Chang932648d2010-10-13 22:23:56 +08002335 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002336 mpSavedBufferBegin = BufferBegin;
2337 mpSavedBufferEnd = BufferEnd;
2338 mpSavedCurBufferPtr = CurBufferPtr;
2339
Zonr Chang932648d2010-10-13 22:23:56 +08002340 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002341 BufferEnd = BufferBegin + StubSize + 1;
2342
2343 return;
2344 }
2345
2346 void finishGVStub() {
2347 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2348
Zonr Chang932648d2010-10-13 22:23:56 +08002349 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002350 BufferBegin = mpSavedBufferBegin;
2351 BufferEnd = mpSavedBufferEnd;
2352 CurBufferPtr = mpSavedCurBufferPtr;
2353
2354 return;
2355 }
2356
Zonr Chang932648d2010-10-13 22:23:56 +08002357 // Allocates and fills storage for an indirect GlobalValue, and returns the
2358 // address.
2359 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002360 const uint8_t *Buffer, size_t Size,
2361 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002362 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002363 memcpy(IndGV, Buffer, Size);
2364 return IndGV;
2365 }
2366
Zonr Chang932648d2010-10-13 22:23:56 +08002367 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002368 void emitLabel(llvm::MCSymbol *Label) {
2369 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002370 return;
2371 }
2372
Zonr Chang932648d2010-10-13 22:23:56 +08002373 // Allocate memory for a global. Unlike allocateSpace, this method does not
2374 // allocate memory in the current output buffer, because a global may live
2375 // longer than the current function.
2376 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2377 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002378 return mpMemMgr->allocateGlobal(Size, Alignment);
2379 }
2380
Zonr Chang932648d2010-10-13 22:23:56 +08002381 // This should be called by the target when a new basic block is about to be
2382 // emitted. This way the MCE knows where the start of the block is, and can
2383 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002384 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002385 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002386 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2387 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2388 return;
2389 }
2390
Zonr Chang932648d2010-10-13 22:23:56 +08002391 // Whenever a relocatable address is needed, it should be noted with this
2392 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002393 void addRelocation(const llvm::MachineRelocation &MR) {
2394 mRelocations.push_back(MR);
2395 return;
2396 }
2397
Zonr Chang932648d2010-10-13 22:23:56 +08002398 // Return the address of the @Index entry in the constant pool that was
2399 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002400 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2401 assert(Index < mpConstantPool->getConstants().size() &&
2402 "Invalid constant pool index!");
2403 return mConstPoolAddresses[Index];
2404 }
2405
Zonr Chang932648d2010-10-13 22:23:56 +08002406 // Return the address of the jump table with index @Index in the function
2407 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002408 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002409 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002410 mpJumpTable->getJumpTables();
2411
Zonr Chang932648d2010-10-13 22:23:56 +08002412 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002413
2414 unsigned int Offset = 0;
2415 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2416
Zonr Chang932648d2010-10-13 22:23:56 +08002417 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002418 Offset += JT[i].MBBs.size();
2419 Offset *= EntrySize;
2420
Zonr Chang932648d2010-10-13 22:23:56 +08002421 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002422 }
2423
Zonr Chang932648d2010-10-13 22:23:56 +08002424 // Return the address of the specified MachineBasicBlock, only usable after
2425 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002426 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2427 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002428 mMBBLocations[MBB->getNumber()] &&
2429 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002430 return mMBBLocations[MBB->getNumber()];
2431 }
2432
Zonr Chang932648d2010-10-13 22:23:56 +08002433 // Return the address of the specified LabelID, only usable after the
2434 // LabelID has been emitted.
2435 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002436 assert(mLabelLocations.count(Label) && "Label not emitted!");
2437 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002438 }
2439
Zonr Chang932648d2010-10-13 22:23:56 +08002440 // Specifies the MachineModuleInfo object. This is used for exception
2441 // handling purposes.
2442 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002443 mpMMI = Info;
2444 return;
2445 }
2446
Zonr Chang932648d2010-10-13 22:23:56 +08002447 void updateFunctionStub(const llvm::Function *F) {
2448 // Get the empty stub we generated earlier.
2449 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002450 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002451 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002452 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002453 else
2454 return;
2455
Zonr Chang932648d2010-10-13 22:23:56 +08002456 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002457
2458 assert(Addr != Stub &&
2459 "Function must have non-stub address to be updated.");
2460
Zonr Chang932648d2010-10-13 22:23:56 +08002461 // Tell the target jit info to rewrite the stub at the specified address,
2462 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002463 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2464 startGVStub(Stub, SL.Size);
2465 mpTJI->emitFunctionStub(F, Addr, *this);
2466 finishGVStub();
2467
Zonr Chang932648d2010-10-13 22:23:56 +08002468 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2469 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002470
2471 PendingFunctions.erase(I);
2472
2473 return;
2474 }
2475
Zonr Chang932648d2010-10-13 22:23:56 +08002476 // Once you finish the compilation on a translation unit, you can call this
2477 // function to recycle the memory (which is used at compilation time and not
2478 // needed for runtime).
2479 //
2480 // NOTE: You should not call this funtion until the code-gen passes for a
2481 // given module is done. Otherwise, the results is undefined and may
2482 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002483 void releaseUnnecessary() {
2484 mMBBLocations.clear();
2485 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002486 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002487 mFunctionToLazyStubMap.clear();
2488 GlobalToIndirectSymMap.clear();
2489 ExternalFnToStubMap.clear();
2490 PendingFunctions.clear();
2491
2492 return;
2493 }
2494
2495 void reset() {
2496 releaseUnnecessary();
2497
2498 mpSymbolLookupFn = NULL;
2499 mpSymbolLookupContext = NULL;
2500
2501 mpTJI = NULL;
2502 mpTD = NULL;
2503
Zonr Chang932648d2010-10-13 22:23:56 +08002504 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2505 E = mEmittedFunctions.end();
2506 I != E;
2507 I++)
2508 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002509 delete I->second;
2510 mEmittedFunctions.clear();
2511
2512 mpMemMgr->reset();
2513
2514 return;
2515 }
2516
Zonr Chang932648d2010-10-13 22:23:56 +08002517 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002518 return lookup( llvm::StringRef(Name) );
2519 }
2520
Zonr Chang932648d2010-10-13 22:23:56 +08002521 void *lookup(const llvm::StringRef &Name) {
2522 EmittedFunctionsMapTy::const_iterator I =
2523 mEmittedFunctions.find(Name.str());
2524 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002525 return NULL;
2526 else
2527 return I->second->Code;
2528 }
2529
Zonr Chang932648d2010-10-13 22:23:56 +08002530 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002531 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002532 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002533 int functionCount = mEmittedFunctions.size();
2534
Zonr Chang932648d2010-10-13 22:23:56 +08002535 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002536 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002537 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002538 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002539 if (functions)
2540 for (EmittedFunctionsMapTy::const_iterator
2541 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2542 (I != E) && (functionCount > 0);
2543 I++, functionCount--)
2544 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002545
2546 return;
2547 }
2548
Zonr Chang932648d2010-10-13 22:23:56 +08002549 void getFunctionBinary(BCCchar *label,
2550 BCCvoid **base,
2551 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002552 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002553 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002554 *base = NULL;
2555 *length = 0;
2556 } else {
2557 *base = I->second->Code;
2558 *length = I->second->Size;
2559 }
2560 return;
2561 }
2562
2563 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002564 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002565#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002566 delete mpAsmInfo;
2567 delete mpDisassmbler;
2568 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002569#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002570 return;
2571 }
Zonr Chang932648d2010-10-13 22:23:56 +08002572 };
2573 // End of Class CodeEmitter
2574 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002575
Zonr Chang932648d2010-10-13 22:23:56 +08002576 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002577 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002578 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002579 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2580 return mCodeEmitter.get();
2581 }
2582
2583 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002584 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002585
Zonr Chang932648d2010-10-13 22:23:56 +08002586 llvm::LLVMContext *mContext;
2587 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002588
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002589 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002590
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002591 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002592 Compiler()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002593 : mUseCache(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002594 mCacheNew(false),
2595 mCacheFd(-1),
2596 mCacheMapAddr(NULL),
2597 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002598 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002599 mCacheDiff(0),
2600 mCodeDataAddr(NULL),
2601 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002602 mpSymbolLookupContext(NULL),
2603 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002604 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002605 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002606 llvm::remove_fatal_error_handler();
2607 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002608 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002609 return;
2610 }
2611
Zonr Chang932648d2010-10-13 22:23:56 +08002612 // interface for BCCscript::registerSymbolCallback()
2613 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002614 mpSymbolLookupFn = pFn;
2615 mpSymbolLookupContext = pContext;
2616 return;
2617 }
2618
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002619 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002620 GlobalInitialization();
2621 mModule = module;
2622 return hasError();
2623 }
2624
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002625 int readBC(const char *bitcode,
Loganc0b9f652010-11-24 22:33:16 +08002626 size_t bitcodeSize,
2627 const BCCchar *resName) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002628 GlobalInitialization();
2629
Loganc0b9f652010-11-24 22:33:16 +08002630 if (resName) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002631 // Turn on mUseCache mode iff
2632 // 1. Has resName
2633 // and, assuming USE_RELOCATE is false:
2634 // 2. Later running code doesn't violate the following condition:
2635 // mCodeDataAddr (set in loadCacheFile()) ==
2636 // mCacheHdr->cachedCodeDataAddr
2637 //
2638 // BTW, this condition is achievable only when in the earlier
2639 // cache-generating run,
2640 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
2641 // which means the mmap'ed is in the reserved area,
2642 //
2643 // Note: Upon violation, mUseCache will be set back to false.
2644 mUseCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002645
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002646 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2647 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2648 return -mCacheFd;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002649 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002650 }
2651
2652 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002653
Zonr Chang932648d2010-10-13 22:23:56 +08002654 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002655 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002656
Zonr Chang932648d2010-10-13 22:23:56 +08002657 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002658 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002659 llvm::StringRef(bitcode, bitcodeSize)));
2660
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002661 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002662 setError("Error reading input program bitcode into memory");
2663 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002664 }
2665
Zonr Chang932648d2010-10-13 22:23:56 +08002666 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002667 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2668 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002669 return hasError();
2670 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002671
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002672 int linkBC(const char *bitcode, size_t bitcodeSize) {
2673 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002674
2675 if (bitcode == NULL || bitcodeSize <= 0)
2676 return 0;
2677
2678 if (mModule == NULL) {
2679 setError("No module presents for linking");
2680 return hasError();
2681 }
2682
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002683 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002684 llvm::StringRef(bitcode, bitcodeSize)));
2685
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002686 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002687 setError("Error reading input library bitcode into memory");
2688 return hasError();
2689 }
2690
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002691 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002692 *mContext,
2693 &mError));
2694 if (Lib.get() == NULL)
2695 return hasError();
2696
2697 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2698 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002699
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002700 // Everything for linking should be settled down here with no error occurs
2701 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002702 return hasError();
2703 }
2704
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002705 // interface for bccLoadBinary()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002706 int loadCacheFile() {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002707 // Check File Descriptor
2708 if (mCacheFd < 0) {
2709 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2710 goto giveup;
2711 }
2712
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002713 // Check File Size
2714 struct stat statCacheFd;
2715 if (fstat(mCacheFd, &statCacheFd) < 0) {
2716 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2717 goto giveup;
2718 }
2719
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002720 mCacheSize = statCacheFd.st_size;
2721
2722 if (mCacheSize < sizeof(oBCCHeader) ||
2723 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002724 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2725 goto giveup;
2726 }
2727
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002728 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2729 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2730 goto giveup;
2731 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002732
Loganc0b9f652010-11-24 22:33:16 +08002733 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002734 {
Loganc0b9f652010-11-24 22:33:16 +08002735 // Read cached file and perform quick integrity check
2736
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002737 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002738 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
Loganad7e8e12010-11-22 20:43:43 +08002739 (unsigned int)mCacheSize,
2740 (unsigned long long int)heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002741
2742 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002743 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002744 flock(mCacheFd, LOCK_UN);
2745 LOGE("allocation failed.\n");
2746 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002747 }
2748
2749 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2750 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002751 if (nread != (size_t)heuristicCodeOffset) {
2752 LOGE("read(mCacheFd) failed\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002753 goto bail;
2754 }
2755
2756 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002757 // Sanity check
2758 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2759 LOGE("assertion failed: heuristic code offset is not correct.\n");
2760 goto bail;
2761 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002762 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2763 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2764 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2765 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2766 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002767
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002768 // Verify the Cache File
2769 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2770 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002771 goto bail;
2772 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002773
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002774 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2775 LOGE("bad oBCC version 0x%08x\n",
2776 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2777 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002778 }
2779
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002780 if (mCacheSize < mCacheHdr->relocOffset +
2781 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2782 LOGE("relocate table overflow\n");
2783 goto bail;
2784 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002785
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002786 if (mCacheSize < mCacheHdr->exportVarsOffset +
2787 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2788 LOGE("export variables table overflow\n");
2789 goto bail;
2790 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002791
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002792 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2793 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2794 LOGE("export functions table overflow\n");
2795 goto bail;
2796 }
2797
2798 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2799 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2800 LOGE("export pragmas table overflow\n");
2801 goto bail;
2802 }
2803
2804 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2805 LOGE("code cache overflow\n");
2806 goto bail;
2807 }
2808
2809 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2810 LOGE("data (global variable) cache overflow\n");
2811 goto bail;
2812 }
Loganc0b9f652010-11-24 22:33:16 +08002813 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002814
Loganc0b9f652010-11-24 22:33:16 +08002815 // Part 2. Deal with the codedata section
2816 {
2817 void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2818
2819 // Try to mmap at cached address directly.
2820 mCodeDataAddr = (char *) mmap(addr, BCC_MMAP_IMG_SIZE,
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002821 PROT_READ | PROT_EXEC | PROT_WRITE,
2822 MAP_PRIVATE | MAP_FIXED,
Loganc0b9f652010-11-24 22:33:16 +08002823 mCacheFd, mCacheHdr->codeOffset);
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002824
Loganc0b9f652010-11-24 22:33:16 +08002825 if (mCodeDataAddr != MAP_FAILED && mCodeDataAddr == addr) {
2826 // Cheers! Mapped at the cached address successfully.
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002827
Loganc0b9f652010-11-24 22:33:16 +08002828 if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
2829 size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
2830
2831 if (offset % BCC_MMAP_IMG_SIZE == 0) {
2832 // Update the BccMmapImgAddrTaken table (if required)
2833 Compiler::BccMmapImgAddrTaken[offset / BCC_MMAP_IMG_SIZE] = true;
2834 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002835 }
2836
2837 flock(mCacheFd, LOCK_UN);
Loganc0b9f652010-11-24 22:33:16 +08002838 return 0; // loadCacheFile succeed!
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002839 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002840 }
2841
Loganc0b9f652010-11-24 22:33:16 +08002842#if !USE_RELOCATE
2843 // Note: Since this build does not support relocation, we have no
2844 // choose but give up to load the cached file, and recompile the
2845 // code.
2846
2847 flock(mCacheFd, LOCK_UN);
2848 goto bail;
2849#else
2850
2851 // Note: Currently, relocation code is not working. Give up now.
2852 flock(mCacheFd, LOCK_UN);
2853 goto bail;
2854
2855 // TODO(logan): Following code is not working. Don't use them.
2856 // And rewrite them asap.
2857#if 0
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002858 {
Loganc0b9f652010-11-24 22:33:16 +08002859 // Try to allocate at arbitary address. And perform relocation.
2860 mCacheMapAddr = (char *) mmap(0, mCacheSize,
2861 PROT_READ | PROT_EXEC | PROT_WRITE,
2862 MAP_PRIVATE, mCacheFd, 0);
2863
2864 if (mCacheMapAddr == MAP_FAILED) {
2865 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2866 flock(mCacheFd, LOCK_UN);
2867 goto giveup;
2868 }
2869
2870 flock(mCacheFd, LOCK_UN);
2871 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2872
2873 // Relocate
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002874 mCacheDiff = mCodeDataAddr -
2875 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2876
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002877 if (mCacheDiff) { // To relocate
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002878 if (mCacheHdr->rootAddr) {
2879 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002880 }
2881
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002882 if (mCacheHdr->initAddr) {
2883 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002884 }
2885
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002886 oBCCRelocEntry *cachedRelocTable =
2887 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2888 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002889
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002890 std::vector<llvm::MachineRelocation> relocations;
2891
2892 // Read in the relocs
2893 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2894 oBCCRelocEntry *entry = &cachedRelocTable[i];
2895
2896 llvm::MachineRelocation reloc =
2897 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2898 (unsigned)entry->relocType, 0, 0);
2899
2900 reloc.setResultPointer(
2901 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2902
2903 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002904 }
2905
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002906 // Rewrite machine code using llvm::TargetJITInfo relocate
2907 {
2908 llvm::TargetMachine *TM = NULL;
2909 const llvm::Target *Target;
2910 std::string FeaturesStr;
2911
2912 // Create TargetMachine
2913 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2914 if (hasError())
2915 goto bail;
2916
2917 if (!CPU.empty() || !Features.empty()) {
2918 llvm::SubtargetFeatures F;
2919 F.setCPU(CPU);
2920 for (std::vector<std::string>::const_iterator I = Features.begin(),
2921 E = Features.end(); I != E; I++)
2922 F.AddFeature(*I);
2923 FeaturesStr = F.getString();
2924 }
2925
2926 TM = Target->createTargetMachine(Triple, FeaturesStr);
2927 if (TM == NULL) {
2928 setError("Failed to create target machine implementation for the"
2929 " specified triple '" + Triple + "'");
2930 goto bail;
2931 }
2932
2933 TM->getJITInfo()->relocate(mCodeDataAddr,
2934 &relocations[0], relocations.size(),
2935 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2936
2937 if (mCodeEmitter.get()) {
2938 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2939 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2940 2 * 1024 /*MaxCodeSize*/,
2941 false);
2942 }
2943
2944 delete TM;
2945 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002946 } // End of if (mCacheDiff)
Loganc0b9f652010-11-24 22:33:16 +08002947
2948 return 0; // Success!
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002949 }
Loganc0b9f652010-11-24 22:33:16 +08002950#endif
2951#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002952
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002953 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002954 if (mCacheMapAddr) {
2955 free(mCacheMapAddr);
Loganad7e8e12010-11-22 20:43:43 +08002956 mCacheMapAddr = 0;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002957 }
Loganad7e8e12010-11-22 20:43:43 +08002958
Loganc0b9f652010-11-24 22:33:16 +08002959 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
2960 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2961 LOGE("munmap failed: %s\n", strerror(errno));
2962 }
2963
2964 mCodeDataAddr = 0;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002965 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002966
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002967 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002968 return 1;
2969 }
2970
2971 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002972 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002973 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002974
Zonr Chang932648d2010-10-13 22:23:56 +08002975 llvm::TargetMachine *TM = NULL;
2976 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002977 std::string FeaturesStr;
2978
Zonr Chang932648d2010-10-13 22:23:56 +08002979 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002980
Zonr Chang932648d2010-10-13 22:23:56 +08002981 const llvm::NamedMDNode *PragmaMetadata;
2982 const llvm::NamedMDNode *ExportVarMetadata;
2983 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002984
Zonr Chang932648d2010-10-13 22:23:56 +08002985 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002986 return 0;
2987
Zonr Chang932648d2010-10-13 22:23:56 +08002988 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002989 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002990 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002991 goto on_bcc_compile_error;
2992
Zonr Chang932648d2010-10-13 22:23:56 +08002993 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002994 llvm::SubtargetFeatures F;
2995 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002996 for (std::vector<std::string>::const_iterator I = Features.begin(),
2997 E = Features.end();
2998 I != E;
2999 I++)
3000 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003001 FeaturesStr = F.getString();
3002 }
3003
3004 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08003005 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003006 setError("Failed to create target machine implementation for the"
3007 " specified triple '" + Triple + "'");
3008 goto on_bcc_compile_error;
3009 }
3010
Zonr Chang932648d2010-10-13 22:23:56 +08003011 // Create memory manager for creation of code emitter later.
3012 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003013 setError("Failed to startup memory management for further compilation");
3014 goto on_bcc_compile_error;
3015 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003016 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003017
Zonr Chang932648d2010-10-13 22:23:56 +08003018 // Create code emitter
3019 if (!mCodeEmitter.get()) {
3020 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003021 setError("Failed to create machine code emitter to complete"
3022 " the compilation");
3023 goto on_bcc_compile_error;
3024 }
3025 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08003026 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003027 mCodeEmitter->reset();
3028 }
3029
3030 mCodeEmitter->setTargetMachine(*TM);
3031 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
3032 mpSymbolLookupContext);
3033
Zonr Chang932648d2010-10-13 22:23:56 +08003034 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003035 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003036
Zonr Chang5d35b972010-10-23 14:36:47 +08003037 // Load named metadata
3038 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
3039 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
3040 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
3041
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003042 // Create LTO passes and run them on the mModule
3043 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003044 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003045 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08003046 LTOPasses.add(new llvm::TargetData(*TD));
3047
3048 std::vector<const char*> ExportSymbols;
3049
3050 // A workaround for getting export variable and function name. Will refine
3051 // it soon.
3052 if (ExportVarMetadata) {
3053 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3054 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3055 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3056 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3057 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
3058 llvm::StringRef ExportVarName =
3059 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
3060 ExportSymbols.push_back(ExportVarName.data());
3061 }
3062 }
3063 }
3064 }
3065
3066 if (ExportFuncMetadata) {
3067 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3068 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3069 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3070 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3071 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
3072 llvm::StringRef ExportFuncName =
3073 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3074 ExportSymbols.push_back(ExportFuncName.data());
3075 }
3076 }
3077 }
3078 }
3079 // root() and init() are born to be exported
3080 ExportSymbols.push_back("root");
3081 ExportSymbols.push_back("init");
3082
Zonr Change5c7a542010-10-24 01:07:27 +08003083 // We now create passes list performing LTO. These are copied from
3084 // (including comments) llvm::createStandardLTOPasses().
3085
3086 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08003087 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003088
Zonr Change5c7a542010-10-24 01:07:27 +08003089 // Propagate constants at call sites into the functions they call. This
3090 // opens opportunities for globalopt (and inlining) by substituting
3091 // function pointers passed as arguments to direct uses of functions.
3092 LTOPasses.add(llvm::createIPSCCPPass());
3093
3094 // Now that we internalized some globals, see if we can hack on them!
3095 LTOPasses.add(llvm::createGlobalOptimizerPass());
3096
3097 // Linking modules together can lead to duplicated global constants, only
3098 // keep one copy of each constant...
3099 LTOPasses.add(llvm::createConstantMergePass());
3100
3101 // Remove unused arguments from functions...
3102 LTOPasses.add(llvm::createDeadArgEliminationPass());
3103
3104 // Reduce the code after globalopt and ipsccp. Both can open up
3105 // significant simplification opportunities, and both can propagate
3106 // functions through function pointers. When this happens, we often have
3107 // to resolve varargs calls, etc, so let instcombine do this.
3108 LTOPasses.add(llvm::createInstructionCombiningPass());
3109
3110 // Inline small functions
3111 LTOPasses.add(llvm::createFunctionInliningPass());
3112
3113 // Remove dead EH info.
3114 LTOPasses.add(llvm::createPruneEHPass());
3115
3116 // Internalize the globals again after inlining
3117 LTOPasses.add(llvm::createGlobalOptimizerPass());
3118
3119 // Remove dead functions.
3120 LTOPasses.add(llvm::createGlobalDCEPass());
3121
3122 // If we didn't decide to inline a function, check to see if we can
3123 // transform it to pass arguments by value instead of by reference.
3124 LTOPasses.add(llvm::createArgumentPromotionPass());
3125
3126 // The IPO passes may leave cruft around. Clean up after them.
3127 LTOPasses.add(llvm::createInstructionCombiningPass());
3128 LTOPasses.add(llvm::createJumpThreadingPass());
3129
3130 // Break up allocas
3131 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3132
3133 // Run a few AA driven optimizations here and now, to cleanup the code.
3134 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3135 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3136
3137 // Hoist loop invariants.
3138 LTOPasses.add(llvm::createLICMPass());
3139
3140 // Remove redundancies.
3141 LTOPasses.add(llvm::createGVNPass());
3142
3143 // Remove dead memcpys.
3144 LTOPasses.add(llvm::createMemCpyOptPass());
3145
3146 // Nuke dead stores.
3147 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3148
3149 // Cleanup and simplify the code after the scalar optimizations.
3150 LTOPasses.add(llvm::createInstructionCombiningPass());
3151
3152 LTOPasses.add(llvm::createJumpThreadingPass());
3153
3154 // Delete basic blocks, which optimization passes may have killed.
3155 LTOPasses.add(llvm::createCFGSimplificationPass());
3156
3157 // Now that we have optimized the program, discard unreachable functions.
3158 LTOPasses.add(llvm::createGlobalDCEPass());
3159
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003160 LTOPasses.run(*mModule);
3161 }
3162
Zonr Chang932648d2010-10-13 22:23:56 +08003163 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003164 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003165 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003166
Zonr Chang932648d2010-10-13 22:23:56 +08003167 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3168 *mCodeEmitter,
3169 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003170 setError("The machine code emission is not supported by BCC on target '"
3171 + Triple + "'");
3172 goto on_bcc_compile_error;
3173 }
3174
Zonr Chang932648d2010-10-13 22:23:56 +08003175 // Run the pass (the code emitter) on every non-declaration function in the
3176 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003177 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003178 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3179 I != E;
3180 I++)
3181 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003182 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003183
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003184 CodeGenPasses->doFinalization();
3185
Zonr Chang932648d2010-10-13 22:23:56 +08003186 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003187 if (ExportVarMetadata) {
3188 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3189 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3190 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3191 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3192 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003193 llvm::StringRef ExportVarName =
3194 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003195 CodeEmitter::global_addresses_const_iterator I, E;
3196 for (I = mCodeEmitter->global_address_begin(),
3197 E = mCodeEmitter->global_address_end();
3198 I != E;
3199 I++) {
3200 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003201 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003202 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003203 mExportVars.push_back(I->second);
3204 break;
3205 }
3206 }
Zonr Chang932648d2010-10-13 22:23:56 +08003207 if (I != mCodeEmitter->global_address_end())
3208 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003209 }
3210 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003211 // if reaching here, we know the global variable record in metadata is
3212 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003213 mExportVars.push_back(NULL);
3214 }
3215 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3216 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003217 }
3218
Zonr Chang932648d2010-10-13 22:23:56 +08003219 if (ExportFuncMetadata) {
3220 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3221 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3222 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3223 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3224 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003225 llvm::StringRef ExportFuncName =
3226 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3227 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3228 }
3229 }
3230 }
3231 }
3232
Zonr Chang932648d2010-10-13 22:23:56 +08003233 // Tell code emitter now can release the memory using during the JIT since
3234 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003235 mCodeEmitter->releaseUnnecessary();
3236
Zonr Chang932648d2010-10-13 22:23:56 +08003237 // Finally, read pragma information from the metadata node of the @Module if
3238 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003239 if (PragmaMetadata)
3240 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3241 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3242 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003243 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003244 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3245 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003246
Zonr Chang932648d2010-10-13 22:23:56 +08003247 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003248 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3249 llvm::StringRef PragmaName =
3250 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3251 llvm::StringRef PragmaValue =
3252 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3253
Zonr Chang932648d2010-10-13 22:23:56 +08003254 mPragmas.push_back(
3255 std::make_pair(std::string(PragmaName.data(),
3256 PragmaName.size()),
3257 std::string(PragmaValue.data(),
3258 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003259 }
3260 }
3261 }
3262
3263 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003264 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003265 if (CodeGenPasses) {
3266 delete CodeGenPasses;
3267 } else if (TD) {
3268 delete TD;
3269 }
3270 if (TM)
3271 delete TM;
3272
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003273 if (mError.empty()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003274 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003275 genCacheFile();
3276 flock(mCacheFd, LOCK_UN);
3277 }
Loganc0b9f652010-11-24 22:33:16 +08003278
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003279 return false;
3280 }
3281
Zonr Chang932648d2010-10-13 22:23:56 +08003282 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003283 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003284 }
3285
Zonr Chang932648d2010-10-13 22:23:56 +08003286 // interface for bccGetScriptInfoLog()
3287 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003288 return const_cast<char*>(mError.c_str());
3289 }
3290
Zonr Chang932648d2010-10-13 22:23:56 +08003291 // interface for bccGetScriptLabel()
3292 void *lookup(const char *name) {
3293 void *addr = NULL;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003294 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003295 if (!strcmp(name, "root")) {
3296 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3297 } else if (!strcmp(name, "init")) {
3298 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3299 }
3300 return addr;
3301 }
3302
Zonr Chang932648d2010-10-13 22:23:56 +08003303 if (mCodeEmitter.get())
3304 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003305 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003306 return addr;
3307 }
3308
Zonr Chang932648d2010-10-13 22:23:56 +08003309 // Interface for bccGetExportVars()
3310 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003311 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003312 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003313 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003314
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003315 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003316 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3317 if (actualVarCount)
3318 *actualVarCount = varCount;
3319 if (varCount > maxVarCount)
3320 varCount = maxVarCount;
3321 if (vars) {
3322 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3323 mCacheHdr->exportVarsOffset);
3324
3325 for (int i = 0; i < varCount; i++) {
3326 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3327 mCacheDiff);
3328 cachedVars++;
3329 }
3330 }
3331 return;
3332 }
3333
3334 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003335 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003336 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003337 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003338 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003339 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003340 for (ExportVarList::const_iterator I = mExportVars.begin(),
3341 E = mExportVars.end();
3342 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003343 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003344 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003345 }
3346 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003347
3348 return;
3349 }
3350
Zonr Chang932648d2010-10-13 22:23:56 +08003351 // Interface for bccGetExportFuncs()
3352 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003353 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003354 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003355 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003356
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003357 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003358 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3359 if (actualFuncCount)
3360 *actualFuncCount = funcCount;
3361 if (funcCount > maxFuncCount)
3362 funcCount = maxFuncCount;
3363 if (funcs) {
3364 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3365 mCacheHdr->exportFuncsOffset);
3366
3367 for (int i = 0; i < funcCount; i++) {
3368 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3369 mCacheDiff);
3370 cachedFuncs++;
3371 }
3372 }
3373 return;
3374 }
3375
3376 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003377 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003378 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003379 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003380 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003381 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003382 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3383 E = mExportFuncs.end();
3384 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003385 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003386 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003387 }
3388 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003389
3390 return;
3391 }
3392
Zonr Chang932648d2010-10-13 22:23:56 +08003393 // Interface for bccGetPragmas()
3394 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003395 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003396 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003397 int stringCount;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003398 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003399 if (actualStringCount)
3400 *actualStringCount = 0; // XXX
3401 return;
3402 }
3403
3404 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003405
Zonr Chang932648d2010-10-13 22:23:56 +08003406 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003407 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003408 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003409 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003410 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003411 for (PragmaList::const_iterator it = mPragmas.begin();
3412 stringCount > 0;
3413 stringCount -= 2, it++) {
3414 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3415 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003416 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003417 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003418
3419 return;
3420 }
3421
Zonr Chang932648d2010-10-13 22:23:56 +08003422 // Interface for bccGetFunctions()
3423 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003424 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003425 BCCchar **functions) {
3426 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003427 mCodeEmitter->getFunctionNames(actualFunctionCount,
3428 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003429 functions);
3430 else
3431 *actualFunctionCount = 0;
3432
3433 return;
3434 }
3435
Zonr Chang932648d2010-10-13 22:23:56 +08003436 // Interface for bccGetFunctionBinary()
3437 void getFunctionBinary(BCCchar *function,
3438 BCCvoid **base,
3439 BCCsizei *length) {
3440 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003441 mCodeEmitter->getFunctionBinary(function, base, length);
3442 } else {
3443 *base = NULL;
3444 *length = 0;
3445 }
3446 return;
3447 }
3448
Zonr Chang932648d2010-10-13 22:23:56 +08003449 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003450 return mModule;
3451 }
3452
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003453 ~Compiler() {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003454 if (!mCodeMemMgr.get()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003455 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003456 // managed by CodeMemoryManager.
3457
3458 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3459 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3460 LOGE("munmap failed while releasing mCodeDataAddr\n");
3461 }
3462
3463 mCodeDataAddr = 0;
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003464 }
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003465
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003466 if (mCacheMapAddr) {
3467 free(mCacheMapAddr);
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003468 mCacheMapAddr = 0;
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003469 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003470 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003471
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003472 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003473 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003474 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003475 return;
3476 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003477
3478 private:
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003479 // Note: loadCacheFile() and genCacheFile() go hand in hand
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003480 void genCacheFile() {
3481 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3482 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3483 return;
3484 }
3485
3486 bool codeOffsetNeedPadding = false;
3487
3488 uint32_t offset = sizeof(oBCCHeader);
3489
3490 // BCC Cache File Header
3491 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3492
3493 if (!hdr) {
3494 LOGE("Unable to allocate oBCCHeader.\n");
3495 return;
3496 }
3497
3498 // Magic Words
3499 memcpy(hdr->magic, OBCC_MAGIC, 4);
3500 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3501
3502 // Timestamp
3503 hdr->sourceWhen = 0; // TODO(all)
3504 hdr->rslibWhen = 0; // TODO(all)
3505 hdr->libRSWhen = 0; // TODO(all)
3506 hdr->libbccWhen = 0; // TODO(all)
3507
3508 // Current Memory Address (Saved for Recalculation)
3509 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3510 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3511 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3512
3513 // Relocation Table Offset and Entry Count
3514 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003515 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003516
Logan824dd0a2010-11-20 01:45:54 +08003517 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003518
3519 // Export Variable Table Offset and Entry Count
3520 hdr->exportVarsOffset = offset;
3521 hdr->exportVarsCount = mExportVars.size();
3522
3523 offset += hdr->exportVarsCount * sizeof(uint32_t);
3524
3525 // Export Function Table Offset and Entry Count
3526 hdr->exportFuncsOffset = offset;
3527 hdr->exportFuncsCount = mExportFuncs.size();
3528
3529 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3530
3531 // Export Pragmas Table Offset and Entry Count
3532 hdr->exportPragmasOffset = offset;
3533 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3534
3535 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3536
3537 // Code Offset and Size
3538
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003539 //#ifdef BCC_CODE_ADDR
3540 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003541 long pagesize = sysconf(_SC_PAGESIZE);
3542
3543 if (offset % pagesize > 0) {
3544 codeOffsetNeedPadding = true;
3545 offset += pagesize - (offset % pagesize);
3546 }
3547 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003548 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003549 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3550 codeOffsetNeedPadding = true;
3551 offset += 0x08 - (offset & 0x07);
3552 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003553 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003554
3555 hdr->codeOffset = offset;
3556 hdr->codeSize = MaxCodeSize;
3557
3558 offset += hdr->codeSize;
3559
3560 // Data (Global Variable) Offset and Size
3561 hdr->dataOffset = offset;
3562 hdr->dataSize = MaxGlobalVarSize;
3563
3564 offset += hdr->dataSize;
3565
3566 // Checksum
3567 hdr->checksum = 0; // Set Field checksum. TODO(all)
3568
3569 // Write Header
3570 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3571 sizeof(oBCCHeader), "Write oBCC header");
3572
Logan824dd0a2010-11-20 01:45:54 +08003573 // Write Relocation Entry Table
3574 {
3575 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003576
Logan824dd0a2010-11-20 01:45:54 +08003577 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3578
3579 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3580 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003581 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003582
3583 // Write Export Variables Table
3584 {
3585 uint32_t *record, *ptr;
3586
3587 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3588 ptr = record;
3589
3590 if (!record) {
3591 goto bail;
3592 }
3593
3594 for (ExportVarList::const_iterator I = mExportVars.begin(),
3595 E = mExportVars.end(); I != E; I++) {
3596 *ptr++ = reinterpret_cast<uint32_t>(*I);
3597 }
3598
3599 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3600 hdr->exportVarsCount * sizeof(uint32_t),
3601 "Write ExportVars");
3602
3603 free(record);
3604 }
3605
3606 // Write Export Functions Table
3607 {
3608 uint32_t *record, *ptr;
3609
3610 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3611 ptr = record;
3612
3613 if (!record) {
3614 goto bail;
3615 }
3616
3617 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3618 E = mExportFuncs.end(); I != E; I++) {
3619 *ptr++ = reinterpret_cast<uint32_t>(*I);
3620 }
3621
3622 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3623 hdr->exportFuncsCount * sizeof(uint32_t),
3624 "Write ExportFuncs");
3625
3626 free(record);
3627 }
3628
3629
3630 // TODO(all): Write Export Pragmas Table
3631#if 0
3632#else
3633 // Note: As long as we have comment out export pragmas table code,
3634 // we have to seek the position to correct offset.
3635
3636 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3637#endif
3638
3639 if (codeOffsetNeedPadding) {
3640 // requires additional padding
3641 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3642 }
3643
3644 // Write Generated Code and Global Variable
3645 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3646 "Write code and global variable");
3647
3648 goto close_return;
3649
3650 bail:
3651 if (ftruncate(mCacheFd, 0) != 0) {
3652 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3653 }
3654
3655 close_return:
3656 free(hdr);
3657 close(mCacheFd);
3658 mCacheFd = -1;
3659 return;
3660 }
3661
3662 // OpenCacheFile() returns fd of the cache file.
3663 // Input:
3664 // BCCchar *resName: Used to genCacheFileName()
3665 // bool createIfMissing: If false, turn off caching
3666 // Output:
3667 // returns fd: If -1: Failed
3668 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3669 // cache file's file descriptor
3670 // Note: openCacheFile() will check the cache file's validity,
3671 // such as Magic number, sourceWhen... dependencies.
3672 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3673 int fd, cc;
3674 struct stat fdStat, fileStat;
3675 bool readOnly = false;
3676
3677 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3678
3679 mCacheNew = false;
3680
3681 retry:
3682 /*
3683 * Try to open the cache file. If we've been asked to,
3684 * create it if it doesn't exist.
3685 */
3686 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3687 if (fd < 0) {
3688 fd = open(cacheFileName, O_RDONLY, 0);
3689 if (fd < 0) {
3690 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08003691 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003692 cacheFileName, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003693 mUseCache = false;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003694 }
3695 return fd;
3696 }
3697 readOnly = true;
3698 }
3699
3700 /*
3701 * Grab an exclusive lock on the cache file. If somebody else is
3702 * working on it, we'll block here until they complete.
3703 */
3704 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3705 cacheFileName, fd);
3706
3707 cc = flock(fd, LOCK_EX | LOCK_NB);
3708 if (cc != 0) {
3709 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3710 cc = flock(fd, LOCK_EX);
3711 }
3712
3713 if (cc != 0) {
3714 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3715 close(fd);
3716 return -1;
3717 }
3718 LOGV("bcc: locked cache file\n");
3719
3720 /*
3721 * Check to see if the fd we opened and locked matches the file in
3722 * the filesystem. If they don't, then somebody else unlinked ours
3723 * and created a new file, and we need to use that one instead. (If
3724 * we caught them between the unlink and the create, we'll get an
3725 * ENOENT from the file stat.)
3726 */
3727 cc = fstat(fd, &fdStat);
3728 if (cc != 0) {
3729 LOGE("Can't stat open file '%s'\n", cacheFileName);
3730 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3731 goto close_fail;
3732 }
3733 cc = stat(cacheFileName, &fileStat);
3734 if (cc != 0 ||
3735 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3736 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3737 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3738 flock(fd, LOCK_UN);
3739 close(fd);
3740 usleep(250 * 1000); // if something is hosed, don't peg machine
3741 goto retry;
3742 }
3743
3744 /*
3745 * We have the correct file open and locked. If the file size is zero,
3746 * then it was just created by us, and we want to fill in some fields
3747 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3748 * verify that the fields in the header match our expectations, and
3749 * reset the file if they don't.
3750 */
3751 if (fdStat.st_size == 0) {
3752 if (readOnly) { // The device is readOnly --> close_fail
3753 LOGW("bcc: file has zero length and isn't writable\n");
3754 goto close_fail;
3755 }
3756 /*cc = createEmptyHeader(fd);
3757 if (cc != 0)
3758 goto close_fail;
3759 */
3760 mCacheNew = true;
3761 LOGV("bcc: successfully initialized new cache file\n");
3762 } else {
3763 // Calculate sourceWhen
3764 // XXX
3765 uint32_t sourceWhen = 0;
3766 uint32_t rslibWhen = 0;
3767 uint32_t libRSWhen = 0;
3768 uint32_t libbccWhen = 0;
3769 if (!checkHeaderAndDependencies(fd,
3770 sourceWhen,
3771 rslibWhen,
3772 libRSWhen,
3773 libbccWhen)) {
3774 // If checkHeaderAndDependencies returns 0: FAILED
3775 // Will truncate the file and retry to createIfMissing the file
3776
3777 if (readOnly) { // Shouldn't be readonly.
3778 /*
3779 * We could unlink and rewrite the file if we own it or
3780 * the "sticky" bit isn't set on the directory. However,
3781 * we're not able to truncate it, which spoils things. So,
3782 * give up now.
3783 */
3784 if (createIfMissing) {
3785 LOGW("Cached file %s is stale and not writable\n",
3786 cacheFileName);
3787 }
3788 goto close_fail;
3789 }
3790
3791 /*
3792 * If we truncate the existing file before unlinking it, any
3793 * process that has it mapped will fail when it tries to touch
3794 * the pages? Probably OK because we use MAP_PRIVATE.
3795 */
3796 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3797 cacheFileName);
3798 if (ftruncate(fd, 0) != 0) {
3799 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3800 cacheFileName, strerror(errno));
3801 /* keep going */
3802 }
3803 if (unlink(cacheFileName) != 0) {
3804 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3805 cacheFileName, errno, strerror(errno));
3806 /* keep going; permission failure should probably be fatal */
3807 }
3808 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3809 flock(fd, LOCK_UN);
3810 close(fd);
3811 goto retry;
3812 } else {
3813 // Got cacheFile! Good to go.
3814 LOGV("Good cache file\n");
3815 }
3816 }
3817
3818 assert(fd >= 0);
3819 return fd;
3820
3821 close_fail:
3822 flock(fd, LOCK_UN);
3823 close(fd);
3824 return -1;
3825 } // End of openCacheFile()
3826
3827 char *genCacheFileName(const char *fileName, const char *subFileName) {
3828 char nameBuf[512];
3829 static const char kCachePath[] = "bcc-cache";
3830 char absoluteFile[sizeof(nameBuf)];
3831 const size_t kBufLen = sizeof(nameBuf) - 1;
3832 const char *dataRoot;
3833 char *cp;
3834
3835 // Get the absolute path of the raw/***.bc file.
3836 absoluteFile[0] = '\0';
3837 if (fileName[0] != '/') {
3838 /*
3839 * Generate the absolute path. This doesn't do everything it
3840 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3841 * the leading "./" out, but it'll do.
3842 */
3843 if (getcwd(absoluteFile, kBufLen) == NULL) {
3844 LOGE("Can't get CWD while opening raw/***.bc file\n");
3845 return NULL;
3846 }
3847 // TODO(srhines): strncat() is a bit dangerous
3848 strncat(absoluteFile, "/", kBufLen);
3849 }
3850 strncat(absoluteFile, fileName, kBufLen);
3851
3852 if (subFileName != NULL) {
3853 strncat(absoluteFile, "/", kBufLen);
3854 strncat(absoluteFile, subFileName, kBufLen);
3855 }
3856
3857 /* Turn the path into a flat filename by replacing
3858 * any slashes after the first one with '@' characters.
3859 */
3860 cp = absoluteFile + 1;
3861 while (*cp != '\0') {
3862 if (*cp == '/') {
3863 *cp = '@';
3864 }
3865 cp++;
3866 }
3867
3868 /* Build the name of the cache directory.
3869 */
3870 dataRoot = getenv("ANDROID_DATA");
3871 if (dataRoot == NULL)
3872 dataRoot = "/data";
3873 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3874
3875 /* Tack on the file name for the actual cache file path.
3876 */
3877 strncat(nameBuf, absoluteFile, kBufLen);
3878
3879 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3880 return strdup(nameBuf);
3881 }
3882
3883 /*
3884 * Read the oBCC header, verify it, then read the dependent section
3885 * and verify that data as well.
3886 *
3887 * On successful return, the file will be seeked immediately past the
3888 * oBCC header.
3889 */
3890 bool checkHeaderAndDependencies(int fd,
3891 uint32_t sourceWhen,
3892 uint32_t rslibWhen,
3893 uint32_t libRSWhen,
3894 uint32_t libbccWhen) {
3895 ssize_t actual;
3896 oBCCHeader optHdr;
3897 uint32_t val;
3898 uint8_t const *magic, *magicVer;
3899
3900 /*
3901 * Start at the start. The "bcc" header, when present, will always be
3902 * the first thing in the file.
3903 */
3904 if (lseek(fd, 0, SEEK_SET) != 0) {
3905 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3906 goto bail;
3907 }
3908
3909 /*
3910 * Read and do trivial verification on the bcc header. The header is
3911 * always in host byte order.
3912 */
3913 actual = read(fd, &optHdr, sizeof(optHdr));
3914 if (actual < 0) {
3915 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3916 goto bail;
3917 } else if (actual != sizeof(optHdr)) {
3918 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3919 (int) actual, sizeof(optHdr));
3920 goto bail;
3921 }
3922
3923 magic = optHdr.magic;
3924 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3925 /* not an oBCC file, or previous attempt was interrupted */
3926 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3927 magic[0], magic[1], magic[2], magic[3]);
3928 goto bail;
3929 }
3930
3931 magicVer = optHdr.magicVersion;
3932 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3933 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3934 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3935 goto bail;
3936 }
3937
3938 /*
3939 * Do the header flags match up with what we want?
3940 *
3941 * This is useful because it allows us to automatically regenerate
3942 * a file when settings change (e.g. verification is now mandatory),
3943 * but can cause difficulties if the thing we depend upon
3944 * were handled differently than the current options specify.
3945 *
3946 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3947 * by limiting the match mask.
3948 *
3949 * The only thing we really can't handle is incorrect byte-ordering.
3950 */
3951
3952 val = optHdr.sourceWhen;
3953 if (val && (val != sourceWhen)) {
3954 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3955 val, sourceWhen);
3956 goto bail;
3957 }
3958 val = optHdr.rslibWhen;
3959 if (val && (val != rslibWhen)) {
3960 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3961 val, rslibWhen);
3962 goto bail;
3963 }
3964 val = optHdr.libRSWhen;
3965 if (val && (val != libRSWhen)) {
3966 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3967 val, libRSWhen);
3968 goto bail;
3969 }
3970 val = optHdr.libbccWhen;
3971 if (val && (val != libbccWhen)) {
3972 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3973 val, libbccWhen);
3974 goto bail;
3975 }
3976
3977 return true;
3978
3979 bail:
3980 return false;
3981 }
3982
Zonr Chang932648d2010-10-13 22:23:56 +08003983};
3984// End of Class Compiler
3985////////////////////////////////////////////////////////////////////////////////
3986
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003987
3988bool Compiler::GlobalInitialized = false;
3989
Loganc0b9f652010-11-24 22:33:16 +08003990bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Loganad7e8e12010-11-22 20:43:43 +08003991
Zonr Chang932648d2010-10-13 22:23:56 +08003992// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003993llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3994
3995std::string Compiler::Triple;
3996
3997std::string Compiler::CPU;
3998
3999std::vector<std::string> Compiler::Features;
4000
Zonr Chang932648d2010-10-13 22:23:56 +08004001// The named of metadata node that pragma resides (should be synced with
4002// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004003const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
4004
Zonr Chang932648d2010-10-13 22:23:56 +08004005// The named of metadata node that export variable name resides (should be
4006// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004007const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
4008
Zonr Chang932648d2010-10-13 22:23:56 +08004009// The named of metadata node that export function name resides (should be
4010// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004011const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
4012
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004013struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08004014 //////////////////////////////////////////////////////////////////////////////
4015 // Part I. Compiler
4016 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004017 Compiler compiler;
4018
Zonr Chang932648d2010-10-13 22:23:56 +08004019 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004020 compiler.registerSymbolCallback(pFn, pContext);
4021 }
4022
Zonr Chang932648d2010-10-13 22:23:56 +08004023 //////////////////////////////////////////////////////////////////////////////
4024 // Part II. Logistics & Error handling
4025 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004026 BCCscript() {
4027 bccError = BCC_NO_ERROR;
4028 }
4029
4030 ~BCCscript() {
4031 }
4032
4033 void setError(BCCenum error) {
4034 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
4035 bccError = error;
4036 }
4037 }
4038
4039 BCCenum getError() {
4040 BCCenum result = bccError;
4041 bccError = BCC_NO_ERROR;
4042 return result;
4043 }
4044
4045 BCCenum bccError;
4046};
4047
4048
4049extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004050BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004051 return new BCCscript();
4052}
4053
4054extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004055BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004056 return script->getError();
4057}
4058
4059extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004060void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004061 delete script;
4062}
4063
4064extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004065void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004066 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08004067 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004068 script->registerSymbolCallback(pFn, pContext);
4069}
4070
4071extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004072int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08004073 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004074 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08004075}
4076
4077extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004078int bccReadBC(BCCscript *script,
4079 const BCCchar *bitcode,
4080 BCCint size,
4081 const BCCchar *resName) {
4082 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004083}
4084
4085extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004086void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08004087 const BCCchar *bitcode,
4088 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004089 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08004090}
4091
4092extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004093void bccLoadBinary(BCCscript *script) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08004094 int result = script->compiler.loadCacheFile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004095 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004096 script->setError(BCC_INVALID_OPERATION);
4097}
4098
4099extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004100void bccCompileBC(BCCscript *script) {
4101 {
4102#if defined(__arm__)
4103 android::StopWatch compileTimer("RenderScript compile time");
4104#endif
4105 int result = script->compiler.compile();
4106 if (result)
4107 script->setError(BCC_INVALID_OPERATION);
4108 }
4109}
4110
4111extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004112void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004113 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08004114 BCCsizei *length,
4115 BCCchar *infoLog) {
4116 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004117 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004118 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004119 *length = messageLength;
4120
4121 if (infoLog && maxLength > 0) {
4122 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4123 memcpy(infoLog, message, trimmedLength);
4124 infoLog[trimmedLength] = 0;
4125 }
4126}
4127
4128extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004129void bccGetScriptLabel(BCCscript *script,
4130 const BCCchar *name,
4131 BCCvoid **address) {
4132 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004133 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004134 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004135 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004136 script->setError(BCC_INVALID_VALUE);
4137}
4138
4139extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004140void bccGetExportVars(BCCscript *script,
4141 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004142 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004143 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004144 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4145}
4146
4147extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004148void bccGetExportFuncs(BCCscript *script,
4149 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004150 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004151 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004152 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4153}
4154
4155extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004156void bccGetPragmas(BCCscript *script,
4157 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004158 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004159 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004160 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4161}
4162
4163extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004164void bccGetFunctions(BCCscript *script,
4165 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004166 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004167 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004168 script->compiler.getFunctions(actualFunctionCount,
4169 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004170 functions);
4171}
4172
4173extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004174void bccGetFunctionBinary(BCCscript *script,
4175 BCCchar *function,
4176 BCCvoid **base,
4177 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004178 script->compiler.getFunctionBinary(function, base, length);
4179}
4180
4181struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004182 const Compiler *compiler;
4183 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004184};
4185
Zonr Chang932648d2010-10-13 22:23:56 +08004186} // namespace bcc