blob: 5cf30c7aadf984871cfe00708a7d42a72969c6c0 [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() {
Logan82e67012010-11-25 00:29:34 +0800910 if (mpCodeMem && mpCodeMem != MAP_FAILED) {
911 munmap(mpCodeMem, BCC_MMAP_IMG_SIZE);
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 }
Logan82e67012010-11-25 00:29:34 +0800916
917 mpCodeMem = 0;
918 mpGVMem = 0;
919
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700920 return;
921 }
Zonr Chang932648d2010-10-13 22:23:56 +0800922 };
923 // End of class CodeMemoryManager
924 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700925
Zonr Chang932648d2010-10-13 22:23:56 +0800926 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700927 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800928 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700929 mCodeMemMgr.reset(new CodeMemoryManager());
930 return mCodeMemMgr.get();
931 }
932
Zonr Chang932648d2010-10-13 22:23:56 +0800933 //////////////////////////////////////////////////////////////////////////////
934 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700935 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700936 public:
937 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
938 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
939
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800940 GlobalAddressMapTy mGlobalAddressMap;
941
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700942 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800943 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700944
Zonr Chang932648d2010-10-13 22:23:56 +0800945 // The JITInfo for the target we are compiling to
946 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700947
Zonr Chang932648d2010-10-13 22:23:56 +0800948 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700949
Zonr Chang932648d2010-10-13 22:23:56 +0800950 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700951
952 class EmittedFunctionCode {
953 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800954 // Beginning of the function's allocation.
955 void *FunctionBody;
956
957 // The address the function's code actually starts at.
958 void *Code;
959
960 // The size of the function code
961 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700962
963 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
964 };
Zonr Chang932648d2010-10-13 22:23:56 +0800965 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700966
Zonr Chang932648d2010-10-13 22:23:56 +0800967 typedef std::map<const std::string,
968 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700969 EmittedFunctionsMapTy mEmittedFunctions;
970
Zonr Chang932648d2010-10-13 22:23:56 +0800971 // This vector is a mapping from MBB ID's to their address. It is filled in
972 // by the StartMachineBasicBlock callback and queried by the
973 // getMachineBasicBlockAddress callback.
974 std::vector<uintptr_t> mMBBLocations;
975
976 // The constant pool for the current function.
977 llvm::MachineConstantPool *mpConstantPool;
978
979 // A pointer to the first entry in the constant pool.
980 void *mpConstantPoolBase;
981
982 // Addresses of individual constant pool entries.
983 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
984
985 // The jump tables for the current function.
986 llvm::MachineJumpTableInfo *mpJumpTable;
987
988 // A pointer to the first entry in the jump table.
989 void *mpJumpTableBase;
990
991 // When outputting a function stub in the context of some other function, we
992 // save BufferBegin/BufferEnd/CurBufferPtr here.
993 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
994
995 // These are the relocations that the function needs, as emitted.
996 std::vector<llvm::MachineRelocation> mRelocations;
997
Logan824dd0a2010-11-20 01:45:54 +0800998 std::vector<oBCCRelocEntry> mCachingRelocations;
999
Zonr Chang932648d2010-10-13 22:23:56 +08001000 // This vector is a mapping from Label ID's to their address.
1001 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
1002
1003 // Machine module info for exception informations
1004 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001005
Zonr Chang932648d2010-10-13 22:23:56 +08001006 // Replace an existing mapping for GV with a new address. This updates both
1007 // maps as required. If Addr is null, the entry for the global is removed
1008 // from the mappings.
1009 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
1010 if (Addr == NULL) {
1011 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001012 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
1013 void *OldVal;
1014
Zonr Chang932648d2010-10-13 22:23:56 +08001015 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001016 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001017 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001018 OldVal = I->second;
1019 mGlobalAddressMap.erase(I);
1020 }
1021
1022 return OldVal;
1023 }
1024
Zonr Chang932648d2010-10-13 22:23:56 +08001025 void *&CurVal = mGlobalAddressMap[GV];
1026 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001027
1028 CurVal = Addr;
1029
1030 return OldVal;
1031 }
1032
Zonr Chang932648d2010-10-13 22:23:56 +08001033 // Tell the execution engine that the specified global is at the specified
1034 // location. This is used internally as functions are JIT'd and as global
1035 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001036 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001037 void *&CurVal = mGlobalAddressMap[GV];
1038 assert((CurVal == 0 || Addr == 0) &&
1039 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001040 CurVal = Addr;
1041 return;
1042 }
1043
Zonr Chang932648d2010-10-13 22:23:56 +08001044 // This returns the address of the specified global value if it is has
1045 // already been codegen'd, otherwise it returns null.
1046 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001047 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001048 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
1049 }
1050
Zonr Chang932648d2010-10-13 22:23:56 +08001051 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
1052 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001053 MCP->getConstants();
1054
Zonr Chang932648d2010-10-13 22:23:56 +08001055 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001056 return 0;
1057
1058 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001059 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001060 llvm::MachineConstantPoolEntry CPE = Constants[i];
1061 unsigned int AlignMask = CPE.getAlignment() - 1;
1062 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +08001063 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001064 Size += mpTD->getTypeAllocSize(Ty);
1065 }
1066
1067 return Size;
1068 }
1069
Zonr Chang932648d2010-10-13 22:23:56 +08001070 // This function converts a Constant* into a GenericValue. The interesting
1071 // part is if C is a ConstantExpr.
1072 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
1073 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001074 return;
Zonr Chang932648d2010-10-13 22:23:56 +08001075 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
1076 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
1077 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001078
Zonr Chang932648d2010-10-13 22:23:56 +08001079 switch (CE->getOpcode()) {
1080 case llvm::Instruction::GetElementPtr: {
1081 // Compute the index
1082 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
1083 CE->op_end());
1084 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
1085 &Indices[0],
1086 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001087
Zonr Chang932648d2010-10-13 22:23:56 +08001088 GetConstantValue(Op0, Result);
1089 Result.PointerVal =
1090 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001091
Zonr Chang932648d2010-10-13 22:23:56 +08001092 return;
1093 }
1094 case llvm::Instruction::Trunc: {
1095 uint32_t BitWidth =
1096 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1097
1098 GetConstantValue(Op0, Result);
1099 Result.IntVal = Result.IntVal.trunc(BitWidth);
1100
1101 return;
1102 }
1103 case llvm::Instruction::ZExt: {
1104 uint32_t BitWidth =
1105 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1106
1107 GetConstantValue(Op0, Result);
1108 Result.IntVal = Result.IntVal.zext(BitWidth);
1109
1110 return;
1111 }
1112 case llvm::Instruction::SExt: {
1113 uint32_t BitWidth =
1114 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1115
1116 GetConstantValue(Op0, Result);
1117 Result.IntVal = Result.IntVal.sext(BitWidth);
1118
1119 return;
1120 }
1121 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001122 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001123 GetConstantValue(Op0, Result);
1124 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1125 return;
1126 }
1127 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001128 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001129 GetConstantValue(Op0, Result);
1130 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1131 return;
1132 }
1133 case llvm::Instruction::UIToFP: {
1134 GetConstantValue(Op0, Result);
1135 if (CE->getType()->isFloatTy())
1136 Result.FloatVal =
1137 static_cast<float>(Result.IntVal.roundToDouble());
1138 else if (CE->getType()->isDoubleTy())
1139 Result.DoubleVal = Result.IntVal.roundToDouble();
1140 else if (CE->getType()->isX86_FP80Ty()) {
1141 const uint64_t zero[] = { 0, 0 };
1142 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1143 apf.convertFromAPInt(Result.IntVal,
1144 false,
1145 llvm::APFloat::rmNearestTiesToEven);
1146 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001147 }
Zonr Chang932648d2010-10-13 22:23:56 +08001148 return;
1149 }
1150 case llvm::Instruction::SIToFP: {
1151 GetConstantValue(Op0, Result);
1152 if (CE->getType()->isFloatTy())
1153 Result.FloatVal =
1154 static_cast<float>(Result.IntVal.signedRoundToDouble());
1155 else if (CE->getType()->isDoubleTy())
1156 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1157 else if (CE->getType()->isX86_FP80Ty()) {
1158 const uint64_t zero[] = { 0, 0 };
1159 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1160 apf.convertFromAPInt(Result.IntVal,
1161 true,
1162 llvm::APFloat::rmNearestTiesToEven);
1163 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001164 }
Zonr Chang932648d2010-10-13 22:23:56 +08001165 return;
1166 }
1167 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001168 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001169 case llvm::Instruction::FPToSI: {
1170 uint32_t BitWidth =
1171 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001172
Zonr Chang932648d2010-10-13 22:23:56 +08001173 GetConstantValue(Op0, Result);
1174 if (Op0->getType()->isFloatTy())
1175 Result.IntVal =
1176 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1177 else if (Op0->getType()->isDoubleTy())
1178 Result.IntVal =
1179 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1180 BitWidth);
1181 else if (Op0->getType()->isX86_FP80Ty()) {
1182 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1183 uint64_t V;
1184 bool Ignored;
1185 apf.convertToInteger(&V,
1186 BitWidth,
1187 CE->getOpcode() == llvm::Instruction::FPToSI,
1188 llvm::APFloat::rmTowardZero,
1189 &Ignored);
1190 Result.IntVal = V; // endian?
1191 }
1192 return;
1193 }
1194 case llvm::Instruction::PtrToInt: {
1195 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1196
1197 GetConstantValue(Op0, Result);
1198 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1199 (Result.PointerVal));
1200
1201 return;
1202 }
1203 case llvm::Instruction::IntToPtr: {
1204 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1205
1206 GetConstantValue(Op0, Result);
1207 if (PtrWidth != Result.IntVal.getBitWidth())
1208 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1209 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1210
1211 Result.PointerVal =
1212 llvm::PointerTy(
1213 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1214
1215 return;
1216 }
1217 case llvm::Instruction::BitCast: {
1218 GetConstantValue(Op0, Result);
1219 const llvm::Type *DestTy = CE->getType();
1220
1221 switch (Op0->getType()->getTypeID()) {
1222 case llvm::Type::IntegerTyID: {
1223 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1224 if (DestTy->isFloatTy())
1225 Result.FloatVal = Result.IntVal.bitsToFloat();
1226 else if (DestTy->isDoubleTy())
1227 Result.DoubleVal = Result.IntVal.bitsToDouble();
1228 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001229 }
Zonr Chang932648d2010-10-13 22:23:56 +08001230 case llvm::Type::FloatTyID: {
1231 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1232 Result.IntVal.floatToBits(Result.FloatVal);
1233 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001234 }
Zonr Chang932648d2010-10-13 22:23:56 +08001235 case llvm::Type::DoubleTyID: {
1236 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1237 Result.IntVal.doubleToBits(Result.DoubleVal);
1238 break;
1239 }
1240 case llvm::Type::PointerTyID: {
1241 assert(DestTy->isPointerTy() && "Invalid bitcast");
1242 break; // getConstantValue(Op0) above already converted it
1243 }
1244 default: {
1245 llvm_unreachable("Invalid bitcast operand");
1246 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001247 }
Zonr Chang932648d2010-10-13 22:23:56 +08001248 return;
1249 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001250 case llvm::Instruction::Add:
1251 case llvm::Instruction::FAdd:
1252 case llvm::Instruction::Sub:
1253 case llvm::Instruction::FSub:
1254 case llvm::Instruction::Mul:
1255 case llvm::Instruction::FMul:
1256 case llvm::Instruction::UDiv:
1257 case llvm::Instruction::SDiv:
1258 case llvm::Instruction::URem:
1259 case llvm::Instruction::SRem:
1260 case llvm::Instruction::And:
1261 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001262 case llvm::Instruction::Xor: {
1263 llvm::GenericValue LHS, RHS;
1264 GetConstantValue(Op0, LHS);
1265 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001266
Zonr Chang932648d2010-10-13 22:23:56 +08001267 switch (Op0->getType()->getTypeID()) {
1268 case llvm::Type::IntegerTyID: {
1269 switch (CE->getOpcode()) {
1270 case llvm::Instruction::Add: {
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::Sub: {
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::Mul: {
1279 Result.IntVal = LHS.IntVal * RHS.IntVal;
1280 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001281 }
Zonr Chang932648d2010-10-13 22:23:56 +08001282 case llvm::Instruction::UDiv: {
1283 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1284 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001285 }
Zonr Chang932648d2010-10-13 22:23:56 +08001286 case llvm::Instruction::SDiv: {
1287 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1288 break;
1289 }
1290 case llvm::Instruction::URem: {
1291 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1292 break;
1293 }
1294 case llvm::Instruction::SRem: {
1295 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1296 break;
1297 }
1298 case llvm::Instruction::And: {
1299 Result.IntVal = LHS.IntVal & RHS.IntVal;
1300 break;
1301 }
1302 case llvm::Instruction::Or: {
1303 Result.IntVal = LHS.IntVal | RHS.IntVal;
1304 break;
1305 }
1306 case llvm::Instruction::Xor: {
1307 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1308 break;
1309 }
1310 default: {
1311 llvm_unreachable("Invalid integer opcode");
1312 }
1313 }
1314 break;
1315 }
1316 case llvm::Type::FloatTyID: {
1317 switch (CE->getOpcode()) {
1318 case llvm::Instruction::FAdd: {
1319 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1320 break;
1321 }
1322 case llvm::Instruction::FSub: {
1323 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1324 break;
1325 }
1326 case llvm::Instruction::FMul: {
1327 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1328 break;
1329 }
1330 case llvm::Instruction::FDiv: {
1331 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1332 break;
1333 }
1334 case llvm::Instruction::FRem: {
1335 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1336 break;
1337 }
1338 default: {
1339 llvm_unreachable("Invalid float opcode");
1340 }
1341 }
1342 break;
1343 }
1344 case llvm::Type::DoubleTyID: {
1345 switch (CE->getOpcode()) {
1346 case llvm::Instruction::FAdd: {
1347 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1348 break;
1349 }
1350 case llvm::Instruction::FSub: {
1351 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1352 break;
1353 }
1354 case llvm::Instruction::FMul: {
1355 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1356 break;
1357 }
1358 case llvm::Instruction::FDiv: {
1359 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1360 break;
1361 }
1362 case llvm::Instruction::FRem: {
1363 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1364 break;
1365 }
1366 default: {
1367 llvm_unreachable("Invalid double opcode");
1368 }
1369 }
1370 break;
1371 }
1372 case llvm::Type::X86_FP80TyID:
1373 case llvm::Type::PPC_FP128TyID:
1374 case llvm::Type::FP128TyID: {
1375 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1376 switch (CE->getOpcode()) {
1377 case llvm::Instruction::FAdd: {
1378 apfLHS.add(llvm::APFloat(RHS.IntVal),
1379 llvm::APFloat::rmNearestTiesToEven);
1380 break;
1381 }
1382 case llvm::Instruction::FSub: {
1383 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1384 llvm::APFloat::rmNearestTiesToEven);
1385 break;
1386 }
1387 case llvm::Instruction::FMul: {
1388 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1389 llvm::APFloat::rmNearestTiesToEven);
1390 break;
1391 }
1392 case llvm::Instruction::FDiv: {
1393 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1394 llvm::APFloat::rmNearestTiesToEven);
1395 break;
1396 }
1397 case llvm::Instruction::FRem: {
1398 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1399 llvm::APFloat::rmNearestTiesToEven);
1400 break;
1401 }
1402 default: {
1403 llvm_unreachable("Invalid long double opcode");
1404 }
1405 }
1406 Result.IntVal = apfLHS.bitcastToAPInt();
1407 break;
1408 }
1409 default: {
1410 llvm_unreachable("Bad add type!");
1411 }
1412 } // End switch (Op0->getType()->getTypeID())
1413 return;
1414 }
1415 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001416 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001417 }
1418 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001419
1420 std::string msg;
1421 llvm::raw_string_ostream Msg(msg);
1422 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001423 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001424 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001425
1426 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001427 case llvm::Type::FloatTyID: {
1428 Result.FloatVal =
1429 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001430 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001431 }
1432 case llvm::Type::DoubleTyID: {
1433 Result.DoubleVal =
1434 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001435 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001436 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001437 case llvm::Type::X86_FP80TyID:
1438 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001439 case llvm::Type::PPC_FP128TyID: {
1440 Result.IntVal =
1441 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001442 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001443 }
1444 case llvm::Type::IntegerTyID: {
1445 Result.IntVal =
1446 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001447 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001448 }
1449 case llvm::Type::PointerTyID: {
1450 switch (C->getValueID()) {
1451 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001452 Result.PointerVal = NULL;
1453 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001454 }
1455 case llvm::Value::FunctionVal: {
1456 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1457 Result.PointerVal =
1458 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001459 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001460 }
1461 case llvm::Value::GlobalVariableVal: {
1462 const llvm::GlobalVariable *GV =
1463 static_cast<const llvm::GlobalVariable*>(C);
1464 Result.PointerVal =
1465 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001466 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001467 }
1468 case llvm::Value::BlockAddressVal: {
1469 assert(false && "JIT does not support address-of-label yet!");
1470 }
1471 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001472 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001473 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001474 }
1475 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001476 }
1477 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001478 std::string msg;
1479 llvm::raw_string_ostream Msg(msg);
1480 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001481 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001482 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001483 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001484 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001485 return;
1486 }
1487
Zonr Chang932648d2010-10-13 22:23:56 +08001488 // Stores the data in @Val of type @Ty at address @Addr.
1489 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001490 const llvm::Type *Ty) {
1491 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1492
Zonr Chang932648d2010-10-13 22:23:56 +08001493 switch (Ty->getTypeID()) {
1494 case llvm::Type::IntegerTyID: {
1495 const llvm::APInt &IntVal = Val.IntVal;
1496 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1497 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001498
Zonr Chang932648d2010-10-13 22:23:56 +08001499 const uint8_t *Src =
1500 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001501
Zonr Chang932648d2010-10-13 22:23:56 +08001502 if (llvm::sys::isLittleEndianHost()) {
1503 // Little-endian host - the source is ordered from LSB to MSB.
1504 // Order the destination from LSB to MSB: Do a straight copy.
1505 memcpy(Addr, Src, StoreBytes);
1506 } else {
1507 // Big-endian host - the source is an array of 64 bit words
1508 // ordered from LSW to MSW.
1509 //
1510 // Each word is ordered from MSB to LSB.
1511 //
1512 // Order the destination from MSB to LSB:
1513 // Reverse the word order, but not the bytes in a word.
1514 unsigned int i = StoreBytes;
1515 while (i > sizeof(uint64_t)) {
1516 i -= sizeof(uint64_t);
1517 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1518 Src,
1519 sizeof(uint64_t));
1520 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001521 }
Zonr Chang932648d2010-10-13 22:23:56 +08001522 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001523 }
1524 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001525 }
1526 case llvm::Type::FloatTyID: {
1527 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001528 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001529 }
1530 case llvm::Type::DoubleTyID: {
1531 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001532 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001533 }
1534 case llvm::Type::X86_FP80TyID: {
1535 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001536 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001537 }
1538 case llvm::Type::PointerTyID: {
1539 // Ensure 64 bit target pointers are fully initialized on 32 bit
1540 // hosts.
1541 if (StoreBytes != sizeof(llvm::PointerTy))
1542 memset(Addr, 0, StoreBytes);
1543 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001544 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001545 }
1546 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001547 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001548 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001549 }
1550
Zonr Chang932648d2010-10-13 22:23:56 +08001551 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1552 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1553 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001554
1555 return;
1556 }
1557
Zonr Chang932648d2010-10-13 22:23:56 +08001558 // Recursive function to apply a @Constant value into the specified memory
1559 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001560 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001561 switch (C->getValueID()) {
1562 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001563 // Nothing to do
1564 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001565 }
1566 case llvm::Value::ConstantVectorVal: {
1567 // dynamic cast may hurt performance
1568 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001569
Zonr Chang932648d2010-10-13 22:23:56 +08001570 unsigned int ElementSize = mpTD->getTypeAllocSize
1571 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001572
Zonr Chang932648d2010-10-13 22:23:56 +08001573 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1574 InitializeConstantToMemory(
1575 CP->getOperand(i),
1576 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001577 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001578 }
1579 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001580 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1581 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001582 }
1583 case llvm::Value::ConstantArrayVal: {
1584 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1585 unsigned int ElementSize = mpTD->getTypeAllocSize
1586 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001587
Zonr Chang932648d2010-10-13 22:23:56 +08001588 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1589 InitializeConstantToMemory(
1590 CPA->getOperand(i),
1591 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1592 break;
1593 }
1594 case llvm::Value::ConstantStructVal: {
1595 const llvm::ConstantStruct *CPS =
1596 static_cast<const llvm::ConstantStruct*>(C);
1597 const llvm::StructLayout *SL = mpTD->getStructLayout
1598 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001599
Zonr Chang932648d2010-10-13 22:23:56 +08001600 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1601 InitializeConstantToMemory(
1602 CPS->getOperand(i),
1603 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1604 break;
1605 }
1606 default: {
1607 if (C->getType()->isFirstClassType()) {
1608 llvm::GenericValue Val;
1609 GetConstantValue(C, Val);
1610 StoreValueToMemory(Val, Addr, C->getType());
1611 } else {
1612 llvm_unreachable("Unknown constant type to initialize memory "
1613 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001614 }
1615 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001616 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001617 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001618 return;
1619 }
1620
1621 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001622 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001623 return;
1624
Zonr Chang932648d2010-10-13 22:23:56 +08001625 // Constant pool address resolution is handled by the target itself in ARM
1626 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001627#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001628 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1629 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001630
Zonr Chang932648d2010-10-13 22:23:56 +08001631 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001632 return;
1633
1634 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1635 unsigned Align = MCP->getConstantPoolAlignment();
1636
1637 mpConstantPoolBase = allocateSpace(Size, Align);
1638 mpConstantPool = MCP;
1639
Zonr Chang932648d2010-10-13 22:23:56 +08001640 if (mpConstantPoolBase == NULL)
1641 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001642
1643 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001644 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001645 llvm::MachineConstantPoolEntry CPE = Constants[i];
1646 unsigned AlignMask = CPE.getAlignment() - 1;
1647 Offset = (Offset + AlignMask) & ~AlignMask;
1648
1649 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1650 mConstPoolAddresses.push_back(CAddr);
1651
Zonr Chang932648d2010-10-13 22:23:56 +08001652 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001653 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001654 ("Initialize memory with machine specific constant pool"
1655 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001656
1657 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1658
1659 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1660 Offset += mpTD->getTypeAllocSize(Ty);
1661 }
1662#endif
1663 return;
1664 }
1665
1666 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001667 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001668 return;
1669
Zonr Chang932648d2010-10-13 22:23:56 +08001670 const std::vector<llvm::MachineJumpTableEntry> &JT =
1671 MJTI->getJumpTables();
1672 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001673 return;
1674
1675 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001676 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001677 NumEntries += JT[i].MBBs.size();
1678
1679 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1680
Zonr Chang932648d2010-10-13 22:23:56 +08001681 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001682 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001683 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001684
1685 return;
1686 }
1687
1688 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001689 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001690 return;
1691
Zonr Chang932648d2010-10-13 22:23:56 +08001692 const std::vector<llvm::MachineJumpTableEntry> &JT =
1693 MJTI->getJumpTables();
1694 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001695 return;
1696
Zonr Chang932648d2010-10-13 22:23:56 +08001697 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1698 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1699 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001700
Zonr Chang932648d2010-10-13 22:23:56 +08001701 // For each jump table, map each target in the jump table to the
1702 // address of an emitted MachineBasicBlock.
1703 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1704 for (int i = 0, ie = JT.size(); i != ie; i++) {
1705 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1706 // Store the address of the basic block for this jump table slot in the
1707 // memory we allocated for the jump table in 'initJumpTableInfo'
1708 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001709 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1710 }
1711 }
1712
Zonr Chang932648d2010-10-13 22:23:56 +08001713 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1714 bool MayNeedFarStub) {
1715 switch (V->getValueID()) {
1716 case llvm::Value::FunctionVal: {
1717 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001718
Zonr Chang932648d2010-10-13 22:23:56 +08001719 // If we have code, go ahead and return that.
1720 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1721 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001722
Zonr Chang932648d2010-10-13 22:23:56 +08001723 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1724 // Return the function stub if it's already created.
1725 // We do this first so that:
1726 // we're returning the same address for the function as any
1727 // previous call.
1728 //
1729 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1730 // guaranteed to be close enough to call.
1731 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001732
Zonr Chang932648d2010-10-13 22:23:56 +08001733 // If we know the target can handle arbitrary-distance calls, try to
1734 // return a direct pointer.
1735 if (!MayNeedFarStub) {
1736 //
1737 // x86_64 architecture may encounter the bug:
1738 // http://llvm.org/bugs/show_bug.cgi?id=5201
1739 // which generate instruction "call" instead of "callq".
1740 //
1741 // And once the real address of stub is greater than 64-bit
1742 // long, the replacement will truncate to 32-bit resulting a
1743 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001744#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001745 // If this is an external function pointer, we can force the JIT
1746 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001747 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1748 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1749 // Changing to false because wanting to allow later calls to
1750 // mpTJI->relocate() without aborting. For caching purpose
1751 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001752#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001753 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001754
Zonr Chang932648d2010-10-13 22:23:56 +08001755 // Otherwise, we may need a to emit a stub, and, conservatively, we
1756 // always do so.
1757 return GetLazyFunctionStub(F);
1758 break;
1759 }
1760 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001761 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1762 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001763 }
1764 case llvm::Value::GlobalAliasVal: {
1765 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1766 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001767
Zonr Chang932648d2010-10-13 22:23:56 +08001768 switch (GV->getValueID()) {
1769 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001770 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001771 // code-gen'd?
1772 return GetPointerToFunction(
1773 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001774 /* AbortOnFailure = */false);
1775 // Changing to false because wanting to allow later calls to
1776 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001777 break;
1778 }
1779 case llvm::Value::GlobalVariableVal: {
1780 if (void *P = mGlobalAddressMap[GV])
1781 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001782
Zonr Chang932648d2010-10-13 22:23:56 +08001783 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1784 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001785
Zonr Chang932648d2010-10-13 22:23:56 +08001786 return mGlobalAddressMap[GV];
1787 break;
1788 }
1789 case llvm::Value::GlobalAliasVal: {
1790 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001791 }
1792 }
1793 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001794 }
1795 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001796 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001797 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001798 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001799 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001800 }
1801
Zonr Chang932648d2010-10-13 22:23:56 +08001802 // If the specified function has been code-gen'd, return a pointer to the
1803 // function. If not, compile it, or use a stub to implement lazy compilation
1804 // if available.
1805 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1806 // If we have already code generated the function, just return the
1807 // address.
1808 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001809 return Addr;
1810
Zonr Chang932648d2010-10-13 22:23:56 +08001811 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001812 return GetLazyFunctionStub(F);
1813 }
1814
Zonr Chang932648d2010-10-13 22:23:56 +08001815 typedef llvm::DenseMap<const llvm::Function*,
1816 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001817 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1818
Zonr Chang932648d2010-10-13 22:23:56 +08001819 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001820 return mFunctionToLazyStubMap.lookup(F);
1821 }
1822
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001823 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001824 void *GetLazyFunctionStub(llvm::Function *F) {
1825 // If we already have a lazy stub for this function, recycle it.
1826 void *&Stub = mFunctionToLazyStubMap[F];
1827 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001828 return Stub;
1829
Zonr Chang932648d2010-10-13 22:23:56 +08001830 // In any cases, we should NOT resolve function at runtime (though we are
1831 // able to). We resolve this right now.
1832 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001833 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1834 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1835 // Changing to false because wanting to allow later calls to
1836 // mpTJI->relocate() without aborting. For caching purpose
1837 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001838
Zonr Chang932648d2010-10-13 22:23:56 +08001839 // Codegen a new stub, calling the actual address of the external
1840 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001841 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1842 startGVStub(F, SL.Size, SL.Alignment);
1843 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1844 finishGVStub();
1845
Zonr Chang932648d2010-10-13 22:23:56 +08001846 // We really want the address of the stub in the GlobalAddressMap for the
1847 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001848 UpdateGlobalMapping(F, Stub);
1849
Zonr Chang932648d2010-10-13 22:23:56 +08001850 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001851 PendingFunctions.insert(F);
1852 else
Zonr Chang932648d2010-10-13 22:23:56 +08001853 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1854 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001855
1856 return Stub;
1857 }
1858
Zonr Chang932648d2010-10-13 22:23:56 +08001859 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1860 void *Addr = GetPointerToGlobalIfAvailable(F);
1861 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001862 return Addr;
1863
1864 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1865 "Internal error: only external defined function routes here!");
1866
Zonr Chang932648d2010-10-13 22:23:56 +08001867 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001868 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001869 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001870
Zonr Chang932648d2010-10-13 22:23:56 +08001871 // If we resolved the symbol to a null address (eg. a weak external)
1872 // return a null pointer let the application handle it.
1873 if (Addr == NULL) {
1874 if (AbortOnFailure)
1875 llvm::report_fatal_error("Could not resolve external function "
1876 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001877 else
1878 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001879 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001880
1881 AddGlobalMapping(F, Addr);
1882
1883 return Addr;
1884 }
1885
Zonr Chang932648d2010-10-13 22:23:56 +08001886 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001887 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001888 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001889 return Addr;
1890
Zonr Chang932648d2010-10-13 22:23:56 +08001891 if (mpSymbolLookupFn)
1892 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001893 return Addr;
1894
Zonr Chang932648d2010-10-13 22:23:56 +08001895 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001896 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001897 "' which could not be resolved!");
1898
1899 return NULL;
1900 }
1901
Zonr Chang932648d2010-10-13 22:23:56 +08001902 // Return the address of the specified global variable, possibly emitting it
1903 // to memory if needed. This is used by the Emitter.
1904 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1905 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1906 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001907 return Ptr;
1908
Zonr Chang932648d2010-10-13 22:23:56 +08001909 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1910 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001911 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1912 AddGlobalMapping(GV, Ptr);
1913 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001914 // If the global hasn't been emitted to memory yet, allocate space and
1915 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001916 Ptr = GetMemoryForGV(GV);
1917 AddGlobalMapping(GV, Ptr);
1918 EmitGlobalVariable(GV);
1919 }
1920
1921 return Ptr;
1922 }
1923
Zonr Chang932648d2010-10-13 22:23:56 +08001924 // This method abstracts memory allocation of global variable so that the
1925 // JIT can allocate thread local variables depending on the target.
1926 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1927 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001928
Zonr Chang932648d2010-10-13 22:23:56 +08001929 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001930 size_t S = mpTD->getTypeAllocSize(GlobalType);
1931 size_t A = mpTD->getPreferredAlignment(GV);
1932
Zonr Chang932648d2010-10-13 22:23:56 +08001933 if (GV->isThreadLocal()) {
1934 // We can support TLS by
1935 //
1936 // Ptr = TJI.allocateThreadLocalMemory(S);
1937 //
1938 // But I tend not to.
1939 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001940 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001941 ("Compilation of Thread Local Storage (TLS) is disabled!");
1942
Zonr Chang932648d2010-10-13 22:23:56 +08001943 } else if (mpTJI->allocateSeparateGVMemory()) {
1944 if (A <= 8) {
1945 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001946 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001947 // Allocate (S + A) bytes of memory, then use an aligned pointer
1948 // within that space.
1949 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001950 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001951 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1952 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001953 }
1954 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001955 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001956 }
1957
1958 return Ptr;
1959 }
1960
1961 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001962 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001963
Zonr Chang932648d2010-10-13 22:23:56 +08001964 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001965 llvm::report_fatal_error
1966 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001967
Zonr Chang932648d2010-10-13 22:23:56 +08001968 if (GA == NULL) {
1969 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001970 GA = GetMemoryForGV(GV);
1971 AddGlobalMapping(GV, GA);
1972 }
1973
1974 InitializeConstantToMemory(GV->getInitializer(), GA);
1975
Zonr Chang932648d2010-10-13 22:23:56 +08001976 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001977 return;
1978 }
1979
1980 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1981 > GlobalToIndirectSymMapTy;
1982 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1983
Zonr Chang932648d2010-10-13 22:23:56 +08001984 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1985 // Make sure GV is emitted first, and create a stub containing the fully
1986 // resolved address.
1987 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001988
Zonr Chang932648d2010-10-13 22:23:56 +08001989 // If we already have a stub for this global variable, recycle it.
1990 void *&IndirectSym = GlobalToIndirectSymMap[V];
1991 // Otherwise, codegen a new indirect symbol.
1992 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001993 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1994
1995 return IndirectSym;
1996 }
1997
Zonr Chang932648d2010-10-13 22:23:56 +08001998 // This is the equivalent of FunctionToLazyStubMap for external functions.
1999 //
2000 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
2001 // It's actually here to make it more likely that far calls
2002 // succeed, but no single stub can guarantee that. I'll
2003 // remove this in a subsequent checkin when I actually fix
2004 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002005 std::map<void*, void*> ExternalFnToStubMap;
2006
Zonr Chang932648d2010-10-13 22:23:56 +08002007 // Return a stub for the function at the specified address.
2008 void *GetExternalFunctionStub(void *FnAddr) {
2009 void *&Stub = ExternalFnToStubMap[FnAddr];
2010 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002011 return Stub;
2012
2013 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2014 startGVStub(0, SL.Size, SL.Alignment);
2015 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
2016 finishGVStub();
2017
2018 return Stub;
2019 }
2020
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002021#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002022 const llvm::MCAsmInfo *mpAsmInfo;
2023 const llvm::MCDisassembler *mpDisassmbler;
2024 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002025
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002026 class BufferMemoryObject : public llvm::MemoryObject {
2027 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002028 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002029 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002030
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002031 public:
2032 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
2033 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002034
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002035 uint64_t getBase() const { return 0; }
2036 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002037
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002038 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002039 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002040 return -1;
2041 *Byte = mBytes[Addr];
2042 return 0;
2043 }
2044 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002045
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002046 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002047 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002048 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08002049 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002050#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002051 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08002052 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
2053 ErrorInfo,
2054 llvm::raw_fd_ostream::F_Append);
2055 if (!ErrorInfo.empty()) { // some errors occurred
2056 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002057 delete OS;
2058 return;
2059 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002060#else
2061 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002062#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002063 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
2064 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002065
Zonr Chang932648d2010-10-13 22:23:56 +08002066 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002067 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08002068 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002069 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08002070 if (mpIP == NULL)
2071 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
2072 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002073
Zonr Chang932648d2010-10-13 22:23:56 +08002074 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
2075 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002076 uint64_t Size;
2077 uint64_t Index;
2078
Zonr Chang932648d2010-10-13 22:23:56 +08002079 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002080 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002081
Zonr Chang932648d2010-10-13 22:23:56 +08002082 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2083 /* REMOVED */ llvm::nulls())) {
2084 (*OS).indent(4)
2085 .write("0x", 2)
2086 .write_hex((uint32_t) Start + Index)
2087 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002088 mpIP->printInst(&Inst, *OS);
2089 *OS << "\n";
2090 } else {
2091 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002092 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002093 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002094 }
2095
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002096 *OS << "\n";
2097 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002098
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002099#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002100 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002101 OS->close();
2102 delete OS;
2103#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002104 return;
2105 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002106#else
Zonr Chang932648d2010-10-13 22:23:56 +08002107 inline void Disassemble(const std::string &Name, uint8_t *Start,
2108 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002109 return;
2110 }
Zonr Chang932648d2010-10-13 22:23:56 +08002111#endif // defined(USE_DISASSEMBLER)
2112
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002113 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002114 // Resolver to undefined symbol in CodeEmitter
2115 BCCSymbolLookupFn mpSymbolLookupFn;
2116 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002117
2118 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002119 // Will take the ownership of @MemMgr
2120 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2121 : mpMemMgr(pMemMgr),
2122 mpTarget(NULL),
2123 mpTJI(NULL),
2124 mpTD(NULL),
2125 mpCurEmitFunction(NULL),
2126 mpConstantPool(NULL),
2127 mpJumpTable(NULL),
2128 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002129#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002130 mpAsmInfo(NULL),
2131 mpDisassmbler(NULL),
2132 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002133#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002134 mpSymbolLookupFn(NULL),
2135 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002136 return;
2137 }
2138
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002139 inline global_addresses_const_iterator global_address_begin() const {
2140 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002141 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002142 inline global_addresses_const_iterator global_address_end() const {
2143 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002144 }
2145
Logan824dd0a2010-11-20 01:45:54 +08002146 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2147 return mCachingRelocations;
2148 }
2149
Zonr Chang932648d2010-10-13 22:23:56 +08002150 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002151 mpSymbolLookupFn = pFn;
2152 mpSymbolLookupContext = pContext;
2153 return;
2154 }
2155
Zonr Chang932648d2010-10-13 22:23:56 +08002156 void setTargetMachine(llvm::TargetMachine &TM) {
2157 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002158 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002159 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002160 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002161 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002162 mpTD = TM.getTargetData();
2163
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002164 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2165
2166 return;
2167 }
2168
Zonr Chang932648d2010-10-13 22:23:56 +08002169 // This callback is invoked when the specified function is about to be code
2170 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002171 void startFunction(llvm::MachineFunction &F) {
2172 uintptr_t ActualSize = 0;
2173
2174 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002175
2176 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2177 // MachineCodeEmitter, which is the super class of the class
2178 // JITCodeEmitter.
2179 //
2180 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2181 // allocated for this code buffer.
2182 //
2183 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2184 // code. This is guranteed to be in the range
2185 // [BufferBegin, BufferEnd]. If this pointer is at
2186 // BufferEnd, it will never move due to code emission, and
2187 // all code emission requests will be ignored (this is the
2188 // buffer overflow condition).
2189 BufferBegin = CurBufferPtr =
2190 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002191 BufferEnd = BufferBegin + ActualSize;
2192
Zonr Chang932648d2010-10-13 22:23:56 +08002193 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002194 mpCurEmitFunction = new EmittedFunctionCode();
2195 mpCurEmitFunction->FunctionBody = BufferBegin;
2196
Zonr Chang932648d2010-10-13 22:23:56 +08002197 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002198 emitAlignment(16);
2199
2200 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002201 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002202 initJumpTableInfo(MJTI);
2203
Zonr Chang932648d2010-10-13 22:23:56 +08002204 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002205 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2206
2207 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2208
2209 mpCurEmitFunction->Code = CurBufferPtr;
2210
2211 mMBBLocations.clear();
2212
2213 return;
2214 }
2215
Zonr Chang932648d2010-10-13 22:23:56 +08002216 // This callback is invoked when the specified function has finished code
2217 // generation. If a buffer overflow has occurred, this method returns true
2218 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002219 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002220 if (CurBufferPtr == BufferEnd) {
2221 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002222 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2223 return false;
2224 }
2225
Zonr Chang932648d2010-10-13 22:23:56 +08002226 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002227 emitJumpTableInfo(MJTI);
2228
Zonr Chang932648d2010-10-13 22:23:56 +08002229 // FnStart is the start of the text, not the start of the constant pool
2230 // and other per-function data.
2231 uint8_t *FnStart =
2232 reinterpret_cast<uint8_t*>(
2233 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002234
Zonr Chang932648d2010-10-13 22:23:56 +08002235 // FnEnd is the end of the function's machine code.
2236 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002237
Zonr Chang932648d2010-10-13 22:23:56 +08002238 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002239 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2240
Zonr Chang932648d2010-10-13 22:23:56 +08002241 // Resolve the relocations to concrete pointers.
2242 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2243 llvm::MachineRelocation &MR = mRelocations[i];
2244 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002245
Zonr Chang932648d2010-10-13 22:23:56 +08002246 if (!MR.letTargetResolve()) {
2247 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002248 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002249
2250 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002251 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002252 }
2253
Zonr Chang932648d2010-10-13 22:23:56 +08002254 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002255 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2256 BufferBegin
2257 + MR.getMachineCodeOffset(),
2258 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002259 } else if (MR.isIndirectSymbol()) {
2260 ResultPtr =
2261 GetPointerToGVIndirectSym(
2262 MR.getGlobalValue(),
2263 BufferBegin + MR.getMachineCodeOffset());
2264 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002265 ResultPtr =
2266 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002267 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002268 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002269 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002270 } else {
2271 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2272 ResultPtr =
2273 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2274 }
2275
Logan824dd0a2010-11-20 01:45:54 +08002276 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2277 // TODO(logan): Cache external symbol relocation entry.
2278 // Currently, we are not caching them. But since Android
2279 // system is using prelink, it is not a problem.
2280
2281 // Cache the relocation result address
2282 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002283 oBCCRelocEntry(MR.getRelocationType(),
2284 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002285 ResultPtr));
2286 }
2287
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002288 MR.setResultPointer(ResultPtr);
2289 }
2290 }
2291
2292 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2293 mpMemMgr->getGOTBase());
2294 }
2295
2296 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002297 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2298 // global variables that were referenced in the relocations.
2299 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002300 return false;
2301
Zonr Chang932648d2010-10-13 22:23:56 +08002302 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002303 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2304 BufferBegin = CurBufferPtr = 0;
2305
Zonr Chang932648d2010-10-13 22:23:56 +08002306 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002307 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2308 mpCurEmitFunction = NULL;
2309
2310 mRelocations.clear();
2311 mConstPoolAddresses.clear();
2312
Zonr Chang932648d2010-10-13 22:23:56 +08002313 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002314 mpMMI->EndFunction();
2315
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002316 updateFunctionStub(F.getFunction());
2317
Zonr Chang932648d2010-10-13 22:23:56 +08002318 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002319 mpMemMgr->setMemoryExecutable();
2320
2321 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2322
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002323 return false;
2324 }
2325
Zonr Chang932648d2010-10-13 22:23:56 +08002326 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002327 unsigned Alignment) {
2328 mpSavedBufferBegin = BufferBegin;
2329 mpSavedBufferEnd = BufferEnd;
2330 mpSavedCurBufferPtr = CurBufferPtr;
2331
2332 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2333 Alignment);
2334 BufferEnd = BufferBegin + StubSize + 1;
2335
2336 return;
2337 }
2338
Zonr Chang932648d2010-10-13 22:23:56 +08002339 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002340 mpSavedBufferBegin = BufferBegin;
2341 mpSavedBufferEnd = BufferEnd;
2342 mpSavedCurBufferPtr = CurBufferPtr;
2343
Zonr Chang932648d2010-10-13 22:23:56 +08002344 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002345 BufferEnd = BufferBegin + StubSize + 1;
2346
2347 return;
2348 }
2349
2350 void finishGVStub() {
2351 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2352
Zonr Chang932648d2010-10-13 22:23:56 +08002353 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002354 BufferBegin = mpSavedBufferBegin;
2355 BufferEnd = mpSavedBufferEnd;
2356 CurBufferPtr = mpSavedCurBufferPtr;
2357
2358 return;
2359 }
2360
Zonr Chang932648d2010-10-13 22:23:56 +08002361 // Allocates and fills storage for an indirect GlobalValue, and returns the
2362 // address.
2363 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002364 const uint8_t *Buffer, size_t Size,
2365 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002366 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002367 memcpy(IndGV, Buffer, Size);
2368 return IndGV;
2369 }
2370
Zonr Chang932648d2010-10-13 22:23:56 +08002371 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002372 void emitLabel(llvm::MCSymbol *Label) {
2373 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002374 return;
2375 }
2376
Zonr Chang932648d2010-10-13 22:23:56 +08002377 // Allocate memory for a global. Unlike allocateSpace, this method does not
2378 // allocate memory in the current output buffer, because a global may live
2379 // longer than the current function.
2380 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2381 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002382 return mpMemMgr->allocateGlobal(Size, Alignment);
2383 }
2384
Zonr Chang932648d2010-10-13 22:23:56 +08002385 // This should be called by the target when a new basic block is about to be
2386 // emitted. This way the MCE knows where the start of the block is, and can
2387 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002388 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002389 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002390 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2391 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2392 return;
2393 }
2394
Zonr Chang932648d2010-10-13 22:23:56 +08002395 // Whenever a relocatable address is needed, it should be noted with this
2396 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002397 void addRelocation(const llvm::MachineRelocation &MR) {
2398 mRelocations.push_back(MR);
2399 return;
2400 }
2401
Zonr Chang932648d2010-10-13 22:23:56 +08002402 // Return the address of the @Index entry in the constant pool that was
2403 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002404 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2405 assert(Index < mpConstantPool->getConstants().size() &&
2406 "Invalid constant pool index!");
2407 return mConstPoolAddresses[Index];
2408 }
2409
Zonr Chang932648d2010-10-13 22:23:56 +08002410 // Return the address of the jump table with index @Index in the function
2411 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002412 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002413 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002414 mpJumpTable->getJumpTables();
2415
Zonr Chang932648d2010-10-13 22:23:56 +08002416 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002417
2418 unsigned int Offset = 0;
2419 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2420
Zonr Chang932648d2010-10-13 22:23:56 +08002421 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002422 Offset += JT[i].MBBs.size();
2423 Offset *= EntrySize;
2424
Zonr Chang932648d2010-10-13 22:23:56 +08002425 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002426 }
2427
Zonr Chang932648d2010-10-13 22:23:56 +08002428 // Return the address of the specified MachineBasicBlock, only usable after
2429 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002430 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2431 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002432 mMBBLocations[MBB->getNumber()] &&
2433 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002434 return mMBBLocations[MBB->getNumber()];
2435 }
2436
Zonr Chang932648d2010-10-13 22:23:56 +08002437 // Return the address of the specified LabelID, only usable after the
2438 // LabelID has been emitted.
2439 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002440 assert(mLabelLocations.count(Label) && "Label not emitted!");
2441 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002442 }
2443
Zonr Chang932648d2010-10-13 22:23:56 +08002444 // Specifies the MachineModuleInfo object. This is used for exception
2445 // handling purposes.
2446 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002447 mpMMI = Info;
2448 return;
2449 }
2450
Zonr Chang932648d2010-10-13 22:23:56 +08002451 void updateFunctionStub(const llvm::Function *F) {
2452 // Get the empty stub we generated earlier.
2453 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002454 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002455 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002456 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002457 else
2458 return;
2459
Zonr Chang932648d2010-10-13 22:23:56 +08002460 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002461
2462 assert(Addr != Stub &&
2463 "Function must have non-stub address to be updated.");
2464
Zonr Chang932648d2010-10-13 22:23:56 +08002465 // Tell the target jit info to rewrite the stub at the specified address,
2466 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002467 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2468 startGVStub(Stub, SL.Size);
2469 mpTJI->emitFunctionStub(F, Addr, *this);
2470 finishGVStub();
2471
Zonr Chang932648d2010-10-13 22:23:56 +08002472 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2473 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002474
2475 PendingFunctions.erase(I);
2476
2477 return;
2478 }
2479
Zonr Chang932648d2010-10-13 22:23:56 +08002480 // Once you finish the compilation on a translation unit, you can call this
2481 // function to recycle the memory (which is used at compilation time and not
2482 // needed for runtime).
2483 //
2484 // NOTE: You should not call this funtion until the code-gen passes for a
2485 // given module is done. Otherwise, the results is undefined and may
2486 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002487 void releaseUnnecessary() {
2488 mMBBLocations.clear();
2489 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002490 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002491 mFunctionToLazyStubMap.clear();
2492 GlobalToIndirectSymMap.clear();
2493 ExternalFnToStubMap.clear();
2494 PendingFunctions.clear();
2495
2496 return;
2497 }
2498
2499 void reset() {
2500 releaseUnnecessary();
2501
2502 mpSymbolLookupFn = NULL;
2503 mpSymbolLookupContext = NULL;
2504
2505 mpTJI = NULL;
2506 mpTD = NULL;
2507
Zonr Chang932648d2010-10-13 22:23:56 +08002508 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2509 E = mEmittedFunctions.end();
2510 I != E;
2511 I++)
2512 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002513 delete I->second;
2514 mEmittedFunctions.clear();
2515
2516 mpMemMgr->reset();
2517
2518 return;
2519 }
2520
Zonr Chang932648d2010-10-13 22:23:56 +08002521 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002522 return lookup( llvm::StringRef(Name) );
2523 }
2524
Zonr Chang932648d2010-10-13 22:23:56 +08002525 void *lookup(const llvm::StringRef &Name) {
2526 EmittedFunctionsMapTy::const_iterator I =
2527 mEmittedFunctions.find(Name.str());
2528 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002529 return NULL;
2530 else
2531 return I->second->Code;
2532 }
2533
Zonr Chang932648d2010-10-13 22:23:56 +08002534 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002535 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002536 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002537 int functionCount = mEmittedFunctions.size();
2538
Zonr Chang932648d2010-10-13 22:23:56 +08002539 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002540 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002541 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002542 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002543 if (functions)
2544 for (EmittedFunctionsMapTy::const_iterator
2545 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2546 (I != E) && (functionCount > 0);
2547 I++, functionCount--)
2548 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002549
2550 return;
2551 }
2552
Zonr Chang932648d2010-10-13 22:23:56 +08002553 void getFunctionBinary(BCCchar *label,
2554 BCCvoid **base,
2555 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002556 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002557 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002558 *base = NULL;
2559 *length = 0;
2560 } else {
2561 *base = I->second->Code;
2562 *length = I->second->Size;
2563 }
2564 return;
2565 }
2566
2567 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002568 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002569#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002570 delete mpAsmInfo;
2571 delete mpDisassmbler;
2572 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002573#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002574 return;
2575 }
Zonr Chang932648d2010-10-13 22:23:56 +08002576 };
2577 // End of Class CodeEmitter
2578 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002579
Zonr Chang932648d2010-10-13 22:23:56 +08002580 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002581 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002582 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002583 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2584 return mCodeEmitter.get();
2585 }
2586
2587 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002588 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002589
Zonr Chang932648d2010-10-13 22:23:56 +08002590 llvm::LLVMContext *mContext;
2591 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002592
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002593 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002594
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002595 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002596 Compiler()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002597 : mUseCache(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002598 mCacheNew(false),
2599 mCacheFd(-1),
2600 mCacheMapAddr(NULL),
2601 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002602 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002603 mCacheDiff(0),
2604 mCodeDataAddr(NULL),
2605 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002606 mpSymbolLookupContext(NULL),
2607 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002608 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002609 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002610 llvm::remove_fatal_error_handler();
2611 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002612 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002613 return;
2614 }
2615
Zonr Chang932648d2010-10-13 22:23:56 +08002616 // interface for BCCscript::registerSymbolCallback()
2617 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002618 mpSymbolLookupFn = pFn;
2619 mpSymbolLookupContext = pContext;
2620 return;
2621 }
2622
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002623 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002624 GlobalInitialization();
2625 mModule = module;
2626 return hasError();
2627 }
2628
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002629 int readBC(const char *bitcode,
Loganc0b9f652010-11-24 22:33:16 +08002630 size_t bitcodeSize,
2631 const BCCchar *resName) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002632 GlobalInitialization();
2633
Loganc0b9f652010-11-24 22:33:16 +08002634 if (resName) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002635 // Turn on mUseCache mode iff
2636 // 1. Has resName
2637 // and, assuming USE_RELOCATE is false:
2638 // 2. Later running code doesn't violate the following condition:
2639 // mCodeDataAddr (set in loadCacheFile()) ==
2640 // mCacheHdr->cachedCodeDataAddr
2641 //
2642 // BTW, this condition is achievable only when in the earlier
2643 // cache-generating run,
2644 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
2645 // which means the mmap'ed is in the reserved area,
2646 //
2647 // Note: Upon violation, mUseCache will be set back to false.
2648 mUseCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002649
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002650 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2651 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2652 return -mCacheFd;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002653 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002654 }
2655
2656 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002657
Zonr Chang932648d2010-10-13 22:23:56 +08002658 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002659 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002660
Zonr Chang932648d2010-10-13 22:23:56 +08002661 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002662 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002663 llvm::StringRef(bitcode, bitcodeSize)));
2664
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002665 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002666 setError("Error reading input program bitcode into memory");
2667 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002668 }
2669
Zonr Chang932648d2010-10-13 22:23:56 +08002670 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002671 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2672 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002673 return hasError();
2674 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002675
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002676 int linkBC(const char *bitcode, size_t bitcodeSize) {
2677 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002678
2679 if (bitcode == NULL || bitcodeSize <= 0)
2680 return 0;
2681
2682 if (mModule == NULL) {
2683 setError("No module presents for linking");
2684 return hasError();
2685 }
2686
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002687 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002688 llvm::StringRef(bitcode, bitcodeSize)));
2689
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002690 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002691 setError("Error reading input library bitcode into memory");
2692 return hasError();
2693 }
2694
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002695 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002696 *mContext,
2697 &mError));
2698 if (Lib.get() == NULL)
2699 return hasError();
2700
2701 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2702 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002703
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002704 // Everything for linking should be settled down here with no error occurs
2705 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002706 return hasError();
2707 }
2708
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002709 // interface for bccLoadBinary()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002710 int loadCacheFile() {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002711 // Check File Descriptor
2712 if (mCacheFd < 0) {
2713 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2714 goto giveup;
2715 }
2716
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002717 // Check File Size
2718 struct stat statCacheFd;
2719 if (fstat(mCacheFd, &statCacheFd) < 0) {
2720 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2721 goto giveup;
2722 }
2723
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002724 mCacheSize = statCacheFd.st_size;
2725
2726 if (mCacheSize < sizeof(oBCCHeader) ||
2727 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002728 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2729 goto giveup;
2730 }
2731
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002732 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2733 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2734 goto giveup;
2735 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002736
Loganc0b9f652010-11-24 22:33:16 +08002737 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002738 {
Loganc0b9f652010-11-24 22:33:16 +08002739 // Read cached file and perform quick integrity check
2740
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002741 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002742 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
Loganad7e8e12010-11-22 20:43:43 +08002743 (unsigned int)mCacheSize,
2744 (unsigned long long int)heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002745
2746 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002747 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002748 flock(mCacheFd, LOCK_UN);
2749 LOGE("allocation failed.\n");
2750 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002751 }
2752
2753 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2754 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002755 if (nread != (size_t)heuristicCodeOffset) {
2756 LOGE("read(mCacheFd) failed\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002757 goto bail;
2758 }
2759
2760 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002761 // Sanity check
2762 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2763 LOGE("assertion failed: heuristic code offset is not correct.\n");
2764 goto bail;
2765 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002766 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2767 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2768 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2769 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2770 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002771
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002772 // Verify the Cache File
2773 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2774 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002775 goto bail;
2776 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002777
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002778 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2779 LOGE("bad oBCC version 0x%08x\n",
2780 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2781 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002782 }
2783
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002784 if (mCacheSize < mCacheHdr->relocOffset +
2785 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2786 LOGE("relocate table overflow\n");
2787 goto bail;
2788 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002789
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002790 if (mCacheSize < mCacheHdr->exportVarsOffset +
2791 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2792 LOGE("export variables table overflow\n");
2793 goto bail;
2794 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002795
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002796 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2797 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2798 LOGE("export functions table overflow\n");
2799 goto bail;
2800 }
2801
2802 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2803 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2804 LOGE("export pragmas table overflow\n");
2805 goto bail;
2806 }
2807
2808 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2809 LOGE("code cache overflow\n");
2810 goto bail;
2811 }
2812
2813 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2814 LOGE("data (global variable) cache overflow\n");
2815 goto bail;
2816 }
Loganefd637b2010-11-25 01:21:03 +08002817
2818 long pagesize = sysconf(_SC_PAGESIZE);
2819 if (mCacheHdr->codeOffset % pagesize != 0) {
2820 LOGE("code offset must aligned to pagesize\n");
2821 goto bail;
2822 }
Loganc0b9f652010-11-24 22:33:16 +08002823 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002824
Loganc0b9f652010-11-24 22:33:16 +08002825 // Part 2. Deal with the codedata section
2826 {
Loganefd637b2010-11-25 01:21:03 +08002827 long pagesize = sysconf(_SC_PAGESIZE);
Loganc0b9f652010-11-24 22:33:16 +08002828
Loganefd637b2010-11-25 01:21:03 +08002829 if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
2830 void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002831
Loganefd637b2010-11-25 01:21:03 +08002832 // Try to mmap at cached address directly.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002833 mCodeDataAddr = (char *) mmap(addr,
2834 BCC_MMAP_IMG_SIZE,
Loganefd637b2010-11-25 01:21:03 +08002835 PROT_READ | PROT_EXEC | PROT_WRITE,
2836 MAP_PRIVATE | MAP_FIXED,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002837 mCacheFd,
2838 mCacheHdr->codeOffset);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002839
Loganefd637b2010-11-25 01:21:03 +08002840 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
2841 // Cheers! Mapped at the cached address successfully.
Loganc0b9f652010-11-24 22:33:16 +08002842
Loganefd637b2010-11-25 01:21:03 +08002843 if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
2844 size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
2845
2846 if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
2847 (offset / BCC_MMAP_IMG_SIZE) < BCC_MMAP_IMG_COUNT) {
2848 // Update the BccMmapImgAddrTaken table (if required)
2849 Compiler::BccMmapImgAddrTaken[offset / BCC_MMAP_IMG_SIZE] = true;
2850 }
Loganc0b9f652010-11-24 22:33:16 +08002851 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002852
Loganefd637b2010-11-25 01:21:03 +08002853 flock(mCacheFd, LOCK_UN);
2854 return 0; // loadCacheFile succeed!
2855 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002856 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002857 }
2858
Loganc0b9f652010-11-24 22:33:16 +08002859#if !USE_RELOCATE
2860 // Note: Since this build does not support relocation, we have no
2861 // choose but give up to load the cached file, and recompile the
2862 // code.
2863
2864 flock(mCacheFd, LOCK_UN);
2865 goto bail;
2866#else
2867
2868 // Note: Currently, relocation code is not working. Give up now.
2869 flock(mCacheFd, LOCK_UN);
2870 goto bail;
2871
2872 // TODO(logan): Following code is not working. Don't use them.
2873 // And rewrite them asap.
2874#if 0
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002875 {
Loganc0b9f652010-11-24 22:33:16 +08002876 // Try to allocate at arbitary address. And perform relocation.
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002877 mCacheMapAddr = (char *) mmap(0,
2878 mCacheSize,
Loganc0b9f652010-11-24 22:33:16 +08002879 PROT_READ | PROT_EXEC | PROT_WRITE,
Shih-wei Liaof49c9e32010-11-24 09:31:52 -08002880 MAP_PRIVATE,
2881 mCacheFd,
2882 0);
Loganc0b9f652010-11-24 22:33:16 +08002883
2884 if (mCacheMapAddr == MAP_FAILED) {
2885 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2886 flock(mCacheFd, LOCK_UN);
2887 goto giveup;
2888 }
2889
2890 flock(mCacheFd, LOCK_UN);
2891 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2892
2893 // Relocate
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002894 mCacheDiff = mCodeDataAddr -
2895 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2896
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002897 if (mCacheDiff) { // To relocate
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002898 if (mCacheHdr->rootAddr) {
2899 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002900 }
2901
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002902 if (mCacheHdr->initAddr) {
2903 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002904 }
2905
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002906 oBCCRelocEntry *cachedRelocTable =
2907 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2908 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002909
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002910 std::vector<llvm::MachineRelocation> relocations;
2911
2912 // Read in the relocs
2913 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2914 oBCCRelocEntry *entry = &cachedRelocTable[i];
2915
2916 llvm::MachineRelocation reloc =
2917 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2918 (unsigned)entry->relocType, 0, 0);
2919
2920 reloc.setResultPointer(
2921 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2922
2923 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002924 }
2925
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002926 // Rewrite machine code using llvm::TargetJITInfo relocate
2927 {
2928 llvm::TargetMachine *TM = NULL;
2929 const llvm::Target *Target;
2930 std::string FeaturesStr;
2931
2932 // Create TargetMachine
2933 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2934 if (hasError())
2935 goto bail;
2936
2937 if (!CPU.empty() || !Features.empty()) {
2938 llvm::SubtargetFeatures F;
2939 F.setCPU(CPU);
2940 for (std::vector<std::string>::const_iterator I = Features.begin(),
2941 E = Features.end(); I != E; I++)
2942 F.AddFeature(*I);
2943 FeaturesStr = F.getString();
2944 }
2945
2946 TM = Target->createTargetMachine(Triple, FeaturesStr);
2947 if (TM == NULL) {
2948 setError("Failed to create target machine implementation for the"
2949 " specified triple '" + Triple + "'");
2950 goto bail;
2951 }
2952
2953 TM->getJITInfo()->relocate(mCodeDataAddr,
2954 &relocations[0], relocations.size(),
2955 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2956
2957 if (mCodeEmitter.get()) {
2958 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2959 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2960 2 * 1024 /*MaxCodeSize*/,
2961 false);
2962 }
2963
2964 delete TM;
2965 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002966 } // End of if (mCacheDiff)
Loganc0b9f652010-11-24 22:33:16 +08002967
2968 return 0; // Success!
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002969 }
Loganc0b9f652010-11-24 22:33:16 +08002970#endif
2971#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002972
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002973 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002974 if (mCacheMapAddr) {
2975 free(mCacheMapAddr);
2976 }
Loganad7e8e12010-11-22 20:43:43 +08002977
Loganc0b9f652010-11-24 22:33:16 +08002978 if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +08002979 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
Loganc0b9f652010-11-24 22:33:16 +08002980 LOGE("munmap failed: %s\n", strerror(errno));
2981 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002982 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002983
Logan82e67012010-11-25 00:29:34 +08002984 mCacheMapAddr = 0;
2985 mCodeDataAddr = 0;
2986
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002987 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002988 return 1;
2989 }
2990
2991 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002992 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002993 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002994
Zonr Chang932648d2010-10-13 22:23:56 +08002995 llvm::TargetMachine *TM = NULL;
2996 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002997 std::string FeaturesStr;
2998
Zonr Chang932648d2010-10-13 22:23:56 +08002999 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003000
Zonr Chang932648d2010-10-13 22:23:56 +08003001 const llvm::NamedMDNode *PragmaMetadata;
3002 const llvm::NamedMDNode *ExportVarMetadata;
3003 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003004
Zonr Chang932648d2010-10-13 22:23:56 +08003005 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003006 return 0;
3007
Zonr Chang932648d2010-10-13 22:23:56 +08003008 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003009 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08003010 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003011 goto on_bcc_compile_error;
3012
Zonr Chang932648d2010-10-13 22:23:56 +08003013 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003014 llvm::SubtargetFeatures F;
3015 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08003016 for (std::vector<std::string>::const_iterator I = Features.begin(),
3017 E = Features.end();
3018 I != E;
3019 I++)
3020 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003021 FeaturesStr = F.getString();
3022 }
3023
3024 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08003025 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003026 setError("Failed to create target machine implementation for the"
3027 " specified triple '" + Triple + "'");
3028 goto on_bcc_compile_error;
3029 }
3030
Zonr Chang932648d2010-10-13 22:23:56 +08003031 // Create memory manager for creation of code emitter later.
3032 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003033 setError("Failed to startup memory management for further compilation");
3034 goto on_bcc_compile_error;
3035 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003036 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003037
Zonr Chang932648d2010-10-13 22:23:56 +08003038 // Create code emitter
3039 if (!mCodeEmitter.get()) {
3040 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003041 setError("Failed to create machine code emitter to complete"
3042 " the compilation");
3043 goto on_bcc_compile_error;
3044 }
3045 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08003046 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003047 mCodeEmitter->reset();
3048 }
3049
3050 mCodeEmitter->setTargetMachine(*TM);
3051 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
3052 mpSymbolLookupContext);
3053
Zonr Chang932648d2010-10-13 22:23:56 +08003054 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003055 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003056
Zonr Chang5d35b972010-10-23 14:36:47 +08003057 // Load named metadata
3058 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
3059 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
3060 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
3061
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003062 // Create LTO passes and run them on the mModule
3063 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003064 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003065 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08003066 LTOPasses.add(new llvm::TargetData(*TD));
3067
3068 std::vector<const char*> ExportSymbols;
3069
3070 // A workaround for getting export variable and function name. Will refine
3071 // it soon.
3072 if (ExportVarMetadata) {
3073 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3074 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3075 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3076 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3077 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
3078 llvm::StringRef ExportVarName =
3079 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
3080 ExportSymbols.push_back(ExportVarName.data());
3081 }
3082 }
3083 }
3084 }
3085
3086 if (ExportFuncMetadata) {
3087 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3088 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3089 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3090 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3091 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
3092 llvm::StringRef ExportFuncName =
3093 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3094 ExportSymbols.push_back(ExportFuncName.data());
3095 }
3096 }
3097 }
3098 }
3099 // root() and init() are born to be exported
3100 ExportSymbols.push_back("root");
3101 ExportSymbols.push_back("init");
3102
Zonr Change5c7a542010-10-24 01:07:27 +08003103 // We now create passes list performing LTO. These are copied from
3104 // (including comments) llvm::createStandardLTOPasses().
3105
3106 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08003107 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003108
Zonr Change5c7a542010-10-24 01:07:27 +08003109 // Propagate constants at call sites into the functions they call. This
3110 // opens opportunities for globalopt (and inlining) by substituting
3111 // function pointers passed as arguments to direct uses of functions.
3112 LTOPasses.add(llvm::createIPSCCPPass());
3113
3114 // Now that we internalized some globals, see if we can hack on them!
3115 LTOPasses.add(llvm::createGlobalOptimizerPass());
3116
3117 // Linking modules together can lead to duplicated global constants, only
3118 // keep one copy of each constant...
3119 LTOPasses.add(llvm::createConstantMergePass());
3120
3121 // Remove unused arguments from functions...
3122 LTOPasses.add(llvm::createDeadArgEliminationPass());
3123
3124 // Reduce the code after globalopt and ipsccp. Both can open up
3125 // significant simplification opportunities, and both can propagate
3126 // functions through function pointers. When this happens, we often have
3127 // to resolve varargs calls, etc, so let instcombine do this.
3128 LTOPasses.add(llvm::createInstructionCombiningPass());
3129
3130 // Inline small functions
3131 LTOPasses.add(llvm::createFunctionInliningPass());
3132
3133 // Remove dead EH info.
3134 LTOPasses.add(llvm::createPruneEHPass());
3135
3136 // Internalize the globals again after inlining
3137 LTOPasses.add(llvm::createGlobalOptimizerPass());
3138
3139 // Remove dead functions.
3140 LTOPasses.add(llvm::createGlobalDCEPass());
3141
3142 // If we didn't decide to inline a function, check to see if we can
3143 // transform it to pass arguments by value instead of by reference.
3144 LTOPasses.add(llvm::createArgumentPromotionPass());
3145
3146 // The IPO passes may leave cruft around. Clean up after them.
3147 LTOPasses.add(llvm::createInstructionCombiningPass());
3148 LTOPasses.add(llvm::createJumpThreadingPass());
3149
3150 // Break up allocas
3151 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3152
3153 // Run a few AA driven optimizations here and now, to cleanup the code.
3154 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3155 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3156
3157 // Hoist loop invariants.
3158 LTOPasses.add(llvm::createLICMPass());
3159
3160 // Remove redundancies.
3161 LTOPasses.add(llvm::createGVNPass());
3162
3163 // Remove dead memcpys.
3164 LTOPasses.add(llvm::createMemCpyOptPass());
3165
3166 // Nuke dead stores.
3167 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3168
3169 // Cleanup and simplify the code after the scalar optimizations.
3170 LTOPasses.add(llvm::createInstructionCombiningPass());
3171
3172 LTOPasses.add(llvm::createJumpThreadingPass());
3173
3174 // Delete basic blocks, which optimization passes may have killed.
3175 LTOPasses.add(llvm::createCFGSimplificationPass());
3176
3177 // Now that we have optimized the program, discard unreachable functions.
3178 LTOPasses.add(llvm::createGlobalDCEPass());
3179
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003180 LTOPasses.run(*mModule);
3181 }
3182
Zonr Chang932648d2010-10-13 22:23:56 +08003183 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003184 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003185 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003186
Zonr Chang932648d2010-10-13 22:23:56 +08003187 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3188 *mCodeEmitter,
3189 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003190 setError("The machine code emission is not supported by BCC on target '"
3191 + Triple + "'");
3192 goto on_bcc_compile_error;
3193 }
3194
Zonr Chang932648d2010-10-13 22:23:56 +08003195 // Run the pass (the code emitter) on every non-declaration function in the
3196 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003197 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003198 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3199 I != E;
3200 I++)
3201 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003202 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003203
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003204 CodeGenPasses->doFinalization();
3205
Zonr Chang932648d2010-10-13 22:23:56 +08003206 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003207 if (ExportVarMetadata) {
3208 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3209 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3210 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3211 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3212 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003213 llvm::StringRef ExportVarName =
3214 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003215 CodeEmitter::global_addresses_const_iterator I, E;
3216 for (I = mCodeEmitter->global_address_begin(),
3217 E = mCodeEmitter->global_address_end();
3218 I != E;
3219 I++) {
3220 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003221 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003222 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003223 mExportVars.push_back(I->second);
3224 break;
3225 }
3226 }
Zonr Chang932648d2010-10-13 22:23:56 +08003227 if (I != mCodeEmitter->global_address_end())
3228 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003229 }
3230 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003231 // if reaching here, we know the global variable record in metadata is
3232 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003233 mExportVars.push_back(NULL);
3234 }
3235 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3236 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003237 }
3238
Zonr Chang932648d2010-10-13 22:23:56 +08003239 if (ExportFuncMetadata) {
3240 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3241 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3242 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3243 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3244 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003245 llvm::StringRef ExportFuncName =
3246 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3247 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3248 }
3249 }
3250 }
3251 }
3252
Zonr Chang932648d2010-10-13 22:23:56 +08003253 // Tell code emitter now can release the memory using during the JIT since
3254 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003255 mCodeEmitter->releaseUnnecessary();
3256
Zonr Chang932648d2010-10-13 22:23:56 +08003257 // Finally, read pragma information from the metadata node of the @Module if
3258 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003259 if (PragmaMetadata)
3260 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3261 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3262 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003263 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003264 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3265 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003266
Zonr Chang932648d2010-10-13 22:23:56 +08003267 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003268 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3269 llvm::StringRef PragmaName =
3270 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3271 llvm::StringRef PragmaValue =
3272 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3273
Zonr Chang932648d2010-10-13 22:23:56 +08003274 mPragmas.push_back(
3275 std::make_pair(std::string(PragmaName.data(),
3276 PragmaName.size()),
3277 std::string(PragmaValue.data(),
3278 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003279 }
3280 }
3281 }
3282
3283 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003284 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003285 if (CodeGenPasses) {
3286 delete CodeGenPasses;
3287 } else if (TD) {
3288 delete TD;
3289 }
3290 if (TM)
3291 delete TM;
3292
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003293 if (mError.empty()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003294 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003295 genCacheFile();
3296 flock(mCacheFd, LOCK_UN);
3297 }
Loganc0b9f652010-11-24 22:33:16 +08003298
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003299 return false;
3300 }
3301
Zonr Chang932648d2010-10-13 22:23:56 +08003302 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003303 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003304 }
3305
Zonr Chang932648d2010-10-13 22:23:56 +08003306 // interface for bccGetScriptInfoLog()
3307 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003308 return const_cast<char*>(mError.c_str());
3309 }
3310
Zonr Chang932648d2010-10-13 22:23:56 +08003311 // interface for bccGetScriptLabel()
3312 void *lookup(const char *name) {
3313 void *addr = NULL;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003314 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003315 if (!strcmp(name, "root")) {
3316 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3317 } else if (!strcmp(name, "init")) {
3318 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3319 }
3320 return addr;
3321 }
3322
Zonr Chang932648d2010-10-13 22:23:56 +08003323 if (mCodeEmitter.get())
3324 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003325 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003326 return addr;
3327 }
3328
Zonr Chang932648d2010-10-13 22:23:56 +08003329 // Interface for bccGetExportVars()
3330 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003331 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003332 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003333 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003334
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003335 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003336 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3337 if (actualVarCount)
3338 *actualVarCount = varCount;
3339 if (varCount > maxVarCount)
3340 varCount = maxVarCount;
3341 if (vars) {
3342 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3343 mCacheHdr->exportVarsOffset);
3344
3345 for (int i = 0; i < varCount; i++) {
3346 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3347 mCacheDiff);
3348 cachedVars++;
3349 }
3350 }
3351 return;
3352 }
3353
3354 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003355 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003356 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003357 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003358 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003359 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003360 for (ExportVarList::const_iterator I = mExportVars.begin(),
3361 E = mExportVars.end();
3362 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003363 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003364 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003365 }
3366 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003367
3368 return;
3369 }
3370
Zonr Chang932648d2010-10-13 22:23:56 +08003371 // Interface for bccGetExportFuncs()
3372 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003373 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003374 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003375 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003376
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003377 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003378 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3379 if (actualFuncCount)
3380 *actualFuncCount = funcCount;
3381 if (funcCount > maxFuncCount)
3382 funcCount = maxFuncCount;
3383 if (funcs) {
3384 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3385 mCacheHdr->exportFuncsOffset);
3386
3387 for (int i = 0; i < funcCount; i++) {
3388 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3389 mCacheDiff);
3390 cachedFuncs++;
3391 }
3392 }
3393 return;
3394 }
3395
3396 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003397 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003398 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003399 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003400 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003401 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003402 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3403 E = mExportFuncs.end();
3404 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003405 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003406 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003407 }
3408 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003409
3410 return;
3411 }
3412
Zonr Chang932648d2010-10-13 22:23:56 +08003413 // Interface for bccGetPragmas()
3414 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003415 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003416 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003417 int stringCount;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003418 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003419 if (actualStringCount)
3420 *actualStringCount = 0; // XXX
3421 return;
3422 }
3423
3424 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003425
Zonr Chang932648d2010-10-13 22:23:56 +08003426 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003427 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003428 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003429 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003430 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003431 for (PragmaList::const_iterator it = mPragmas.begin();
3432 stringCount > 0;
3433 stringCount -= 2, it++) {
3434 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3435 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003436 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003437 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003438
3439 return;
3440 }
3441
Zonr Chang932648d2010-10-13 22:23:56 +08003442 // Interface for bccGetFunctions()
3443 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003444 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003445 BCCchar **functions) {
3446 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003447 mCodeEmitter->getFunctionNames(actualFunctionCount,
3448 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003449 functions);
3450 else
3451 *actualFunctionCount = 0;
3452
3453 return;
3454 }
3455
Zonr Chang932648d2010-10-13 22:23:56 +08003456 // Interface for bccGetFunctionBinary()
3457 void getFunctionBinary(BCCchar *function,
3458 BCCvoid **base,
3459 BCCsizei *length) {
3460 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003461 mCodeEmitter->getFunctionBinary(function, base, length);
3462 } else {
3463 *base = NULL;
3464 *length = 0;
3465 }
3466 return;
3467 }
3468
Zonr Chang932648d2010-10-13 22:23:56 +08003469 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003470 return mModule;
3471 }
3472
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003473 ~Compiler() {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003474 if (!mCodeMemMgr.get()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003475 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003476 // managed by CodeMemoryManager.
3477
3478 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
Logan82e67012010-11-25 00:29:34 +08003479 if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003480 LOGE("munmap failed while releasing mCodeDataAddr\n");
3481 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003482 }
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003483
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003484 if (mCacheMapAddr) {
3485 free(mCacheMapAddr);
3486 }
Logan82e67012010-11-25 00:29:34 +08003487
3488 mCodeDataAddr = 0;
3489 mCacheMapAddr = 0;
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003490 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003491
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003492 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003493 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003494 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003495 return;
3496 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003497
3498 private:
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003499 // Note: loadCacheFile() and genCacheFile() go hand in hand
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003500 void genCacheFile() {
3501 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3502 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3503 return;
3504 }
3505
3506 bool codeOffsetNeedPadding = false;
3507
3508 uint32_t offset = sizeof(oBCCHeader);
3509
3510 // BCC Cache File Header
3511 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3512
3513 if (!hdr) {
3514 LOGE("Unable to allocate oBCCHeader.\n");
3515 return;
3516 }
3517
3518 // Magic Words
3519 memcpy(hdr->magic, OBCC_MAGIC, 4);
3520 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3521
3522 // Timestamp
3523 hdr->sourceWhen = 0; // TODO(all)
3524 hdr->rslibWhen = 0; // TODO(all)
3525 hdr->libRSWhen = 0; // TODO(all)
3526 hdr->libbccWhen = 0; // TODO(all)
3527
3528 // Current Memory Address (Saved for Recalculation)
3529 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3530 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3531 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3532
3533 // Relocation Table Offset and Entry Count
3534 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003535 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003536
Logan824dd0a2010-11-20 01:45:54 +08003537 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003538
3539 // Export Variable Table Offset and Entry Count
3540 hdr->exportVarsOffset = offset;
3541 hdr->exportVarsCount = mExportVars.size();
3542
3543 offset += hdr->exportVarsCount * sizeof(uint32_t);
3544
3545 // Export Function Table Offset and Entry Count
3546 hdr->exportFuncsOffset = offset;
3547 hdr->exportFuncsCount = mExportFuncs.size();
3548
3549 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3550
3551 // Export Pragmas Table Offset and Entry Count
3552 hdr->exportPragmasOffset = offset;
3553 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3554
3555 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3556
3557 // Code Offset and Size
3558
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003559 //#ifdef BCC_CODE_ADDR
3560 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003561 long pagesize = sysconf(_SC_PAGESIZE);
3562
3563 if (offset % pagesize > 0) {
3564 codeOffsetNeedPadding = true;
3565 offset += pagesize - (offset % pagesize);
3566 }
3567 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003568 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003569 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3570 codeOffsetNeedPadding = true;
3571 offset += 0x08 - (offset & 0x07);
3572 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003573 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003574
3575 hdr->codeOffset = offset;
3576 hdr->codeSize = MaxCodeSize;
3577
3578 offset += hdr->codeSize;
3579
3580 // Data (Global Variable) Offset and Size
3581 hdr->dataOffset = offset;
3582 hdr->dataSize = MaxGlobalVarSize;
3583
3584 offset += hdr->dataSize;
3585
3586 // Checksum
3587 hdr->checksum = 0; // Set Field checksum. TODO(all)
3588
3589 // Write Header
3590 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3591 sizeof(oBCCHeader), "Write oBCC header");
3592
Logan824dd0a2010-11-20 01:45:54 +08003593 // Write Relocation Entry Table
3594 {
3595 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003596
Logan824dd0a2010-11-20 01:45:54 +08003597 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3598
3599 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3600 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003601 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003602
3603 // Write Export Variables Table
3604 {
3605 uint32_t *record, *ptr;
3606
3607 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3608 ptr = record;
3609
3610 if (!record) {
3611 goto bail;
3612 }
3613
3614 for (ExportVarList::const_iterator I = mExportVars.begin(),
3615 E = mExportVars.end(); I != E; I++) {
3616 *ptr++ = reinterpret_cast<uint32_t>(*I);
3617 }
3618
3619 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3620 hdr->exportVarsCount * sizeof(uint32_t),
3621 "Write ExportVars");
3622
3623 free(record);
3624 }
3625
3626 // Write Export Functions Table
3627 {
3628 uint32_t *record, *ptr;
3629
3630 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3631 ptr = record;
3632
3633 if (!record) {
3634 goto bail;
3635 }
3636
3637 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3638 E = mExportFuncs.end(); I != E; I++) {
3639 *ptr++ = reinterpret_cast<uint32_t>(*I);
3640 }
3641
3642 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3643 hdr->exportFuncsCount * sizeof(uint32_t),
3644 "Write ExportFuncs");
3645
3646 free(record);
3647 }
3648
3649
3650 // TODO(all): Write Export Pragmas Table
3651#if 0
3652#else
3653 // Note: As long as we have comment out export pragmas table code,
3654 // we have to seek the position to correct offset.
3655
3656 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3657#endif
3658
3659 if (codeOffsetNeedPadding) {
3660 // requires additional padding
3661 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3662 }
3663
3664 // Write Generated Code and Global Variable
3665 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3666 "Write code and global variable");
3667
3668 goto close_return;
3669
3670 bail:
3671 if (ftruncate(mCacheFd, 0) != 0) {
3672 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3673 }
3674
3675 close_return:
3676 free(hdr);
3677 close(mCacheFd);
3678 mCacheFd = -1;
3679 return;
3680 }
3681
3682 // OpenCacheFile() returns fd of the cache file.
3683 // Input:
3684 // BCCchar *resName: Used to genCacheFileName()
3685 // bool createIfMissing: If false, turn off caching
3686 // Output:
3687 // returns fd: If -1: Failed
3688 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3689 // cache file's file descriptor
3690 // Note: openCacheFile() will check the cache file's validity,
3691 // such as Magic number, sourceWhen... dependencies.
3692 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3693 int fd, cc;
3694 struct stat fdStat, fileStat;
3695 bool readOnly = false;
3696
3697 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3698
3699 mCacheNew = false;
3700
3701 retry:
3702 /*
3703 * Try to open the cache file. If we've been asked to,
3704 * create it if it doesn't exist.
3705 */
3706 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3707 if (fd < 0) {
3708 fd = open(cacheFileName, O_RDONLY, 0);
3709 if (fd < 0) {
3710 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08003711 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003712 cacheFileName, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003713 mUseCache = false;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003714 }
3715 return fd;
3716 }
3717 readOnly = true;
3718 }
3719
3720 /*
3721 * Grab an exclusive lock on the cache file. If somebody else is
3722 * working on it, we'll block here until they complete.
3723 */
3724 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3725 cacheFileName, fd);
3726
3727 cc = flock(fd, LOCK_EX | LOCK_NB);
3728 if (cc != 0) {
3729 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3730 cc = flock(fd, LOCK_EX);
3731 }
3732
3733 if (cc != 0) {
3734 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3735 close(fd);
3736 return -1;
3737 }
3738 LOGV("bcc: locked cache file\n");
3739
3740 /*
3741 * Check to see if the fd we opened and locked matches the file in
3742 * the filesystem. If they don't, then somebody else unlinked ours
3743 * and created a new file, and we need to use that one instead. (If
3744 * we caught them between the unlink and the create, we'll get an
3745 * ENOENT from the file stat.)
3746 */
3747 cc = fstat(fd, &fdStat);
3748 if (cc != 0) {
3749 LOGE("Can't stat open file '%s'\n", cacheFileName);
3750 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3751 goto close_fail;
3752 }
3753 cc = stat(cacheFileName, &fileStat);
3754 if (cc != 0 ||
3755 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3756 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3757 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3758 flock(fd, LOCK_UN);
3759 close(fd);
3760 usleep(250 * 1000); // if something is hosed, don't peg machine
3761 goto retry;
3762 }
3763
3764 /*
3765 * We have the correct file open and locked. If the file size is zero,
3766 * then it was just created by us, and we want to fill in some fields
3767 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3768 * verify that the fields in the header match our expectations, and
3769 * reset the file if they don't.
3770 */
3771 if (fdStat.st_size == 0) {
3772 if (readOnly) { // The device is readOnly --> close_fail
3773 LOGW("bcc: file has zero length and isn't writable\n");
3774 goto close_fail;
3775 }
3776 /*cc = createEmptyHeader(fd);
3777 if (cc != 0)
3778 goto close_fail;
3779 */
3780 mCacheNew = true;
3781 LOGV("bcc: successfully initialized new cache file\n");
3782 } else {
3783 // Calculate sourceWhen
3784 // XXX
3785 uint32_t sourceWhen = 0;
3786 uint32_t rslibWhen = 0;
3787 uint32_t libRSWhen = 0;
3788 uint32_t libbccWhen = 0;
3789 if (!checkHeaderAndDependencies(fd,
3790 sourceWhen,
3791 rslibWhen,
3792 libRSWhen,
3793 libbccWhen)) {
3794 // If checkHeaderAndDependencies returns 0: FAILED
3795 // Will truncate the file and retry to createIfMissing the file
3796
3797 if (readOnly) { // Shouldn't be readonly.
3798 /*
3799 * We could unlink and rewrite the file if we own it or
3800 * the "sticky" bit isn't set on the directory. However,
3801 * we're not able to truncate it, which spoils things. So,
3802 * give up now.
3803 */
3804 if (createIfMissing) {
3805 LOGW("Cached file %s is stale and not writable\n",
3806 cacheFileName);
3807 }
3808 goto close_fail;
3809 }
3810
3811 /*
3812 * If we truncate the existing file before unlinking it, any
3813 * process that has it mapped will fail when it tries to touch
3814 * the pages? Probably OK because we use MAP_PRIVATE.
3815 */
3816 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3817 cacheFileName);
3818 if (ftruncate(fd, 0) != 0) {
3819 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3820 cacheFileName, strerror(errno));
3821 /* keep going */
3822 }
3823 if (unlink(cacheFileName) != 0) {
3824 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3825 cacheFileName, errno, strerror(errno));
3826 /* keep going; permission failure should probably be fatal */
3827 }
3828 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3829 flock(fd, LOCK_UN);
3830 close(fd);
3831 goto retry;
3832 } else {
3833 // Got cacheFile! Good to go.
3834 LOGV("Good cache file\n");
3835 }
3836 }
3837
3838 assert(fd >= 0);
3839 return fd;
3840
3841 close_fail:
3842 flock(fd, LOCK_UN);
3843 close(fd);
3844 return -1;
3845 } // End of openCacheFile()
3846
3847 char *genCacheFileName(const char *fileName, const char *subFileName) {
3848 char nameBuf[512];
3849 static const char kCachePath[] = "bcc-cache";
3850 char absoluteFile[sizeof(nameBuf)];
3851 const size_t kBufLen = sizeof(nameBuf) - 1;
3852 const char *dataRoot;
3853 char *cp;
3854
3855 // Get the absolute path of the raw/***.bc file.
3856 absoluteFile[0] = '\0';
3857 if (fileName[0] != '/') {
3858 /*
3859 * Generate the absolute path. This doesn't do everything it
3860 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3861 * the leading "./" out, but it'll do.
3862 */
3863 if (getcwd(absoluteFile, kBufLen) == NULL) {
3864 LOGE("Can't get CWD while opening raw/***.bc file\n");
3865 return NULL;
3866 }
3867 // TODO(srhines): strncat() is a bit dangerous
3868 strncat(absoluteFile, "/", kBufLen);
3869 }
3870 strncat(absoluteFile, fileName, kBufLen);
3871
3872 if (subFileName != NULL) {
3873 strncat(absoluteFile, "/", kBufLen);
3874 strncat(absoluteFile, subFileName, kBufLen);
3875 }
3876
3877 /* Turn the path into a flat filename by replacing
3878 * any slashes after the first one with '@' characters.
3879 */
3880 cp = absoluteFile + 1;
3881 while (*cp != '\0') {
3882 if (*cp == '/') {
3883 *cp = '@';
3884 }
3885 cp++;
3886 }
3887
3888 /* Build the name of the cache directory.
3889 */
3890 dataRoot = getenv("ANDROID_DATA");
3891 if (dataRoot == NULL)
3892 dataRoot = "/data";
3893 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3894
3895 /* Tack on the file name for the actual cache file path.
3896 */
3897 strncat(nameBuf, absoluteFile, kBufLen);
3898
3899 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3900 return strdup(nameBuf);
3901 }
3902
3903 /*
3904 * Read the oBCC header, verify it, then read the dependent section
3905 * and verify that data as well.
3906 *
3907 * On successful return, the file will be seeked immediately past the
3908 * oBCC header.
3909 */
3910 bool checkHeaderAndDependencies(int fd,
3911 uint32_t sourceWhen,
3912 uint32_t rslibWhen,
3913 uint32_t libRSWhen,
3914 uint32_t libbccWhen) {
3915 ssize_t actual;
3916 oBCCHeader optHdr;
3917 uint32_t val;
3918 uint8_t const *magic, *magicVer;
3919
3920 /*
3921 * Start at the start. The "bcc" header, when present, will always be
3922 * the first thing in the file.
3923 */
3924 if (lseek(fd, 0, SEEK_SET) != 0) {
3925 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3926 goto bail;
3927 }
3928
3929 /*
3930 * Read and do trivial verification on the bcc header. The header is
3931 * always in host byte order.
3932 */
3933 actual = read(fd, &optHdr, sizeof(optHdr));
3934 if (actual < 0) {
3935 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3936 goto bail;
3937 } else if (actual != sizeof(optHdr)) {
3938 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3939 (int) actual, sizeof(optHdr));
3940 goto bail;
3941 }
3942
3943 magic = optHdr.magic;
3944 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3945 /* not an oBCC file, or previous attempt was interrupted */
3946 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3947 magic[0], magic[1], magic[2], magic[3]);
3948 goto bail;
3949 }
3950
3951 magicVer = optHdr.magicVersion;
3952 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3953 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3954 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3955 goto bail;
3956 }
3957
3958 /*
3959 * Do the header flags match up with what we want?
3960 *
3961 * This is useful because it allows us to automatically regenerate
3962 * a file when settings change (e.g. verification is now mandatory),
3963 * but can cause difficulties if the thing we depend upon
3964 * were handled differently than the current options specify.
3965 *
3966 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3967 * by limiting the match mask.
3968 *
3969 * The only thing we really can't handle is incorrect byte-ordering.
3970 */
3971
3972 val = optHdr.sourceWhen;
3973 if (val && (val != sourceWhen)) {
3974 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3975 val, sourceWhen);
3976 goto bail;
3977 }
3978 val = optHdr.rslibWhen;
3979 if (val && (val != rslibWhen)) {
3980 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3981 val, rslibWhen);
3982 goto bail;
3983 }
3984 val = optHdr.libRSWhen;
3985 if (val && (val != libRSWhen)) {
3986 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3987 val, libRSWhen);
3988 goto bail;
3989 }
3990 val = optHdr.libbccWhen;
3991 if (val && (val != libbccWhen)) {
3992 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3993 val, libbccWhen);
3994 goto bail;
3995 }
3996
3997 return true;
3998
3999 bail:
4000 return false;
4001 }
4002
Zonr Chang932648d2010-10-13 22:23:56 +08004003};
4004// End of Class Compiler
4005////////////////////////////////////////////////////////////////////////////////
4006
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004007
4008bool Compiler::GlobalInitialized = false;
4009
Loganc0b9f652010-11-24 22:33:16 +08004010bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
Loganad7e8e12010-11-22 20:43:43 +08004011
Zonr Chang932648d2010-10-13 22:23:56 +08004012// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004013llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
4014
4015std::string Compiler::Triple;
4016
4017std::string Compiler::CPU;
4018
4019std::vector<std::string> Compiler::Features;
4020
Zonr Chang932648d2010-10-13 22:23:56 +08004021// The named of metadata node that pragma resides (should be synced with
4022// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004023const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
4024
Zonr Chang932648d2010-10-13 22:23:56 +08004025// The named of metadata node that export variable name resides (should be
4026// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004027const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
4028
Zonr Chang932648d2010-10-13 22:23:56 +08004029// The named of metadata node that export function name resides (should be
4030// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004031const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
4032
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004033struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08004034 //////////////////////////////////////////////////////////////////////////////
4035 // Part I. Compiler
4036 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004037 Compiler compiler;
4038
Zonr Chang932648d2010-10-13 22:23:56 +08004039 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004040 compiler.registerSymbolCallback(pFn, pContext);
4041 }
4042
Zonr Chang932648d2010-10-13 22:23:56 +08004043 //////////////////////////////////////////////////////////////////////////////
4044 // Part II. Logistics & Error handling
4045 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004046 BCCscript() {
4047 bccError = BCC_NO_ERROR;
4048 }
4049
4050 ~BCCscript() {
4051 }
4052
4053 void setError(BCCenum error) {
4054 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
4055 bccError = error;
4056 }
4057 }
4058
4059 BCCenum getError() {
4060 BCCenum result = bccError;
4061 bccError = BCC_NO_ERROR;
4062 return result;
4063 }
4064
4065 BCCenum bccError;
4066};
4067
4068
4069extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004070BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004071 return new BCCscript();
4072}
4073
4074extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004075BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004076 return script->getError();
4077}
4078
4079extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004080void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004081 delete script;
4082}
4083
4084extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004085void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004086 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08004087 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004088 script->registerSymbolCallback(pFn, pContext);
4089}
4090
4091extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004092int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08004093 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004094 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08004095}
4096
4097extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004098int bccReadBC(BCCscript *script,
4099 const BCCchar *bitcode,
4100 BCCint size,
4101 const BCCchar *resName) {
4102 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004103}
4104
4105extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004106void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08004107 const BCCchar *bitcode,
4108 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004109 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08004110}
4111
4112extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004113void bccLoadBinary(BCCscript *script) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08004114 int result = script->compiler.loadCacheFile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004115 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004116 script->setError(BCC_INVALID_OPERATION);
4117}
4118
4119extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004120void bccCompileBC(BCCscript *script) {
4121 {
4122#if defined(__arm__)
4123 android::StopWatch compileTimer("RenderScript compile time");
4124#endif
4125 int result = script->compiler.compile();
4126 if (result)
4127 script->setError(BCC_INVALID_OPERATION);
4128 }
4129}
4130
4131extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004132void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004133 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08004134 BCCsizei *length,
4135 BCCchar *infoLog) {
4136 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004137 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004138 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004139 *length = messageLength;
4140
4141 if (infoLog && maxLength > 0) {
4142 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4143 memcpy(infoLog, message, trimmedLength);
4144 infoLog[trimmedLength] = 0;
4145 }
4146}
4147
4148extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004149void bccGetScriptLabel(BCCscript *script,
4150 const BCCchar *name,
4151 BCCvoid **address) {
4152 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004153 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004154 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004155 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004156 script->setError(BCC_INVALID_VALUE);
4157}
4158
4159extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004160void bccGetExportVars(BCCscript *script,
4161 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004162 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004163 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004164 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4165}
4166
4167extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004168void bccGetExportFuncs(BCCscript *script,
4169 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004170 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004171 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004172 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4173}
4174
4175extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004176void bccGetPragmas(BCCscript *script,
4177 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004178 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004179 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004180 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4181}
4182
4183extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004184void bccGetFunctions(BCCscript *script,
4185 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004186 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004187 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004188 script->compiler.getFunctions(actualFunctionCount,
4189 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004190 functions);
4191}
4192
4193extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004194void bccGetFunctionBinary(BCCscript *script,
4195 BCCchar *function,
4196 BCCvoid **base,
4197 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004198 script->compiler.getFunctionBinary(function, base, length);
4199}
4200
4201struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004202 const Compiler *compiler;
4203 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004204};
4205
Zonr Chang932648d2010-10-13 22:23:56 +08004206} // namespace bcc