blob: 94aed434591beec1eaec3c22d968f1e7ba54cf96 [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
Shih-wei Liaobc5ed672010-11-24 01:53:02 -080020// BCC_CODE_ADDR == Beginning of mmap region to generate EXE onto and
21// to load EXE from disk cache
22// Note: The static variable Compiler::BccCodeAddr = BCC_CODE_ADDR
23// I.e., Compiler::BccCodeAddr is used as "Compiler::UseCache"
24//
25#if (USE_CACHE)
26# define BCC_CODE_ADDR 0x7e000000
27#else
28# define BCC_CODE_ADDR 0
29#endif
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080030
Shih-wei Liaobc5ed672010-11-24 01:53:02 -080031// Design of caching EXE:
32// ======================
Shih-wei Liao1c6ac2b2010-11-23 00:32:32 -080033// 1. Each process will have virtual address available starting at 0x7e00000.
34// E.g., Books and Youtube all have its own 0x7e00000. Next, we should
35// minimize the chance of needing to do relocation INSIDE an app too.
36//
37// 2. Each process will have ONE class static variable called BccCodeAddr.
38// I.e., even though the Compiler class will have multiple Compiler objects,
39// e.g, one object for carousel.rs and the other for pageturn.rs,
40// both Compiler objects will share 1 static variable called BccCodeAddr.
41//
42// Key observation: Every app (process) initiates, say 3, scripts (which
43// correspond to 3 Compiler objects) in the same order, usually.
44//
45// So, we should mmap to, e.g., 0x7e00000, 0x7e40000, 0x7e80000 for the 3
46// scripts, respectively. Each time, BccCodeAddr should be updated after
47// JITTing a script. BTW, in ~Compiler(), BccCodeAddr should NOT be
48// decremented back by CodeDataSize. I.e., for 3 scripts: A, B, C,
49// even if it's A -> B -> ~B -> C -> ~C -> B -> C ... no relocation will
50// ever be needed.)
51//
52// If we are lucky, then we don't need relocation ever, since next time the
53// application gets run, the 3 scripts are likely created in the SAME order.
Shih-wei Liaobc5ed672010-11-24 01:53:02 -080054//
55//
56// End-to-end algorithm on when to caching and when to JIT:
57// ========================================================
58// Prologue:
59// ---------
60// Assertion: bccReadBC() is always called and is before bccCompileBC(),
61// bccLoadBinary(), ...
62//
63// Key variable definitions: Normally,
64// Compiler::BccCodeAddr: non-zero if (USE_CACHE)
65// | (Stricter, because currently relocation doesn't work. So mUseCache only
66// | when BccCodeAddr is nonzero.)
67// V
68// mUseCache: In addition to (USE_CACHE), resName is non-zero
69// Note: mUseCache will be set to false later on whenever we find that caching
70// won't work. E.g., when mCodeDataAddr != mCacheHdr->cachedCodeDataAddr.
71// This is because currently relocation doesn't work.
72// | (Stricter, initially)
73// V
74// mCacheFd: In addition, >= 0 if openCacheFile() returns >= 0
75// | (Stricter)
76// V
77// mCacheNew: In addition, mCacheFd's size is 0, so need to call genCacheFile()
78// at the end of compile()
79//
80//
81// Main algorithm:
82// ---------------
83// #if !USE_RELOCATE
84// Case 1. ReadBC() doesn't detect a cache file:
85// compile(), which calls genCacheFile() at the end.
86// Note: mCacheNew will guard the invocation of genCacheFile()
87// Case 2. ReadBC() find a cache file
88// loadCacheFile(). But if loadCacheFile() failed, should go to Case 1.
89// #endif
Shih-wei Liao1c6ac2b2010-11-23 00:32:32 -080090
Shih-wei Liao77ed6142010-04-07 12:21:42 -070091#define LOG_TAG "bcc"
92#include <cutils/log.h>
93
94#include <ctype.h>
95#include <errno.h>
96#include <limits.h>
97#include <stdarg.h>
98#include <stdint.h>
99#include <stdio.h>
100#include <stdlib.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800101#include <stddef.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700102#include <string.h>
103#include <unistd.h>
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700104#include <sys/mman.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800105#include <sys/file.h>
106#include <sys/stat.h>
107#include <sys/types.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700108
109#include <cutils/hashmap.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800110#include <utils/StopWatch.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700111
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700112#if defined(__arm__)
Zonr Chang932648d2010-10-13 22:23:56 +0800113# define DEFAULT_ARM_CODEGEN
114# define PROVIDE_ARM_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700115#elif defined(__i386__)
Zonr Chang932648d2010-10-13 22:23:56 +0800116# define DEFAULT_X86_CODEGEN
117# define PROVIDE_X86_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700118#elif defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +0800119# define DEFAULT_X64_CODEGEN
120# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700121#endif
122
123#if defined(FORCE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800124# define DEFAULT_ARM_CODEGEN
125# undef DEFAULT_X86_CODEGEN
126# undef DEFAULT_X64_CODEGEN
127# define PROVIDE_ARM_CODEGEN
128# undef PROVIDE_X86_CODEGEN
129# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700130#elif defined(FORCE_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800131# undef DEFAULT_ARM_CODEGEN
132# define DEFAULT_X86_CODEGEN
133# undef DEFAULT_X64_CODEGEN
134# undef PROVIDE_ARM_CODEGEN
135# define PROVIDE_X86_CODEGEN
136# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700137#elif defined(FORCE_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800138# undef DEFAULT_ARM_CODEGEN
139# undef DEFAULT_X86_CODEGEN
140# define DEFAULT_X64_CODEGEN
141# undef PROVIDE_ARM_CODEGEN
142# undef PROVIDE_X86_CODEGEN
143# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700144#endif
145
146#if defined(DEFAULT_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800147# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700148#elif defined(DEFAULT_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800149# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700150#elif defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800151# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700152#endif
153
154#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
Zonr Chang932648d2010-10-13 22:23:56 +0800155# define ARM_USE_VFP
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700156#endif
157
158#include <bcc/bcc.h>
159#include "bcc_runtime.h"
160
Zonr Chang932648d2010-10-13 22:23:56 +0800161#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700162// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
163
Zonr Chang932648d2010-10-13 22:23:56 +0800164#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700165// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
166
167// #define PROVIDE_TRACE_CODEGEN
168
169#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +0800170# include "llvm/MC/MCInst.h"
171# include "llvm/MC/MCAsmInfo.h"
172# include "llvm/MC/MCInstPrinter.h"
173# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700174// If you want the disassemble results written to file, define this:
175# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700176#endif
177
178#include <set>
179#include <map>
180#include <list>
181#include <cmath>
182#include <string>
183#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800184#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700185
Zonr Chang932648d2010-10-13 22:23:56 +0800186// VMCore
187#include "llvm/Use.h"
188#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800189#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800190#include "llvm/Module.h"
191#include "llvm/Function.h"
192#include "llvm/Constant.h"
193#include "llvm/Constants.h"
194#include "llvm/Instruction.h"
195#include "llvm/PassManager.h"
196#include "llvm/LLVMContext.h"
197#include "llvm/GlobalValue.h"
198#include "llvm/Instructions.h"
199#include "llvm/OperandTraits.h"
200#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700201
202// System
Zonr Chang932648d2010-10-13 22:23:56 +0800203#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700204
205// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800206#include "llvm/ADT/APInt.h"
207#include "llvm/ADT/APFloat.h"
208#include "llvm/ADT/DenseMap.h"
209#include "llvm/ADT/ValueMap.h"
210#include "llvm/ADT/StringMap.h"
211#include "llvm/ADT/OwningPtr.h"
212#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700213
214// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800215#include "llvm/Target/TargetData.h"
216#include "llvm/Target/TargetSelect.h"
217#include "llvm/Target/TargetOptions.h"
218#include "llvm/Target/TargetMachine.h"
219#include "llvm/Target/TargetJITInfo.h"
220#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700221#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700222
223// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800224#include "llvm/Support/Casting.h"
225#include "llvm/Support/raw_ostream.h"
226#include "llvm/Support/ValueHandle.h"
227#include "llvm/Support/MemoryBuffer.h"
228#include "llvm/Support/MemoryObject.h"
229#include "llvm/Support/ManagedStatic.h"
230#include "llvm/Support/ErrorHandling.h"
231#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700232#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700233
234// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800235#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700236
237// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800238#include "llvm/CodeGen/Passes.h"
239#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700240#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700241#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700242#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700243#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700244#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700245#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700246#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700247#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700248
249// ExecutionEngine
250#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700251#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700252
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700253extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700254
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800255// For caching
256struct oBCCHeader {
257 uint8_t magic[4]; // includes version number
258 uint8_t magicVersion[4];
259
260 uint32_t sourceWhen;
261 uint32_t rslibWhen;
262 uint32_t libRSWhen;
263 uint32_t libbccWhen;
264
265 uint32_t cachedCodeDataAddr;
266 uint32_t rootAddr;
267 uint32_t initAddr;
268
269 uint32_t relocOffset; // offset of reloc table.
270 uint32_t relocCount;
271 uint32_t exportVarsOffset; // offset of export var table
272 uint32_t exportVarsCount;
273 uint32_t exportFuncsOffset; // offset of export func table
274 uint32_t exportFuncsCount;
275 uint32_t exportPragmasOffset; // offset of export pragma table
276 uint32_t exportPragmasCount;
277
278 uint32_t codeOffset; // offset of code: 64-bit alignment
279 uint32_t codeSize;
280 uint32_t dataOffset; // offset of data section
281 uint32_t dataSize;
282
283 // uint32_t flags; // some info flags
284 uint32_t checksum; // adler32 checksum covering deps/opt
285};
286
Logan824dd0a2010-11-20 01:45:54 +0800287struct oBCCRelocEntry {
288 uint32_t relocType; // target instruction relocation type
289 uint32_t relocOffset; // offset of hole (holeAddr - codeAddr)
290 uint32_t cachedResultAddr; // address resolved at compile time
291
Logan634bd832010-11-20 09:00:36 +0800292 oBCCRelocEntry(uint32_t ty, uintptr_t off, void *addr)
Logan824dd0a2010-11-20 01:45:54 +0800293 : relocType(ty),
294 relocOffset(static_cast<uint32_t>(off)),
295 cachedResultAddr(reinterpret_cast<uint32_t>(addr)) {
296 }
297};
298
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800299/* oBCCHeader Offset Table */
300#define k_magic offsetof(oBCCHeader, magic)
301#define k_magicVersion offsetof(oBCCHeader, magicVersion)
302#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
303#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
304#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
305#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
306#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
307#define k_rootAddr offsetof(oBCCHeader, rootAddr)
308#define k_initAddr offsetof(oBCCHeader, initAddr)
309#define k_relocOffset offsetof(oBCCHeader, relocOffset)
310#define k_relocCount offsetof(oBCCHeader, relocCount)
311#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
312#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
313#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
314#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
315#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
316#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
317#define k_codeOffset offsetof(oBCCHeader, codeOffset)
318#define k_codeSize offsetof(oBCCHeader, codeSize)
319#define k_dataOffset offsetof(oBCCHeader, dataOffset)
320#define k_dataSize offsetof(oBCCHeader, dataSize)
321#define k_checksum offsetof(oBCCHeader, checksum)
322
323/* oBCC file magic number */
324#define OBCC_MAGIC "bcc\n"
325/* version, encoded in 4 bytes of ASCII */
326#define OBCC_MAGIC_VERS "001\0"
327
328#define TEMP_FAILURE_RETRY1(exp) ({ \
329 typeof (exp) _rc; \
330 do { \
331 _rc = (exp); \
332 } while (_rc == -1 && errno == EINTR); \
333 _rc; })
334
335static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
336{
337 while (count != 0) {
338 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
339 if (actual < 0) {
340 int err = errno;
341 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
342 return err;
343 } else if (actual != (ssize_t) count) {
344 LOGD("%s: partial write (will retry): (%d of %zd)\n",
345 logMsg, (int) actual, count);
346 buf = (const void*) (((const uint8_t*) buf) + actual);
347 }
348 count -= actual;
349 }
350
351 return 0;
352}
353
Zonr Chang932648d2010-10-13 22:23:56 +0800354//
355// Compilation class that suits Android's needs.
356// (Support: no argument passed, ...)
357//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700358namespace bcc {
359
360class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800361 // This part is designed to be orthogonal to those exported bcc*() functions
362 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700363
Zonr Chang932648d2010-10-13 22:23:56 +0800364 //////////////////////////////////////////////////////////////////////////////
365 // The variable section below (e.g., Triple, CodeGenOptLevel)
366 // is initialized in GlobalInitialization()
367 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700368 static bool GlobalInitialized;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800369 static char *BccCodeAddr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700370
Zonr Chang932648d2010-10-13 22:23:56 +0800371 // If given, this will be the name of the target triple to compile for.
372 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700373 static std::string Triple;
374
375 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700376
Zonr Chang932648d2010-10-13 22:23:56 +0800377 // End of section of GlobalInitializing variables
378 //////////////////////////////////////////////////////////////////////////////
379
380 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700381 static std::string CPU;
382
Zonr Chang932648d2010-10-13 22:23:56 +0800383 // The list of target specific features to enable or disable -- this should
384 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700385 static std::vector<std::string> Features;
386
387 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800388 const char *mName;
389 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700390 };
391 static struct Runtime Runtimes[];
392
393 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800394 if (GlobalInitialized)
395 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700396
Zonr Chang932648d2010-10-13 22:23:56 +0800397 // if (!llvm::llvm_is_multithreaded())
398 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700399
Zonr Chang932648d2010-10-13 22:23:56 +0800400 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700401 Triple = TARGET_TRIPLE_STRING;
402
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800403 // TODO(sliao): NEON for JIT
Zonr Chang932648d2010-10-13 22:23:56 +0800404 // Features.push_back("+neon");
405 // Features.push_back("+vmlx");
406 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700407 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700408 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700409
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700410#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
411 LLVMInitializeARMTargetInfo();
412 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700413#if defined(USE_DISASSEMBLER)
414 LLVMInitializeARMDisassembler();
415 LLVMInitializeARMAsmPrinter();
416#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700417#endif
418
419#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
420 LLVMInitializeX86TargetInfo();
421 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700422#if defined(USE_DISASSEMBLER)
423 LLVMInitializeX86Disassembler();
424 LLVMInitializeX86AsmPrinter();
425#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700426#endif
427
428#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
429 LLVMInitializeX86TargetInfo();
430 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700431#if defined(USE_DISASSEMBLER)
432 LLVMInitializeX86Disassembler();
433 LLVMInitializeX86AsmPrinter();
434#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700435#endif
436
Zonr Chang932648d2010-10-13 22:23:56 +0800437 // -O0: llvm::CodeGenOpt::None
438 // -O1: llvm::CodeGenOpt::Less
439 // -O2: llvm::CodeGenOpt::Default
440 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700441 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700442
Zonr Chang932648d2010-10-13 22:23:56 +0800443 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700444
Zonr Chang932648d2010-10-13 22:23:56 +0800445 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700446 llvm::NoFramePointerElim = false;
447
Zonr Chang932648d2010-10-13 22:23:56 +0800448 // Use hardfloat ABI
449 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800450 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800451 // softfp. To use softfp, change following 2 lines to
452 //
453 // llvm::FloatABIType = llvm::FloatABI::Soft;
454 // llvm::UseSoftFloat = true;
455 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700456 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700457 llvm::UseSoftFloat = false;
458
Zonr Chang932648d2010-10-13 22:23:56 +0800459 // BCC needs all unknown symbols resolved at JIT/compilation time.
460 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700461 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
462
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700463#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800464 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700465 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
466#else
Zonr Chang932648d2010-10-13 22:23:56 +0800467 // This is set for the linker (specify how large of the virtual addresses
468 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700469 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
470#endif
471
Zonr Chang932648d2010-10-13 22:23:56 +0800472 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700473 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
474
Zonr Chang932648d2010-10-13 22:23:56 +0800475 // Register allocation policy:
476 // createFastRegisterAllocator: fast but bad quality
477 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700478 llvm::RegisterRegAlloc::setDefault
479 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700480 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700481 llvm::createLinearScanRegisterAllocator);
482
483 GlobalInitialized = true;
484 return;
485 }
486
487 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800488 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700489 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700490 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800491 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700492 }
493
494 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700495 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700496 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700497
498 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700499 std::string mError;
500
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700501 inline bool hasError() const {
502 return !mError.empty();
503 }
Zonr Chang932648d2010-10-13 22:23:56 +0800504 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700505 mError.assign(Error); // Copying
506 return;
507 }
Zonr Chang932648d2010-10-13 22:23:56 +0800508 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700509 mError = Error;
510 return;
511 }
512
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800513 bool mUseCache; // Set by readBC()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800514 bool mCacheNew; // Set by readBC()
515 int mCacheFd; // Set by readBC()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800516 char *mCacheMapAddr; // Set by loadCacheFile() if mCacheNew is false
517 oBCCHeader *mCacheHdr; // Set by loadCacheFile()
518 size_t mCacheSize; // Set by loadCacheFile()
519 ptrdiff_t mCacheDiff; // Set by loadCacheFile()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800520 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
521 // Used by genCacheFile() for dumping
522
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700523 typedef std::list< std::pair<std::string, std::string> > PragmaList;
524 PragmaList mPragmas;
525
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700526 typedef std::list<void*> ExportVarList;
527 ExportVarList mExportVars;
528
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700529 typedef std::list<void*> ExportFuncList;
530 ExportFuncList mExportFuncs;
531
Zonr Chang932648d2010-10-13 22:23:56 +0800532 //////////////////////////////////////////////////////////////////////////////
533 // Memory manager for the code reside in memory
534 //
535 // The memory for our code emitter is very simple and is conforming to the
536 // design decisions of Android RenderScript's Exection Environment:
537 // The code, data, and symbol sizes are limited (currently 100KB.)
538 //
539 // It's very different from typical compiler, which has no limitation
540 // on the code size. How does code emitter know the size of the code
541 // it is about to emit? It does not know beforehand. We want to solve
542 // this without complicating the code emitter too much.
543 //
544 // We solve this by pre-allocating a certain amount of memory,
545 // and then start the code emission. Once the buffer overflows, the emitter
546 // simply discards all the subsequent emission but still has a counter
547 // on how many bytes have been emitted.
548 //
549 // So once the whole emission is done, if there's a buffer overflow,
550 // it re-allocates the buffer with enough size (based on the
551 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800552
553 // 128 KiB for code
554 static const unsigned int MaxCodeSize = 128 * 1024;
555 // 1 KiB for global offset table (GOT)
556 static const unsigned int MaxGOTSize = 1 * 1024;
557 // 128 KiB for global variable
558 static const unsigned int MaxGlobalVarSize = 128 * 1024;
559
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700560 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700561 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800562 //
563 // Our memory layout is as follows:
564 //
565 // The direction of arrows (-> and <-) shows memory's growth direction
566 // when more space is needed.
567 //
568 // @mpCodeMem:
569 // +--------------------------------------------------------------+
570 // | Function Memory ... -> <- ... Stub/GOT |
571 // +--------------------------------------------------------------+
572 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
573 //
574 // Where size of GOT is @MaxGOTSize KiB.
575 //
576 // @mpGVMem:
577 // +--------------------------------------------------------------+
578 // | Global variable ... -> |
579 // +--------------------------------------------------------------+
580 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
581 //
582 //
583 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
584 // of function code's memory usage
585 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
586 // of stub/GOT's memory usage
587 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
588 // of global variable's memory usage
589 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700590 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700591 uintptr_t mCurSGMemIdx;
592 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800593 void *mpCodeMem;
594 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700595
Zonr Chang932648d2010-10-13 22:23:56 +0800596 // GOT Base
597 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700598
599 typedef std::map<const llvm::Function*, pair<void* /* start address */,
600 void* /* end address */>
601 > FunctionMapTy;
602 FunctionMapTy mFunctionMap;
603
Zonr Chang932648d2010-10-13 22:23:56 +0800604 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700605 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700606 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700607
Zonr Chang932648d2010-10-13 22:23:56 +0800608 uint8_t *allocateSGMemory(uintptr_t Size,
609 unsigned Alignment = 1 /* no alignment */) {
610 intptr_t FreeMemSize = getFreeCodeMemSize();
611 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
612 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700613 return NULL;
614
Zonr Chang932648d2010-10-13 22:23:56 +0800615 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700616 Alignment = 1;
617
Zonr Chang932648d2010-10-13 22:23:56 +0800618 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700619 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
620
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700621 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700622
623 return result;
624 }
625
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700626 inline uintptr_t getFreeGVMemSize() const {
627 return MaxGlobalVarSize - mCurGVMemIdx;
628 }
Zonr Chang932648d2010-10-13 22:23:56 +0800629 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700630 return reinterpret_cast<uint8_t*>(mpGVMem);
631 }
632
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700633 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700634 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700635 reset();
636 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700637
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800638 if (Compiler::BccCodeAddr) { // Try to use BccCodeAddr
639 mpCodeMem = mmap(reinterpret_cast<void*>(Compiler::BccCodeAddr),
Loganad7e8e12010-11-22 20:43:43 +0800640 MaxCodeSize + MaxGlobalVarSize,
641 PROT_READ | PROT_EXEC | PROT_WRITE,
642 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
643 -1, 0);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800644
Loganad7e8e12010-11-22 20:43:43 +0800645 if (mpCodeMem == MAP_FAILED) {
646 LOGE("Mmap mpCodeMem at %p failed with reason: %s.\n",
647 reinterpret_cast<void *>(BCC_CODE_ADDR), strerror(errno));
648 LOGE("Retry to mmap mpCodeMem at arbitary address\n");
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800649 // TODO(sliao): Future: Should we retry at
650 // BccCodeAddr + MaxCodeSize + MaxGlobalVarSize?
651
652 } else {
653 Compiler::BccCodeAddr += MaxCodeSize + MaxGlobalVarSize;
Loganad7e8e12010-11-22 20:43:43 +0800654 }
655 }
656
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800657 if (!Compiler::BccCodeAddr || mpCodeMem == MAP_FAILED) {
658 // If no BccCodeAddr specified, or we can't allocate
Loganad7e8e12010-11-22 20:43:43 +0800659 // mpCodeMem in previous mmap, then allocate them in arbitary
Shih-wei Liaobc5ed672010-11-24 01:53:02 -0800660 // location and rely on relocation.
661 // Note: Will incur time overhead in relocating when reloading from disk
Loganad7e8e12010-11-22 20:43:43 +0800662
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800663 mpCodeMem = mmap(NULL,
664 MaxCodeSize + MaxGlobalVarSize,
665 PROT_READ | PROT_EXEC | PROT_WRITE,
666 MAP_PRIVATE | MAP_ANON,
Loganad7e8e12010-11-22 20:43:43 +0800667 -1, 0);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800668
Loganad7e8e12010-11-22 20:43:43 +0800669 if (mpCodeMem == MAP_FAILED) {
670 LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
671 llvm::report_fatal_error("Failed to allocate memory for emitting "
672 "codes\n" + ErrMsg);
673 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800674 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800675
Loganad7e8e12010-11-22 20:43:43 +0800676 // Set global variable pool
677 mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
678
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700679 return;
680 }
681
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800682 inline uint8_t *getCodeMemBase() const {
683 return reinterpret_cast<uint8_t*>(mpCodeMem);
684 }
685
Zonr Chang932648d2010-10-13 22:23:56 +0800686 // setMemoryWritable - When code generation is in progress, the code pages
687 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700688 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700689 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700690 return;
691 }
692
Zonr Chang932648d2010-10-13 22:23:56 +0800693 // When code generation is done and we're ready to start execution, the
694 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700695 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700696 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700697 return;
698 }
699
Zonr Chang932648d2010-10-13 22:23:56 +0800700 // Setting this flag to true makes the memory manager garbage values over
701 // freed memory. This is useful for testing and debugging, and is to be
702 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700703 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800704 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700705 return;
706 }
707
Zonr Chang932648d2010-10-13 22:23:56 +0800708 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700709
Zonr Chang932648d2010-10-13 22:23:56 +0800710 // If the current table requires a Global Offset Table, this method is
711 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700712 void AllocateGOT() {
713 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700714 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700715 HasGOT = true;
716 return;
717 }
718
Zonr Chang932648d2010-10-13 22:23:56 +0800719 // If this is managing a Global Offset Table, this method should return a
720 // pointer to its base.
721 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700722 return mpGOTBase;
723 }
724
Zonr Chang932648d2010-10-13 22:23:56 +0800725 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700726
Zonr Chang932648d2010-10-13 22:23:56 +0800727 // When we start JITing a function, the JIT calls this method to allocate a
728 // block of free RWX memory, which returns a pointer to it. If the JIT wants
729 // to request a block of memory of at least a certain size, it passes that
730 // value as ActualSize, and this method returns a block with at least that
731 // much space. If the JIT doesn't know ahead of time how much space it will
732 // need to emit the function, it passes 0 for the ActualSize. In either
733 // case, this method is required to pass back the size of the allocated
734 // block through ActualSize. The JIT will be careful to not write more than
735 // the returned ActualSize bytes of memory.
736 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
737 intptr_t FreeMemSize = getFreeCodeMemSize();
738 if ((FreeMemSize < 0) ||
739 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
740 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700741 return NULL;
742
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700743 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700744 return (getCodeMemBase() + mCurFuncMemIdx);
745 }
746
Zonr Chang932648d2010-10-13 22:23:56 +0800747 // This method is called by the JIT to allocate space for a function stub
748 // (used to handle limited branch displacements) while it is JIT compiling a
749 // function. For example, if foo calls bar, and if bar either needs to be
750 // lazily compiled or is a native function that exists too far away from the
751 // call site to work, this method will be used to make a thunk for it. The
752 // stub should be "close" to the current function body, but should not be
753 // included in the 'actualsize' returned by startFunctionBody.
754 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700755 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700756 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700757 }
758
Zonr Chang932648d2010-10-13 22:23:56 +0800759 // This method is called when the JIT is done codegen'ing the specified
760 // function. At this point we know the size of the JIT compiled function.
761 // This passes in FunctionStart (which was returned by the startFunctionBody
762 // method) and FunctionEnd which is a pointer to the actual end of the
763 // function. This method should mark the space allocated and remember where
764 // it is in case the client wants to deallocate it.
765 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
766 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700767 assert(FunctionEnd > FunctionStart);
768 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
769 "Mismatched function start/end!");
770
Zonr Chang932648d2010-10-13 22:23:56 +0800771 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700772 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700773 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700774 "Code size excess the limitation!");
775 mCurFuncMemIdx += FunctionCodeSize;
776
Zonr Chang932648d2010-10-13 22:23:56 +0800777 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700778 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
779 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800780 mFunctionMap.insert(
781 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
782 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700783
784 return;
785 }
786
Zonr Chang932648d2010-10-13 22:23:56 +0800787 // Allocate a (function code) memory block of the given size. This method
788 // cannot be called between calls to startFunctionBody and endFunctionBody.
789 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
790 if (getFreeCodeMemSize() < Size)
791 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700792 return NULL;
793
Zonr Chang932648d2010-10-13 22:23:56 +0800794 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700795 Alignment = 1;
796
Zonr Chang932648d2010-10-13 22:23:56 +0800797 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700798 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800799 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700800
801 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
802
803 return result;
804 }
805
Zonr Chang932648d2010-10-13 22:23:56 +0800806 // Allocate memory for a global variable.
807 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700808 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800809 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700810 LOGE("No Global Memory");
811 return NULL;
812 }
813
Zonr Chang932648d2010-10-13 22:23:56 +0800814 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700815 Alignment = 1;
816
Zonr Chang932648d2010-10-13 22:23:56 +0800817 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700818 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800819 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700820
821 mCurGVMemIdx = (result + Size) - getGVMemBase();
822
823 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700824 }
825
Zonr Chang932648d2010-10-13 22:23:56 +0800826 // Free the specified function body. The argument must be the return value
827 // from a call to startFunctionBody() that hasn't been deallocated yet. This
828 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700829 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800830 // linear search
831 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
832 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
833 E = mFunctionMap.end();
834 I != E;
835 I++)
836 if (I->second.first == Body) {
837 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
838 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700839 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800840 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700841
Zonr Chang932648d2010-10-13 22:23:56 +0800842 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700843
Zonr Chang932648d2010-10-13 22:23:56 +0800844 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700845 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
846
847 assert(SizeNeedMove >= 0 &&
848 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
849 " be correctly calculated!");
850
Zonr Chang932648d2010-10-13 22:23:56 +0800851 if (SizeNeedMove > 0)
852 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700853 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
854 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
855
856 return;
857 }
858
Zonr Chang932648d2010-10-13 22:23:56 +0800859 // When we finished JITing the function, if exception handling is set, we
860 // emit the exception table.
861 uint8_t *startExceptionTable(const llvm::Function *F,
862 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700863 assert(false && "Exception is not allowed in our language specification");
864 return NULL;
865 }
866
Zonr Chang932648d2010-10-13 22:23:56 +0800867 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700868 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800869 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700870 assert(false && "Exception is not allowed in our language specification");
871 return;
872 }
873
Zonr Chang932648d2010-10-13 22:23:56 +0800874 // Free the specified exception table's memory. The argument must be the
875 // return value from a call to startExceptionTable() that hasn't been
876 // deallocated yet. This is never called when the JIT is currently emitting
877 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700878 void deallocateExceptionTable(void *ET) {
879 assert(false && "Exception is not allowed in our language specification");
880 return;
881 }
882
Zonr Chang932648d2010-10-13 22:23:56 +0800883 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700884 void reset() {
885 mpGOTBase = NULL;
886 HasGOT = false;
887
888 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700889 mCurSGMemIdx = MaxCodeSize - 1;
890 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700891
892 mFunctionMap.clear();
893
894 return;
895 }
896
897 ~CodeMemoryManager() {
Loganad7e8e12010-11-22 20:43:43 +0800898 if (mpCodeMem != NULL && mpCodeMem != MAP_FAILED)
899 munmap(mpCodeMem, MaxCodeSize + MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700900 return;
901 }
Zonr Chang932648d2010-10-13 22:23:56 +0800902 };
903 // End of class CodeMemoryManager
904 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700905
Zonr Chang932648d2010-10-13 22:23:56 +0800906 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700907 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800908 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700909 mCodeMemMgr.reset(new CodeMemoryManager());
910 return mCodeMemMgr.get();
911 }
912
Zonr Chang932648d2010-10-13 22:23:56 +0800913 //////////////////////////////////////////////////////////////////////////////
914 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700915 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700916 public:
917 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
918 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
919
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800920 GlobalAddressMapTy mGlobalAddressMap;
921
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700922 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800923 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700924
Zonr Chang932648d2010-10-13 22:23:56 +0800925 // The JITInfo for the target we are compiling to
926 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700927
Zonr Chang932648d2010-10-13 22:23:56 +0800928 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700929
Zonr Chang932648d2010-10-13 22:23:56 +0800930 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700931
932 class EmittedFunctionCode {
933 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800934 // Beginning of the function's allocation.
935 void *FunctionBody;
936
937 // The address the function's code actually starts at.
938 void *Code;
939
940 // The size of the function code
941 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700942
943 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
944 };
Zonr Chang932648d2010-10-13 22:23:56 +0800945 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700946
Zonr Chang932648d2010-10-13 22:23:56 +0800947 typedef std::map<const std::string,
948 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700949 EmittedFunctionsMapTy mEmittedFunctions;
950
Zonr Chang932648d2010-10-13 22:23:56 +0800951 // This vector is a mapping from MBB ID's to their address. It is filled in
952 // by the StartMachineBasicBlock callback and queried by the
953 // getMachineBasicBlockAddress callback.
954 std::vector<uintptr_t> mMBBLocations;
955
956 // The constant pool for the current function.
957 llvm::MachineConstantPool *mpConstantPool;
958
959 // A pointer to the first entry in the constant pool.
960 void *mpConstantPoolBase;
961
962 // Addresses of individual constant pool entries.
963 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
964
965 // The jump tables for the current function.
966 llvm::MachineJumpTableInfo *mpJumpTable;
967
968 // A pointer to the first entry in the jump table.
969 void *mpJumpTableBase;
970
971 // When outputting a function stub in the context of some other function, we
972 // save BufferBegin/BufferEnd/CurBufferPtr here.
973 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
974
975 // These are the relocations that the function needs, as emitted.
976 std::vector<llvm::MachineRelocation> mRelocations;
977
Logan824dd0a2010-11-20 01:45:54 +0800978 std::vector<oBCCRelocEntry> mCachingRelocations;
979
Zonr Chang932648d2010-10-13 22:23:56 +0800980 // This vector is a mapping from Label ID's to their address.
981 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
982
983 // Machine module info for exception informations
984 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700985
Zonr Chang932648d2010-10-13 22:23:56 +0800986 // Replace an existing mapping for GV with a new address. This updates both
987 // maps as required. If Addr is null, the entry for the global is removed
988 // from the mappings.
989 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
990 if (Addr == NULL) {
991 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700992 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
993 void *OldVal;
994
Zonr Chang932648d2010-10-13 22:23:56 +0800995 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700996 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800997 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700998 OldVal = I->second;
999 mGlobalAddressMap.erase(I);
1000 }
1001
1002 return OldVal;
1003 }
1004
Zonr Chang932648d2010-10-13 22:23:56 +08001005 void *&CurVal = mGlobalAddressMap[GV];
1006 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001007
1008 CurVal = Addr;
1009
1010 return OldVal;
1011 }
1012
Zonr Chang932648d2010-10-13 22:23:56 +08001013 // Tell the execution engine that the specified global is at the specified
1014 // location. This is used internally as functions are JIT'd and as global
1015 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001016 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001017 void *&CurVal = mGlobalAddressMap[GV];
1018 assert((CurVal == 0 || Addr == 0) &&
1019 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001020 CurVal = Addr;
1021 return;
1022 }
1023
Zonr Chang932648d2010-10-13 22:23:56 +08001024 // This returns the address of the specified global value if it is has
1025 // already been codegen'd, otherwise it returns null.
1026 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001027 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001028 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
1029 }
1030
Zonr Chang932648d2010-10-13 22:23:56 +08001031 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
1032 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001033 MCP->getConstants();
1034
Zonr Chang932648d2010-10-13 22:23:56 +08001035 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001036 return 0;
1037
1038 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001039 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001040 llvm::MachineConstantPoolEntry CPE = Constants[i];
1041 unsigned int AlignMask = CPE.getAlignment() - 1;
1042 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +08001043 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001044 Size += mpTD->getTypeAllocSize(Ty);
1045 }
1046
1047 return Size;
1048 }
1049
Zonr Chang932648d2010-10-13 22:23:56 +08001050 // This function converts a Constant* into a GenericValue. The interesting
1051 // part is if C is a ConstantExpr.
1052 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
1053 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001054 return;
Zonr Chang932648d2010-10-13 22:23:56 +08001055 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
1056 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
1057 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001058
Zonr Chang932648d2010-10-13 22:23:56 +08001059 switch (CE->getOpcode()) {
1060 case llvm::Instruction::GetElementPtr: {
1061 // Compute the index
1062 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
1063 CE->op_end());
1064 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
1065 &Indices[0],
1066 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001067
Zonr Chang932648d2010-10-13 22:23:56 +08001068 GetConstantValue(Op0, Result);
1069 Result.PointerVal =
1070 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001071
Zonr Chang932648d2010-10-13 22:23:56 +08001072 return;
1073 }
1074 case llvm::Instruction::Trunc: {
1075 uint32_t BitWidth =
1076 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1077
1078 GetConstantValue(Op0, Result);
1079 Result.IntVal = Result.IntVal.trunc(BitWidth);
1080
1081 return;
1082 }
1083 case llvm::Instruction::ZExt: {
1084 uint32_t BitWidth =
1085 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1086
1087 GetConstantValue(Op0, Result);
1088 Result.IntVal = Result.IntVal.zext(BitWidth);
1089
1090 return;
1091 }
1092 case llvm::Instruction::SExt: {
1093 uint32_t BitWidth =
1094 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1095
1096 GetConstantValue(Op0, Result);
1097 Result.IntVal = Result.IntVal.sext(BitWidth);
1098
1099 return;
1100 }
1101 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001102 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001103 GetConstantValue(Op0, Result);
1104 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1105 return;
1106 }
1107 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001108 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001109 GetConstantValue(Op0, Result);
1110 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1111 return;
1112 }
1113 case llvm::Instruction::UIToFP: {
1114 GetConstantValue(Op0, Result);
1115 if (CE->getType()->isFloatTy())
1116 Result.FloatVal =
1117 static_cast<float>(Result.IntVal.roundToDouble());
1118 else if (CE->getType()->isDoubleTy())
1119 Result.DoubleVal = Result.IntVal.roundToDouble();
1120 else if (CE->getType()->isX86_FP80Ty()) {
1121 const uint64_t zero[] = { 0, 0 };
1122 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1123 apf.convertFromAPInt(Result.IntVal,
1124 false,
1125 llvm::APFloat::rmNearestTiesToEven);
1126 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001127 }
Zonr Chang932648d2010-10-13 22:23:56 +08001128 return;
1129 }
1130 case llvm::Instruction::SIToFP: {
1131 GetConstantValue(Op0, Result);
1132 if (CE->getType()->isFloatTy())
1133 Result.FloatVal =
1134 static_cast<float>(Result.IntVal.signedRoundToDouble());
1135 else if (CE->getType()->isDoubleTy())
1136 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1137 else if (CE->getType()->isX86_FP80Ty()) {
1138 const uint64_t zero[] = { 0, 0 };
1139 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1140 apf.convertFromAPInt(Result.IntVal,
1141 true,
1142 llvm::APFloat::rmNearestTiesToEven);
1143 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001144 }
Zonr Chang932648d2010-10-13 22:23:56 +08001145 return;
1146 }
1147 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001148 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001149 case llvm::Instruction::FPToSI: {
1150 uint32_t BitWidth =
1151 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001152
Zonr Chang932648d2010-10-13 22:23:56 +08001153 GetConstantValue(Op0, Result);
1154 if (Op0->getType()->isFloatTy())
1155 Result.IntVal =
1156 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1157 else if (Op0->getType()->isDoubleTy())
1158 Result.IntVal =
1159 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1160 BitWidth);
1161 else if (Op0->getType()->isX86_FP80Ty()) {
1162 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1163 uint64_t V;
1164 bool Ignored;
1165 apf.convertToInteger(&V,
1166 BitWidth,
1167 CE->getOpcode() == llvm::Instruction::FPToSI,
1168 llvm::APFloat::rmTowardZero,
1169 &Ignored);
1170 Result.IntVal = V; // endian?
1171 }
1172 return;
1173 }
1174 case llvm::Instruction::PtrToInt: {
1175 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1176
1177 GetConstantValue(Op0, Result);
1178 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1179 (Result.PointerVal));
1180
1181 return;
1182 }
1183 case llvm::Instruction::IntToPtr: {
1184 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1185
1186 GetConstantValue(Op0, Result);
1187 if (PtrWidth != Result.IntVal.getBitWidth())
1188 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1189 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1190
1191 Result.PointerVal =
1192 llvm::PointerTy(
1193 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1194
1195 return;
1196 }
1197 case llvm::Instruction::BitCast: {
1198 GetConstantValue(Op0, Result);
1199 const llvm::Type *DestTy = CE->getType();
1200
1201 switch (Op0->getType()->getTypeID()) {
1202 case llvm::Type::IntegerTyID: {
1203 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1204 if (DestTy->isFloatTy())
1205 Result.FloatVal = Result.IntVal.bitsToFloat();
1206 else if (DestTy->isDoubleTy())
1207 Result.DoubleVal = Result.IntVal.bitsToDouble();
1208 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001209 }
Zonr Chang932648d2010-10-13 22:23:56 +08001210 case llvm::Type::FloatTyID: {
1211 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1212 Result.IntVal.floatToBits(Result.FloatVal);
1213 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001214 }
Zonr Chang932648d2010-10-13 22:23:56 +08001215 case llvm::Type::DoubleTyID: {
1216 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1217 Result.IntVal.doubleToBits(Result.DoubleVal);
1218 break;
1219 }
1220 case llvm::Type::PointerTyID: {
1221 assert(DestTy->isPointerTy() && "Invalid bitcast");
1222 break; // getConstantValue(Op0) above already converted it
1223 }
1224 default: {
1225 llvm_unreachable("Invalid bitcast operand");
1226 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001227 }
Zonr Chang932648d2010-10-13 22:23:56 +08001228 return;
1229 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001230 case llvm::Instruction::Add:
1231 case llvm::Instruction::FAdd:
1232 case llvm::Instruction::Sub:
1233 case llvm::Instruction::FSub:
1234 case llvm::Instruction::Mul:
1235 case llvm::Instruction::FMul:
1236 case llvm::Instruction::UDiv:
1237 case llvm::Instruction::SDiv:
1238 case llvm::Instruction::URem:
1239 case llvm::Instruction::SRem:
1240 case llvm::Instruction::And:
1241 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001242 case llvm::Instruction::Xor: {
1243 llvm::GenericValue LHS, RHS;
1244 GetConstantValue(Op0, LHS);
1245 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001246
Zonr Chang932648d2010-10-13 22:23:56 +08001247 switch (Op0->getType()->getTypeID()) {
1248 case llvm::Type::IntegerTyID: {
1249 switch (CE->getOpcode()) {
1250 case llvm::Instruction::Add: {
1251 Result.IntVal = LHS.IntVal + RHS.IntVal;
1252 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001253 }
Zonr Chang932648d2010-10-13 22:23:56 +08001254 case llvm::Instruction::Sub: {
1255 Result.IntVal = LHS.IntVal - RHS.IntVal;
1256 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001257 }
Zonr Chang932648d2010-10-13 22:23:56 +08001258 case llvm::Instruction::Mul: {
1259 Result.IntVal = LHS.IntVal * RHS.IntVal;
1260 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001261 }
Zonr Chang932648d2010-10-13 22:23:56 +08001262 case llvm::Instruction::UDiv: {
1263 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1264 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001265 }
Zonr Chang932648d2010-10-13 22:23:56 +08001266 case llvm::Instruction::SDiv: {
1267 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1268 break;
1269 }
1270 case llvm::Instruction::URem: {
1271 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1272 break;
1273 }
1274 case llvm::Instruction::SRem: {
1275 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1276 break;
1277 }
1278 case llvm::Instruction::And: {
1279 Result.IntVal = LHS.IntVal & RHS.IntVal;
1280 break;
1281 }
1282 case llvm::Instruction::Or: {
1283 Result.IntVal = LHS.IntVal | RHS.IntVal;
1284 break;
1285 }
1286 case llvm::Instruction::Xor: {
1287 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1288 break;
1289 }
1290 default: {
1291 llvm_unreachable("Invalid integer opcode");
1292 }
1293 }
1294 break;
1295 }
1296 case llvm::Type::FloatTyID: {
1297 switch (CE->getOpcode()) {
1298 case llvm::Instruction::FAdd: {
1299 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1300 break;
1301 }
1302 case llvm::Instruction::FSub: {
1303 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1304 break;
1305 }
1306 case llvm::Instruction::FMul: {
1307 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1308 break;
1309 }
1310 case llvm::Instruction::FDiv: {
1311 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1312 break;
1313 }
1314 case llvm::Instruction::FRem: {
1315 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1316 break;
1317 }
1318 default: {
1319 llvm_unreachable("Invalid float opcode");
1320 }
1321 }
1322 break;
1323 }
1324 case llvm::Type::DoubleTyID: {
1325 switch (CE->getOpcode()) {
1326 case llvm::Instruction::FAdd: {
1327 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1328 break;
1329 }
1330 case llvm::Instruction::FSub: {
1331 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1332 break;
1333 }
1334 case llvm::Instruction::FMul: {
1335 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1336 break;
1337 }
1338 case llvm::Instruction::FDiv: {
1339 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1340 break;
1341 }
1342 case llvm::Instruction::FRem: {
1343 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1344 break;
1345 }
1346 default: {
1347 llvm_unreachable("Invalid double opcode");
1348 }
1349 }
1350 break;
1351 }
1352 case llvm::Type::X86_FP80TyID:
1353 case llvm::Type::PPC_FP128TyID:
1354 case llvm::Type::FP128TyID: {
1355 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1356 switch (CE->getOpcode()) {
1357 case llvm::Instruction::FAdd: {
1358 apfLHS.add(llvm::APFloat(RHS.IntVal),
1359 llvm::APFloat::rmNearestTiesToEven);
1360 break;
1361 }
1362 case llvm::Instruction::FSub: {
1363 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1364 llvm::APFloat::rmNearestTiesToEven);
1365 break;
1366 }
1367 case llvm::Instruction::FMul: {
1368 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1369 llvm::APFloat::rmNearestTiesToEven);
1370 break;
1371 }
1372 case llvm::Instruction::FDiv: {
1373 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1374 llvm::APFloat::rmNearestTiesToEven);
1375 break;
1376 }
1377 case llvm::Instruction::FRem: {
1378 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1379 llvm::APFloat::rmNearestTiesToEven);
1380 break;
1381 }
1382 default: {
1383 llvm_unreachable("Invalid long double opcode");
1384 }
1385 }
1386 Result.IntVal = apfLHS.bitcastToAPInt();
1387 break;
1388 }
1389 default: {
1390 llvm_unreachable("Bad add type!");
1391 }
1392 } // End switch (Op0->getType()->getTypeID())
1393 return;
1394 }
1395 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001396 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001397 }
1398 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001399
1400 std::string msg;
1401 llvm::raw_string_ostream Msg(msg);
1402 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001403 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001404 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001405
1406 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001407 case llvm::Type::FloatTyID: {
1408 Result.FloatVal =
1409 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001410 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001411 }
1412 case llvm::Type::DoubleTyID: {
1413 Result.DoubleVal =
1414 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001415 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001416 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001417 case llvm::Type::X86_FP80TyID:
1418 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001419 case llvm::Type::PPC_FP128TyID: {
1420 Result.IntVal =
1421 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001422 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001423 }
1424 case llvm::Type::IntegerTyID: {
1425 Result.IntVal =
1426 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001427 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001428 }
1429 case llvm::Type::PointerTyID: {
1430 switch (C->getValueID()) {
1431 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001432 Result.PointerVal = NULL;
1433 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001434 }
1435 case llvm::Value::FunctionVal: {
1436 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1437 Result.PointerVal =
1438 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001439 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001440 }
1441 case llvm::Value::GlobalVariableVal: {
1442 const llvm::GlobalVariable *GV =
1443 static_cast<const llvm::GlobalVariable*>(C);
1444 Result.PointerVal =
1445 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001446 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001447 }
1448 case llvm::Value::BlockAddressVal: {
1449 assert(false && "JIT does not support address-of-label yet!");
1450 }
1451 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001452 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001453 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001454 }
1455 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001456 }
1457 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001458 std::string msg;
1459 llvm::raw_string_ostream Msg(msg);
1460 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001461 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001462 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001463 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001464 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001465 return;
1466 }
1467
Zonr Chang932648d2010-10-13 22:23:56 +08001468 // Stores the data in @Val of type @Ty at address @Addr.
1469 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001470 const llvm::Type *Ty) {
1471 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1472
Zonr Chang932648d2010-10-13 22:23:56 +08001473 switch (Ty->getTypeID()) {
1474 case llvm::Type::IntegerTyID: {
1475 const llvm::APInt &IntVal = Val.IntVal;
1476 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1477 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001478
Zonr Chang932648d2010-10-13 22:23:56 +08001479 const uint8_t *Src =
1480 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001481
Zonr Chang932648d2010-10-13 22:23:56 +08001482 if (llvm::sys::isLittleEndianHost()) {
1483 // Little-endian host - the source is ordered from LSB to MSB.
1484 // Order the destination from LSB to MSB: Do a straight copy.
1485 memcpy(Addr, Src, StoreBytes);
1486 } else {
1487 // Big-endian host - the source is an array of 64 bit words
1488 // ordered from LSW to MSW.
1489 //
1490 // Each word is ordered from MSB to LSB.
1491 //
1492 // Order the destination from MSB to LSB:
1493 // Reverse the word order, but not the bytes in a word.
1494 unsigned int i = StoreBytes;
1495 while (i > sizeof(uint64_t)) {
1496 i -= sizeof(uint64_t);
1497 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1498 Src,
1499 sizeof(uint64_t));
1500 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001501 }
Zonr Chang932648d2010-10-13 22:23:56 +08001502 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001503 }
1504 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001505 }
1506 case llvm::Type::FloatTyID: {
1507 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001508 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001509 }
1510 case llvm::Type::DoubleTyID: {
1511 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001512 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001513 }
1514 case llvm::Type::X86_FP80TyID: {
1515 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001516 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001517 }
1518 case llvm::Type::PointerTyID: {
1519 // Ensure 64 bit target pointers are fully initialized on 32 bit
1520 // hosts.
1521 if (StoreBytes != sizeof(llvm::PointerTy))
1522 memset(Addr, 0, StoreBytes);
1523 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001524 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001525 }
1526 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001527 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001528 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001529 }
1530
Zonr Chang932648d2010-10-13 22:23:56 +08001531 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1532 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1533 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001534
1535 return;
1536 }
1537
Zonr Chang932648d2010-10-13 22:23:56 +08001538 // Recursive function to apply a @Constant value into the specified memory
1539 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001540 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001541 switch (C->getValueID()) {
1542 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001543 // Nothing to do
1544 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001545 }
1546 case llvm::Value::ConstantVectorVal: {
1547 // dynamic cast may hurt performance
1548 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001549
Zonr Chang932648d2010-10-13 22:23:56 +08001550 unsigned int ElementSize = mpTD->getTypeAllocSize
1551 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001552
Zonr Chang932648d2010-10-13 22:23:56 +08001553 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1554 InitializeConstantToMemory(
1555 CP->getOperand(i),
1556 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001557 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001558 }
1559 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001560 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1561 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001562 }
1563 case llvm::Value::ConstantArrayVal: {
1564 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1565 unsigned int ElementSize = mpTD->getTypeAllocSize
1566 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001567
Zonr Chang932648d2010-10-13 22:23:56 +08001568 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1569 InitializeConstantToMemory(
1570 CPA->getOperand(i),
1571 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1572 break;
1573 }
1574 case llvm::Value::ConstantStructVal: {
1575 const llvm::ConstantStruct *CPS =
1576 static_cast<const llvm::ConstantStruct*>(C);
1577 const llvm::StructLayout *SL = mpTD->getStructLayout
1578 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001579
Zonr Chang932648d2010-10-13 22:23:56 +08001580 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1581 InitializeConstantToMemory(
1582 CPS->getOperand(i),
1583 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1584 break;
1585 }
1586 default: {
1587 if (C->getType()->isFirstClassType()) {
1588 llvm::GenericValue Val;
1589 GetConstantValue(C, Val);
1590 StoreValueToMemory(Val, Addr, C->getType());
1591 } else {
1592 llvm_unreachable("Unknown constant type to initialize memory "
1593 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001594 }
1595 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001596 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001597 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001598 return;
1599 }
1600
1601 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001602 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001603 return;
1604
Zonr Chang932648d2010-10-13 22:23:56 +08001605 // Constant pool address resolution is handled by the target itself in ARM
1606 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001607#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001608 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1609 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001610
Zonr Chang932648d2010-10-13 22:23:56 +08001611 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001612 return;
1613
1614 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1615 unsigned Align = MCP->getConstantPoolAlignment();
1616
1617 mpConstantPoolBase = allocateSpace(Size, Align);
1618 mpConstantPool = MCP;
1619
Zonr Chang932648d2010-10-13 22:23:56 +08001620 if (mpConstantPoolBase == NULL)
1621 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001622
1623 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001624 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001625 llvm::MachineConstantPoolEntry CPE = Constants[i];
1626 unsigned AlignMask = CPE.getAlignment() - 1;
1627 Offset = (Offset + AlignMask) & ~AlignMask;
1628
1629 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1630 mConstPoolAddresses.push_back(CAddr);
1631
Zonr Chang932648d2010-10-13 22:23:56 +08001632 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001633 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001634 ("Initialize memory with machine specific constant pool"
1635 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001636
1637 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1638
1639 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1640 Offset += mpTD->getTypeAllocSize(Ty);
1641 }
1642#endif
1643 return;
1644 }
1645
1646 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001647 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001648 return;
1649
Zonr Chang932648d2010-10-13 22:23:56 +08001650 const std::vector<llvm::MachineJumpTableEntry> &JT =
1651 MJTI->getJumpTables();
1652 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001653 return;
1654
1655 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001656 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001657 NumEntries += JT[i].MBBs.size();
1658
1659 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1660
Zonr Chang932648d2010-10-13 22:23:56 +08001661 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001662 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001663 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001664
1665 return;
1666 }
1667
1668 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001669 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001670 return;
1671
Zonr Chang932648d2010-10-13 22:23:56 +08001672 const std::vector<llvm::MachineJumpTableEntry> &JT =
1673 MJTI->getJumpTables();
1674 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001675 return;
1676
Zonr Chang932648d2010-10-13 22:23:56 +08001677 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1678 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1679 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001680
Zonr Chang932648d2010-10-13 22:23:56 +08001681 // For each jump table, map each target in the jump table to the
1682 // address of an emitted MachineBasicBlock.
1683 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1684 for (int i = 0, ie = JT.size(); i != ie; i++) {
1685 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1686 // Store the address of the basic block for this jump table slot in the
1687 // memory we allocated for the jump table in 'initJumpTableInfo'
1688 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001689 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1690 }
1691 }
1692
Zonr Chang932648d2010-10-13 22:23:56 +08001693 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1694 bool MayNeedFarStub) {
1695 switch (V->getValueID()) {
1696 case llvm::Value::FunctionVal: {
1697 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001698
Zonr Chang932648d2010-10-13 22:23:56 +08001699 // If we have code, go ahead and return that.
1700 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1701 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001702
Zonr Chang932648d2010-10-13 22:23:56 +08001703 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1704 // Return the function stub if it's already created.
1705 // We do this first so that:
1706 // we're returning the same address for the function as any
1707 // previous call.
1708 //
1709 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1710 // guaranteed to be close enough to call.
1711 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001712
Zonr Chang932648d2010-10-13 22:23:56 +08001713 // If we know the target can handle arbitrary-distance calls, try to
1714 // return a direct pointer.
1715 if (!MayNeedFarStub) {
1716 //
1717 // x86_64 architecture may encounter the bug:
1718 // http://llvm.org/bugs/show_bug.cgi?id=5201
1719 // which generate instruction "call" instead of "callq".
1720 //
1721 // And once the real address of stub is greater than 64-bit
1722 // long, the replacement will truncate to 32-bit resulting a
1723 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001724#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001725 // If this is an external function pointer, we can force the JIT
1726 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001727 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1728 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1729 // Changing to false because wanting to allow later calls to
1730 // mpTJI->relocate() without aborting. For caching purpose
1731 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001732#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001733 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001734
Zonr Chang932648d2010-10-13 22:23:56 +08001735 // Otherwise, we may need a to emit a stub, and, conservatively, we
1736 // always do so.
1737 return GetLazyFunctionStub(F);
1738 break;
1739 }
1740 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001741 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1742 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001743 }
1744 case llvm::Value::GlobalAliasVal: {
1745 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1746 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001747
Zonr Chang932648d2010-10-13 22:23:56 +08001748 switch (GV->getValueID()) {
1749 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001750 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001751 // code-gen'd?
1752 return GetPointerToFunction(
1753 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001754 /* AbortOnFailure = */false);
1755 // Changing to false because wanting to allow later calls to
1756 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001757 break;
1758 }
1759 case llvm::Value::GlobalVariableVal: {
1760 if (void *P = mGlobalAddressMap[GV])
1761 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001762
Zonr Chang932648d2010-10-13 22:23:56 +08001763 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1764 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001765
Zonr Chang932648d2010-10-13 22:23:56 +08001766 return mGlobalAddressMap[GV];
1767 break;
1768 }
1769 case llvm::Value::GlobalAliasVal: {
1770 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001771 }
1772 }
1773 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001774 }
1775 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001776 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001777 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001778 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001779 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001780 }
1781
Zonr Chang932648d2010-10-13 22:23:56 +08001782 // If the specified function has been code-gen'd, return a pointer to the
1783 // function. If not, compile it, or use a stub to implement lazy compilation
1784 // if available.
1785 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1786 // If we have already code generated the function, just return the
1787 // address.
1788 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001789 return Addr;
1790
Zonr Chang932648d2010-10-13 22:23:56 +08001791 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001792 return GetLazyFunctionStub(F);
1793 }
1794
Zonr Chang932648d2010-10-13 22:23:56 +08001795 typedef llvm::DenseMap<const llvm::Function*,
1796 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001797 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1798
Zonr Chang932648d2010-10-13 22:23:56 +08001799 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001800 return mFunctionToLazyStubMap.lookup(F);
1801 }
1802
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001803 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001804 void *GetLazyFunctionStub(llvm::Function *F) {
1805 // If we already have a lazy stub for this function, recycle it.
1806 void *&Stub = mFunctionToLazyStubMap[F];
1807 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001808 return Stub;
1809
Zonr Chang932648d2010-10-13 22:23:56 +08001810 // In any cases, we should NOT resolve function at runtime (though we are
1811 // able to). We resolve this right now.
1812 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001813 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1814 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1815 // Changing to false because wanting to allow later calls to
1816 // mpTJI->relocate() without aborting. For caching purpose
1817 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001818
Zonr Chang932648d2010-10-13 22:23:56 +08001819 // Codegen a new stub, calling the actual address of the external
1820 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001821 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1822 startGVStub(F, SL.Size, SL.Alignment);
1823 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1824 finishGVStub();
1825
Zonr Chang932648d2010-10-13 22:23:56 +08001826 // We really want the address of the stub in the GlobalAddressMap for the
1827 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001828 UpdateGlobalMapping(F, Stub);
1829
Zonr Chang932648d2010-10-13 22:23:56 +08001830 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001831 PendingFunctions.insert(F);
1832 else
Zonr Chang932648d2010-10-13 22:23:56 +08001833 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1834 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001835
1836 return Stub;
1837 }
1838
Zonr Chang932648d2010-10-13 22:23:56 +08001839 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1840 void *Addr = GetPointerToGlobalIfAvailable(F);
1841 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001842 return Addr;
1843
1844 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1845 "Internal error: only external defined function routes here!");
1846
Zonr Chang932648d2010-10-13 22:23:56 +08001847 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001848 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001849 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001850
Zonr Chang932648d2010-10-13 22:23:56 +08001851 // If we resolved the symbol to a null address (eg. a weak external)
1852 // return a null pointer let the application handle it.
1853 if (Addr == NULL) {
1854 if (AbortOnFailure)
1855 llvm::report_fatal_error("Could not resolve external function "
1856 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001857 else
1858 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001859 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001860
1861 AddGlobalMapping(F, Addr);
1862
1863 return Addr;
1864 }
1865
Zonr Chang932648d2010-10-13 22:23:56 +08001866 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001867 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001868 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001869 return Addr;
1870
Zonr Chang932648d2010-10-13 22:23:56 +08001871 if (mpSymbolLookupFn)
1872 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001873 return Addr;
1874
Zonr Chang932648d2010-10-13 22:23:56 +08001875 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001876 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001877 "' which could not be resolved!");
1878
1879 return NULL;
1880 }
1881
Zonr Chang932648d2010-10-13 22:23:56 +08001882 // Return the address of the specified global variable, possibly emitting it
1883 // to memory if needed. This is used by the Emitter.
1884 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1885 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1886 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001887 return Ptr;
1888
Zonr Chang932648d2010-10-13 22:23:56 +08001889 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1890 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001891 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1892 AddGlobalMapping(GV, Ptr);
1893 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001894 // If the global hasn't been emitted to memory yet, allocate space and
1895 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001896 Ptr = GetMemoryForGV(GV);
1897 AddGlobalMapping(GV, Ptr);
1898 EmitGlobalVariable(GV);
1899 }
1900
1901 return Ptr;
1902 }
1903
Zonr Chang932648d2010-10-13 22:23:56 +08001904 // This method abstracts memory allocation of global variable so that the
1905 // JIT can allocate thread local variables depending on the target.
1906 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1907 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001908
Zonr Chang932648d2010-10-13 22:23:56 +08001909 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001910 size_t S = mpTD->getTypeAllocSize(GlobalType);
1911 size_t A = mpTD->getPreferredAlignment(GV);
1912
Zonr Chang932648d2010-10-13 22:23:56 +08001913 if (GV->isThreadLocal()) {
1914 // We can support TLS by
1915 //
1916 // Ptr = TJI.allocateThreadLocalMemory(S);
1917 //
1918 // But I tend not to.
1919 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001920 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001921 ("Compilation of Thread Local Storage (TLS) is disabled!");
1922
Zonr Chang932648d2010-10-13 22:23:56 +08001923 } else if (mpTJI->allocateSeparateGVMemory()) {
1924 if (A <= 8) {
1925 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001926 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001927 // Allocate (S + A) bytes of memory, then use an aligned pointer
1928 // within that space.
1929 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001930 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001931 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1932 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001933 }
1934 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001935 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001936 }
1937
1938 return Ptr;
1939 }
1940
1941 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001942 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001943
Zonr Chang932648d2010-10-13 22:23:56 +08001944 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001945 llvm::report_fatal_error
1946 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001947
Zonr Chang932648d2010-10-13 22:23:56 +08001948 if (GA == NULL) {
1949 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001950 GA = GetMemoryForGV(GV);
1951 AddGlobalMapping(GV, GA);
1952 }
1953
1954 InitializeConstantToMemory(GV->getInitializer(), GA);
1955
Zonr Chang932648d2010-10-13 22:23:56 +08001956 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001957 return;
1958 }
1959
1960 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1961 > GlobalToIndirectSymMapTy;
1962 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1963
Zonr Chang932648d2010-10-13 22:23:56 +08001964 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1965 // Make sure GV is emitted first, and create a stub containing the fully
1966 // resolved address.
1967 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001968
Zonr Chang932648d2010-10-13 22:23:56 +08001969 // If we already have a stub for this global variable, recycle it.
1970 void *&IndirectSym = GlobalToIndirectSymMap[V];
1971 // Otherwise, codegen a new indirect symbol.
1972 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001973 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1974
1975 return IndirectSym;
1976 }
1977
Zonr Chang932648d2010-10-13 22:23:56 +08001978 // This is the equivalent of FunctionToLazyStubMap for external functions.
1979 //
1980 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1981 // It's actually here to make it more likely that far calls
1982 // succeed, but no single stub can guarantee that. I'll
1983 // remove this in a subsequent checkin when I actually fix
1984 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001985 std::map<void*, void*> ExternalFnToStubMap;
1986
Zonr Chang932648d2010-10-13 22:23:56 +08001987 // Return a stub for the function at the specified address.
1988 void *GetExternalFunctionStub(void *FnAddr) {
1989 void *&Stub = ExternalFnToStubMap[FnAddr];
1990 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001991 return Stub;
1992
1993 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1994 startGVStub(0, SL.Size, SL.Alignment);
1995 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1996 finishGVStub();
1997
1998 return Stub;
1999 }
2000
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002001#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002002 const llvm::MCAsmInfo *mpAsmInfo;
2003 const llvm::MCDisassembler *mpDisassmbler;
2004 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002005
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002006 class BufferMemoryObject : public llvm::MemoryObject {
2007 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002008 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002009 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002010
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002011 public:
2012 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
2013 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002014
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002015 uint64_t getBase() const { return 0; }
2016 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002017
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002018 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002019 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002020 return -1;
2021 *Byte = mBytes[Addr];
2022 return 0;
2023 }
2024 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002025
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002026 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002027 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002028 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08002029 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002030#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002031 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08002032 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
2033 ErrorInfo,
2034 llvm::raw_fd_ostream::F_Append);
2035 if (!ErrorInfo.empty()) { // some errors occurred
2036 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002037 delete OS;
2038 return;
2039 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002040#else
2041 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002042#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002043 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
2044 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002045
Zonr Chang932648d2010-10-13 22:23:56 +08002046 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002047 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08002048 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002049 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08002050 if (mpIP == NULL)
2051 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
2052 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002053
Zonr Chang932648d2010-10-13 22:23:56 +08002054 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
2055 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002056 uint64_t Size;
2057 uint64_t Index;
2058
Zonr Chang932648d2010-10-13 22:23:56 +08002059 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002060 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002061
Zonr Chang932648d2010-10-13 22:23:56 +08002062 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2063 /* REMOVED */ llvm::nulls())) {
2064 (*OS).indent(4)
2065 .write("0x", 2)
2066 .write_hex((uint32_t) Start + Index)
2067 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002068 mpIP->printInst(&Inst, *OS);
2069 *OS << "\n";
2070 } else {
2071 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002072 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002073 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002074 }
2075
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002076 *OS << "\n";
2077 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002078
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002079#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002080 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002081 OS->close();
2082 delete OS;
2083#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002084 return;
2085 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002086#else
Zonr Chang932648d2010-10-13 22:23:56 +08002087 inline void Disassemble(const std::string &Name, uint8_t *Start,
2088 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002089 return;
2090 }
Zonr Chang932648d2010-10-13 22:23:56 +08002091#endif // defined(USE_DISASSEMBLER)
2092
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002093 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002094 // Resolver to undefined symbol in CodeEmitter
2095 BCCSymbolLookupFn mpSymbolLookupFn;
2096 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002097
2098 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002099 // Will take the ownership of @MemMgr
2100 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2101 : mpMemMgr(pMemMgr),
2102 mpTarget(NULL),
2103 mpTJI(NULL),
2104 mpTD(NULL),
2105 mpCurEmitFunction(NULL),
2106 mpConstantPool(NULL),
2107 mpJumpTable(NULL),
2108 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002109#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002110 mpAsmInfo(NULL),
2111 mpDisassmbler(NULL),
2112 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002113#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002114 mpSymbolLookupFn(NULL),
2115 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002116 return;
2117 }
2118
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002119 inline global_addresses_const_iterator global_address_begin() const {
2120 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002121 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002122 inline global_addresses_const_iterator global_address_end() const {
2123 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002124 }
2125
Logan824dd0a2010-11-20 01:45:54 +08002126 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2127 return mCachingRelocations;
2128 }
2129
Zonr Chang932648d2010-10-13 22:23:56 +08002130 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002131 mpSymbolLookupFn = pFn;
2132 mpSymbolLookupContext = pContext;
2133 return;
2134 }
2135
Zonr Chang932648d2010-10-13 22:23:56 +08002136 void setTargetMachine(llvm::TargetMachine &TM) {
2137 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002138 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002139 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002140 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002141 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002142 mpTD = TM.getTargetData();
2143
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002144 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2145
2146 return;
2147 }
2148
Zonr Chang932648d2010-10-13 22:23:56 +08002149 // This callback is invoked when the specified function is about to be code
2150 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002151 void startFunction(llvm::MachineFunction &F) {
2152 uintptr_t ActualSize = 0;
2153
2154 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002155
2156 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2157 // MachineCodeEmitter, which is the super class of the class
2158 // JITCodeEmitter.
2159 //
2160 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2161 // allocated for this code buffer.
2162 //
2163 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2164 // code. This is guranteed to be in the range
2165 // [BufferBegin, BufferEnd]. If this pointer is at
2166 // BufferEnd, it will never move due to code emission, and
2167 // all code emission requests will be ignored (this is the
2168 // buffer overflow condition).
2169 BufferBegin = CurBufferPtr =
2170 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002171 BufferEnd = BufferBegin + ActualSize;
2172
Zonr Chang932648d2010-10-13 22:23:56 +08002173 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002174 mpCurEmitFunction = new EmittedFunctionCode();
2175 mpCurEmitFunction->FunctionBody = BufferBegin;
2176
Zonr Chang932648d2010-10-13 22:23:56 +08002177 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002178 emitAlignment(16);
2179
2180 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002181 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002182 initJumpTableInfo(MJTI);
2183
Zonr Chang932648d2010-10-13 22:23:56 +08002184 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002185 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2186
2187 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2188
2189 mpCurEmitFunction->Code = CurBufferPtr;
2190
2191 mMBBLocations.clear();
2192
2193 return;
2194 }
2195
Zonr Chang932648d2010-10-13 22:23:56 +08002196 // This callback is invoked when the specified function has finished code
2197 // generation. If a buffer overflow has occurred, this method returns true
2198 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002199 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002200 if (CurBufferPtr == BufferEnd) {
2201 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002202 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2203 return false;
2204 }
2205
Zonr Chang932648d2010-10-13 22:23:56 +08002206 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002207 emitJumpTableInfo(MJTI);
2208
Zonr Chang932648d2010-10-13 22:23:56 +08002209 // FnStart is the start of the text, not the start of the constant pool
2210 // and other per-function data.
2211 uint8_t *FnStart =
2212 reinterpret_cast<uint8_t*>(
2213 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002214
Zonr Chang932648d2010-10-13 22:23:56 +08002215 // FnEnd is the end of the function's machine code.
2216 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002217
Zonr Chang932648d2010-10-13 22:23:56 +08002218 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002219 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2220
Zonr Chang932648d2010-10-13 22:23:56 +08002221 // Resolve the relocations to concrete pointers.
2222 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2223 llvm::MachineRelocation &MR = mRelocations[i];
2224 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002225
Zonr Chang932648d2010-10-13 22:23:56 +08002226 if (!MR.letTargetResolve()) {
2227 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002228 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002229
2230 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002231 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002232 }
2233
Zonr Chang932648d2010-10-13 22:23:56 +08002234 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002235 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2236 BufferBegin
2237 + MR.getMachineCodeOffset(),
2238 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002239 } else if (MR.isIndirectSymbol()) {
2240 ResultPtr =
2241 GetPointerToGVIndirectSym(
2242 MR.getGlobalValue(),
2243 BufferBegin + MR.getMachineCodeOffset());
2244 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002245 ResultPtr =
2246 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002247 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002248 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002249 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002250 } else {
2251 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2252 ResultPtr =
2253 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2254 }
2255
Logan824dd0a2010-11-20 01:45:54 +08002256 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2257 // TODO(logan): Cache external symbol relocation entry.
2258 // Currently, we are not caching them. But since Android
2259 // system is using prelink, it is not a problem.
2260
2261 // Cache the relocation result address
2262 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002263 oBCCRelocEntry(MR.getRelocationType(),
2264 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002265 ResultPtr));
2266 }
2267
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002268 MR.setResultPointer(ResultPtr);
2269 }
2270 }
2271
2272 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2273 mpMemMgr->getGOTBase());
2274 }
2275
2276 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002277 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2278 // global variables that were referenced in the relocations.
2279 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002280 return false;
2281
Zonr Chang932648d2010-10-13 22:23:56 +08002282 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002283 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2284 BufferBegin = CurBufferPtr = 0;
2285
Zonr Chang932648d2010-10-13 22:23:56 +08002286 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002287 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2288 mpCurEmitFunction = NULL;
2289
2290 mRelocations.clear();
2291 mConstPoolAddresses.clear();
2292
Zonr Chang932648d2010-10-13 22:23:56 +08002293 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002294 mpMMI->EndFunction();
2295
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002296 updateFunctionStub(F.getFunction());
2297
Zonr Chang932648d2010-10-13 22:23:56 +08002298 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002299 mpMemMgr->setMemoryExecutable();
2300
2301 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2302
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002303 return false;
2304 }
2305
Zonr Chang932648d2010-10-13 22:23:56 +08002306 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002307 unsigned Alignment) {
2308 mpSavedBufferBegin = BufferBegin;
2309 mpSavedBufferEnd = BufferEnd;
2310 mpSavedCurBufferPtr = CurBufferPtr;
2311
2312 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2313 Alignment);
2314 BufferEnd = BufferBegin + StubSize + 1;
2315
2316 return;
2317 }
2318
Zonr Chang932648d2010-10-13 22:23:56 +08002319 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002320 mpSavedBufferBegin = BufferBegin;
2321 mpSavedBufferEnd = BufferEnd;
2322 mpSavedCurBufferPtr = CurBufferPtr;
2323
Zonr Chang932648d2010-10-13 22:23:56 +08002324 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002325 BufferEnd = BufferBegin + StubSize + 1;
2326
2327 return;
2328 }
2329
2330 void finishGVStub() {
2331 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2332
Zonr Chang932648d2010-10-13 22:23:56 +08002333 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002334 BufferBegin = mpSavedBufferBegin;
2335 BufferEnd = mpSavedBufferEnd;
2336 CurBufferPtr = mpSavedCurBufferPtr;
2337
2338 return;
2339 }
2340
Zonr Chang932648d2010-10-13 22:23:56 +08002341 // Allocates and fills storage for an indirect GlobalValue, and returns the
2342 // address.
2343 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002344 const uint8_t *Buffer, size_t Size,
2345 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002346 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002347 memcpy(IndGV, Buffer, Size);
2348 return IndGV;
2349 }
2350
Zonr Chang932648d2010-10-13 22:23:56 +08002351 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002352 void emitLabel(llvm::MCSymbol *Label) {
2353 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002354 return;
2355 }
2356
Zonr Chang932648d2010-10-13 22:23:56 +08002357 // Allocate memory for a global. Unlike allocateSpace, this method does not
2358 // allocate memory in the current output buffer, because a global may live
2359 // longer than the current function.
2360 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2361 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002362 return mpMemMgr->allocateGlobal(Size, Alignment);
2363 }
2364
Zonr Chang932648d2010-10-13 22:23:56 +08002365 // This should be called by the target when a new basic block is about to be
2366 // emitted. This way the MCE knows where the start of the block is, and can
2367 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002368 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002369 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002370 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2371 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2372 return;
2373 }
2374
Zonr Chang932648d2010-10-13 22:23:56 +08002375 // Whenever a relocatable address is needed, it should be noted with this
2376 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002377 void addRelocation(const llvm::MachineRelocation &MR) {
2378 mRelocations.push_back(MR);
2379 return;
2380 }
2381
Zonr Chang932648d2010-10-13 22:23:56 +08002382 // Return the address of the @Index entry in the constant pool that was
2383 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002384 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2385 assert(Index < mpConstantPool->getConstants().size() &&
2386 "Invalid constant pool index!");
2387 return mConstPoolAddresses[Index];
2388 }
2389
Zonr Chang932648d2010-10-13 22:23:56 +08002390 // Return the address of the jump table with index @Index in the function
2391 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002392 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002393 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002394 mpJumpTable->getJumpTables();
2395
Zonr Chang932648d2010-10-13 22:23:56 +08002396 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002397
2398 unsigned int Offset = 0;
2399 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2400
Zonr Chang932648d2010-10-13 22:23:56 +08002401 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002402 Offset += JT[i].MBBs.size();
2403 Offset *= EntrySize;
2404
Zonr Chang932648d2010-10-13 22:23:56 +08002405 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002406 }
2407
Zonr Chang932648d2010-10-13 22:23:56 +08002408 // Return the address of the specified MachineBasicBlock, only usable after
2409 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002410 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2411 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002412 mMBBLocations[MBB->getNumber()] &&
2413 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002414 return mMBBLocations[MBB->getNumber()];
2415 }
2416
Zonr Chang932648d2010-10-13 22:23:56 +08002417 // Return the address of the specified LabelID, only usable after the
2418 // LabelID has been emitted.
2419 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002420 assert(mLabelLocations.count(Label) && "Label not emitted!");
2421 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002422 }
2423
Zonr Chang932648d2010-10-13 22:23:56 +08002424 // Specifies the MachineModuleInfo object. This is used for exception
2425 // handling purposes.
2426 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002427 mpMMI = Info;
2428 return;
2429 }
2430
Zonr Chang932648d2010-10-13 22:23:56 +08002431 void updateFunctionStub(const llvm::Function *F) {
2432 // Get the empty stub we generated earlier.
2433 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002434 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002435 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002436 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002437 else
2438 return;
2439
Zonr Chang932648d2010-10-13 22:23:56 +08002440 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002441
2442 assert(Addr != Stub &&
2443 "Function must have non-stub address to be updated.");
2444
Zonr Chang932648d2010-10-13 22:23:56 +08002445 // Tell the target jit info to rewrite the stub at the specified address,
2446 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002447 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2448 startGVStub(Stub, SL.Size);
2449 mpTJI->emitFunctionStub(F, Addr, *this);
2450 finishGVStub();
2451
Zonr Chang932648d2010-10-13 22:23:56 +08002452 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2453 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002454
2455 PendingFunctions.erase(I);
2456
2457 return;
2458 }
2459
Zonr Chang932648d2010-10-13 22:23:56 +08002460 // Once you finish the compilation on a translation unit, you can call this
2461 // function to recycle the memory (which is used at compilation time and not
2462 // needed for runtime).
2463 //
2464 // NOTE: You should not call this funtion until the code-gen passes for a
2465 // given module is done. Otherwise, the results is undefined and may
2466 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002467 void releaseUnnecessary() {
2468 mMBBLocations.clear();
2469 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002470 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002471 mFunctionToLazyStubMap.clear();
2472 GlobalToIndirectSymMap.clear();
2473 ExternalFnToStubMap.clear();
2474 PendingFunctions.clear();
2475
2476 return;
2477 }
2478
2479 void reset() {
2480 releaseUnnecessary();
2481
2482 mpSymbolLookupFn = NULL;
2483 mpSymbolLookupContext = NULL;
2484
2485 mpTJI = NULL;
2486 mpTD = NULL;
2487
Zonr Chang932648d2010-10-13 22:23:56 +08002488 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2489 E = mEmittedFunctions.end();
2490 I != E;
2491 I++)
2492 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002493 delete I->second;
2494 mEmittedFunctions.clear();
2495
2496 mpMemMgr->reset();
2497
2498 return;
2499 }
2500
Zonr Chang932648d2010-10-13 22:23:56 +08002501 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002502 return lookup( llvm::StringRef(Name) );
2503 }
2504
Zonr Chang932648d2010-10-13 22:23:56 +08002505 void *lookup(const llvm::StringRef &Name) {
2506 EmittedFunctionsMapTy::const_iterator I =
2507 mEmittedFunctions.find(Name.str());
2508 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002509 return NULL;
2510 else
2511 return I->second->Code;
2512 }
2513
Zonr Chang932648d2010-10-13 22:23:56 +08002514 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002515 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002516 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002517 int functionCount = mEmittedFunctions.size();
2518
Zonr Chang932648d2010-10-13 22:23:56 +08002519 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002520 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002521 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002522 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002523 if (functions)
2524 for (EmittedFunctionsMapTy::const_iterator
2525 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2526 (I != E) && (functionCount > 0);
2527 I++, functionCount--)
2528 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002529
2530 return;
2531 }
2532
Zonr Chang932648d2010-10-13 22:23:56 +08002533 void getFunctionBinary(BCCchar *label,
2534 BCCvoid **base,
2535 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002536 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002537 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002538 *base = NULL;
2539 *length = 0;
2540 } else {
2541 *base = I->second->Code;
2542 *length = I->second->Size;
2543 }
2544 return;
2545 }
2546
2547 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002548 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002549#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002550 delete mpAsmInfo;
2551 delete mpDisassmbler;
2552 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002553#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002554 return;
2555 }
Zonr Chang932648d2010-10-13 22:23:56 +08002556 };
2557 // End of Class CodeEmitter
2558 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002559
Zonr Chang932648d2010-10-13 22:23:56 +08002560 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002561 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002562 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002563 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2564 return mCodeEmitter.get();
2565 }
2566
2567 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002568 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002569
Zonr Chang932648d2010-10-13 22:23:56 +08002570 llvm::LLVMContext *mContext;
2571 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002572
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002573 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002574
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002575 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002576 Compiler()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002577 : mUseCache(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002578 mCacheNew(false),
2579 mCacheFd(-1),
2580 mCacheMapAddr(NULL),
2581 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002582 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002583 mCacheDiff(0),
2584 mCodeDataAddr(NULL),
2585 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002586 mpSymbolLookupContext(NULL),
2587 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002588 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002589 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002590 llvm::remove_fatal_error_handler();
2591 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002592 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002593 return;
2594 }
2595
Zonr Chang932648d2010-10-13 22:23:56 +08002596 // interface for BCCscript::registerSymbolCallback()
2597 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002598 mpSymbolLookupFn = pFn;
2599 mpSymbolLookupContext = pContext;
2600 return;
2601 }
2602
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002603 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002604 GlobalInitialization();
2605 mModule = module;
2606 return hasError();
2607 }
2608
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002609 int readBC(const char *bitcode,
2610 size_t bitcodeSize,
2611 const BCCchar *resName) {
2612 GlobalInitialization();
2613
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002614 if (Compiler::BccCodeAddr /* USE_CACHE */ && resName) {
2615 // Turn on mUseCache mode iff
2616 // 1. Has resName
2617 // and, assuming USE_RELOCATE is false:
2618 // 2. Later running code doesn't violate the following condition:
2619 // mCodeDataAddr (set in loadCacheFile()) ==
2620 // mCacheHdr->cachedCodeDataAddr
2621 //
2622 // BTW, this condition is achievable only when in the earlier
2623 // cache-generating run,
2624 // mpCodeMem == BccCodeAddr - MaxCodeSize - MaxGlobalVarSize,
2625 // which means the mmap'ed is in the reserved area,
2626 //
2627 // Note: Upon violation, mUseCache will be set back to false.
2628 mUseCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002629
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002630 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2631 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2632 return -mCacheFd;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002633 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002634 }
2635
2636 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002637
Zonr Chang932648d2010-10-13 22:23:56 +08002638 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002639 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002640
Zonr Chang932648d2010-10-13 22:23:56 +08002641 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002642 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002643 llvm::StringRef(bitcode, bitcodeSize)));
2644
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002645 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002646 setError("Error reading input program bitcode into memory");
2647 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002648 }
2649
Zonr Chang932648d2010-10-13 22:23:56 +08002650 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002651 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2652 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002653 return hasError();
2654 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002655
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002656 int linkBC(const char *bitcode, size_t bitcodeSize) {
2657 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002658
2659 if (bitcode == NULL || bitcodeSize <= 0)
2660 return 0;
2661
2662 if (mModule == NULL) {
2663 setError("No module presents for linking");
2664 return hasError();
2665 }
2666
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002667 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002668 llvm::StringRef(bitcode, bitcodeSize)));
2669
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002670 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002671 setError("Error reading input library bitcode into memory");
2672 return hasError();
2673 }
2674
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002675 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002676 *mContext,
2677 &mError));
2678 if (Lib.get() == NULL)
2679 return hasError();
2680
2681 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2682 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002683
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002684 // Everything for linking should be settled down here with no error occurs
2685 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002686 return hasError();
2687 }
2688
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002689 // interface for bccLoadBinary()
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002690 int loadCacheFile() {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002691 // Check File Descriptor
2692 if (mCacheFd < 0) {
2693 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2694 goto giveup;
2695 }
2696
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002697 // Check File Size
2698 struct stat statCacheFd;
2699 if (fstat(mCacheFd, &statCacheFd) < 0) {
2700 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2701 goto giveup;
2702 }
2703
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002704 mCacheSize = statCacheFd.st_size;
2705
2706 if (mCacheSize < sizeof(oBCCHeader) ||
2707 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002708 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2709 goto giveup;
2710 }
2711
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002712 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2713 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2714 goto giveup;
2715 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002716
2717 // Read File Content
2718 {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002719 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002720 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002721 LOGW("TODO(sliao)@loadCacheFile: mCacheSize=%x, heuristicCodeOffset=%llx",
Loganad7e8e12010-11-22 20:43:43 +08002722 (unsigned int)mCacheSize,
2723 (unsigned long long int)heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002724
2725 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002726 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002727 flock(mCacheFd, LOCK_UN);
2728 LOGE("allocation failed.\n");
2729 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002730 }
2731
2732 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2733 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002734 if (nread != (size_t)heuristicCodeOffset) {
2735 LOGE("read(mCacheFd) failed\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002736 goto bail;
2737 }
2738
2739 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002740 // Sanity check
2741 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2742 LOGE("assertion failed: heuristic code offset is not correct.\n");
2743 goto bail;
2744 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002745 LOGW("TODO(sliao): mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2746 LOGW("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2747 LOGW("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2748 LOGW("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2749 LOGW("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002750
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002751 // Verify the Cache File
2752 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2753 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002754 goto bail;
2755 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002756
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002757 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2758 LOGE("bad oBCC version 0x%08x\n",
2759 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2760 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002761 }
2762
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002763 if (mCacheSize < mCacheHdr->relocOffset +
2764 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2765 LOGE("relocate table overflow\n");
2766 goto bail;
2767 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002768
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002769 if (mCacheSize < mCacheHdr->exportVarsOffset +
2770 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2771 LOGE("export variables table overflow\n");
2772 goto bail;
2773 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002774
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002775 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2776 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2777 LOGE("export functions table overflow\n");
2778 goto bail;
2779 }
2780
2781 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2782 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2783 LOGE("export pragmas table overflow\n");
2784 goto bail;
2785 }
2786
2787 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2788 LOGE("code cache overflow\n");
2789 goto bail;
2790 }
2791
2792 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2793 LOGE("data (global variable) cache overflow\n");
2794 goto bail;
2795 }
2796
2797 // Part 2. Deal with the codedata section
2798 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2799 MaxCodeSize + MaxGlobalVarSize,
2800 PROT_READ | PROT_EXEC | PROT_WRITE,
2801 MAP_PRIVATE | MAP_FIXED,
2802 mCacheFd, heuristicCodeOffset);
2803 if (mCodeDataAddr != MAP_FAILED &&
2804 mCodeDataAddr ==
2805 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr)) {
2806 // relocate is avoidable
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002807
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002808
2809 flock(mCacheFd, LOCK_UN);
2810 } else {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002811#if (USE_RELOCATE)
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002812 mCacheMapAddr = (char *) mmap(0,
2813 mCacheSize,
2814 PROT_READ | PROT_EXEC | PROT_WRITE,
2815 MAP_PRIVATE,
2816 mCacheFd,
2817 0);
2818 if (mCacheMapAddr == MAP_FAILED) {
2819 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2820 flock(mCacheFd, LOCK_UN);
2821 goto giveup;
2822 }
2823
2824 flock(mCacheFd, LOCK_UN);
2825 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002826#else
2827 // TODO(sliao): XXX: Call Compile();
2828 flock(mCacheFd, LOCK_UN);
2829#endif
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002830 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002831 }
2832
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002833#if (USE_RELOCATE)
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002834 // Relocate
2835 {
2836 mCacheDiff = mCodeDataAddr -
2837 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2838
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002839 if (mCacheDiff) { // To relocate
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002840 if (mCacheHdr->rootAddr) {
2841 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002842 }
2843
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002844 if (mCacheHdr->initAddr) {
2845 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002846 }
2847
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002848 oBCCRelocEntry *cachedRelocTable =
2849 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2850 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002851
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002852 std::vector<llvm::MachineRelocation> relocations;
2853
2854 // Read in the relocs
2855 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2856 oBCCRelocEntry *entry = &cachedRelocTable[i];
2857
2858 llvm::MachineRelocation reloc =
2859 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2860 (unsigned)entry->relocType, 0, 0);
2861
2862 reloc.setResultPointer(
2863 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2864
2865 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002866 }
2867
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002868 // Rewrite machine code using llvm::TargetJITInfo relocate
2869 {
2870 llvm::TargetMachine *TM = NULL;
2871 const llvm::Target *Target;
2872 std::string FeaturesStr;
2873
2874 // Create TargetMachine
2875 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2876 if (hasError())
2877 goto bail;
2878
2879 if (!CPU.empty() || !Features.empty()) {
2880 llvm::SubtargetFeatures F;
2881 F.setCPU(CPU);
2882 for (std::vector<std::string>::const_iterator I = Features.begin(),
2883 E = Features.end(); I != E; I++)
2884 F.AddFeature(*I);
2885 FeaturesStr = F.getString();
2886 }
2887
2888 TM = Target->createTargetMachine(Triple, FeaturesStr);
2889 if (TM == NULL) {
2890 setError("Failed to create target machine implementation for the"
2891 " specified triple '" + Triple + "'");
2892 goto bail;
2893 }
2894
2895 TM->getJITInfo()->relocate(mCodeDataAddr,
2896 &relocations[0], relocations.size(),
2897 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2898
2899 if (mCodeEmitter.get()) {
2900 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2901 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2902 2 * 1024 /*MaxCodeSize*/,
2903 false);
2904 }
2905
2906 delete TM;
2907 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002908 } // End of if (mCacheDiff)
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002909 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002910#else
2911 // TODO(sliao): XXX: Call Compile();
2912#endif // End of USE_RELOCATE
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002913 return 0;
2914
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002915 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002916 if (mCacheMapAddr) {
2917 free(mCacheMapAddr);
Loganad7e8e12010-11-22 20:43:43 +08002918 mCacheMapAddr = 0;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002919 }
Loganad7e8e12010-11-22 20:43:43 +08002920
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002921 // if (BccCodeAddrTaken) {
2922 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2923 LOGE("munmap failed: %s\n", strerror(errno));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002924 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08002925 mCodeDataAddr = 0;
2926 //}
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002927
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002928 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002929 return 1;
2930 }
2931
2932 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002933 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002934 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002935
Zonr Chang932648d2010-10-13 22:23:56 +08002936 llvm::TargetMachine *TM = NULL;
2937 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002938 std::string FeaturesStr;
2939
Zonr Chang932648d2010-10-13 22:23:56 +08002940 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002941
Zonr Chang932648d2010-10-13 22:23:56 +08002942 const llvm::NamedMDNode *PragmaMetadata;
2943 const llvm::NamedMDNode *ExportVarMetadata;
2944 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002945
Zonr Chang932648d2010-10-13 22:23:56 +08002946 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002947 return 0;
2948
Zonr Chang932648d2010-10-13 22:23:56 +08002949 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002950 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002951 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002952 goto on_bcc_compile_error;
2953
Zonr Chang932648d2010-10-13 22:23:56 +08002954 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002955 llvm::SubtargetFeatures F;
2956 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002957 for (std::vector<std::string>::const_iterator I = Features.begin(),
2958 E = Features.end();
2959 I != E;
2960 I++)
2961 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002962 FeaturesStr = F.getString();
2963 }
2964
2965 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002966 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002967 setError("Failed to create target machine implementation for the"
2968 " specified triple '" + Triple + "'");
2969 goto on_bcc_compile_error;
2970 }
2971
Zonr Chang932648d2010-10-13 22:23:56 +08002972 // Create memory manager for creation of code emitter later.
2973 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002974 setError("Failed to startup memory management for further compilation");
2975 goto on_bcc_compile_error;
2976 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002977 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002978
Zonr Chang932648d2010-10-13 22:23:56 +08002979 // Create code emitter
2980 if (!mCodeEmitter.get()) {
2981 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002982 setError("Failed to create machine code emitter to complete"
2983 " the compilation");
2984 goto on_bcc_compile_error;
2985 }
2986 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002987 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002988 mCodeEmitter->reset();
2989 }
2990
2991 mCodeEmitter->setTargetMachine(*TM);
2992 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2993 mpSymbolLookupContext);
2994
Zonr Chang932648d2010-10-13 22:23:56 +08002995 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002996 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002997
Zonr Chang5d35b972010-10-23 14:36:47 +08002998 // Load named metadata
2999 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
3000 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
3001 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
3002
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003003 // Create LTO passes and run them on the mModule
3004 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003005 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003006 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08003007 LTOPasses.add(new llvm::TargetData(*TD));
3008
3009 std::vector<const char*> ExportSymbols;
3010
3011 // A workaround for getting export variable and function name. Will refine
3012 // it soon.
3013 if (ExportVarMetadata) {
3014 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3015 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3016 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3017 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3018 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
3019 llvm::StringRef ExportVarName =
3020 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
3021 ExportSymbols.push_back(ExportVarName.data());
3022 }
3023 }
3024 }
3025 }
3026
3027 if (ExportFuncMetadata) {
3028 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3029 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3030 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3031 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3032 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
3033 llvm::StringRef ExportFuncName =
3034 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3035 ExportSymbols.push_back(ExportFuncName.data());
3036 }
3037 }
3038 }
3039 }
3040 // root() and init() are born to be exported
3041 ExportSymbols.push_back("root");
3042 ExportSymbols.push_back("init");
3043
Zonr Change5c7a542010-10-24 01:07:27 +08003044 // We now create passes list performing LTO. These are copied from
3045 // (including comments) llvm::createStandardLTOPasses().
3046
3047 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08003048 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003049
Zonr Change5c7a542010-10-24 01:07:27 +08003050 // Propagate constants at call sites into the functions they call. This
3051 // opens opportunities for globalopt (and inlining) by substituting
3052 // function pointers passed as arguments to direct uses of functions.
3053 LTOPasses.add(llvm::createIPSCCPPass());
3054
3055 // Now that we internalized some globals, see if we can hack on them!
3056 LTOPasses.add(llvm::createGlobalOptimizerPass());
3057
3058 // Linking modules together can lead to duplicated global constants, only
3059 // keep one copy of each constant...
3060 LTOPasses.add(llvm::createConstantMergePass());
3061
3062 // Remove unused arguments from functions...
3063 LTOPasses.add(llvm::createDeadArgEliminationPass());
3064
3065 // Reduce the code after globalopt and ipsccp. Both can open up
3066 // significant simplification opportunities, and both can propagate
3067 // functions through function pointers. When this happens, we often have
3068 // to resolve varargs calls, etc, so let instcombine do this.
3069 LTOPasses.add(llvm::createInstructionCombiningPass());
3070
3071 // Inline small functions
3072 LTOPasses.add(llvm::createFunctionInliningPass());
3073
3074 // Remove dead EH info.
3075 LTOPasses.add(llvm::createPruneEHPass());
3076
3077 // Internalize the globals again after inlining
3078 LTOPasses.add(llvm::createGlobalOptimizerPass());
3079
3080 // Remove dead functions.
3081 LTOPasses.add(llvm::createGlobalDCEPass());
3082
3083 // If we didn't decide to inline a function, check to see if we can
3084 // transform it to pass arguments by value instead of by reference.
3085 LTOPasses.add(llvm::createArgumentPromotionPass());
3086
3087 // The IPO passes may leave cruft around. Clean up after them.
3088 LTOPasses.add(llvm::createInstructionCombiningPass());
3089 LTOPasses.add(llvm::createJumpThreadingPass());
3090
3091 // Break up allocas
3092 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3093
3094 // Run a few AA driven optimizations here and now, to cleanup the code.
3095 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3096 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3097
3098 // Hoist loop invariants.
3099 LTOPasses.add(llvm::createLICMPass());
3100
3101 // Remove redundancies.
3102 LTOPasses.add(llvm::createGVNPass());
3103
3104 // Remove dead memcpys.
3105 LTOPasses.add(llvm::createMemCpyOptPass());
3106
3107 // Nuke dead stores.
3108 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3109
3110 // Cleanup and simplify the code after the scalar optimizations.
3111 LTOPasses.add(llvm::createInstructionCombiningPass());
3112
3113 LTOPasses.add(llvm::createJumpThreadingPass());
3114
3115 // Delete basic blocks, which optimization passes may have killed.
3116 LTOPasses.add(llvm::createCFGSimplificationPass());
3117
3118 // Now that we have optimized the program, discard unreachable functions.
3119 LTOPasses.add(llvm::createGlobalDCEPass());
3120
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003121 LTOPasses.run(*mModule);
3122 }
3123
Zonr Chang932648d2010-10-13 22:23:56 +08003124 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003125 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003126 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003127
Zonr Chang932648d2010-10-13 22:23:56 +08003128 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3129 *mCodeEmitter,
3130 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003131 setError("The machine code emission is not supported by BCC on target '"
3132 + Triple + "'");
3133 goto on_bcc_compile_error;
3134 }
3135
Zonr Chang932648d2010-10-13 22:23:56 +08003136 // Run the pass (the code emitter) on every non-declaration function in the
3137 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003138 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003139 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3140 I != E;
3141 I++)
3142 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003143 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003144
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003145 CodeGenPasses->doFinalization();
3146
Zonr Chang932648d2010-10-13 22:23:56 +08003147 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003148 if (ExportVarMetadata) {
3149 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3150 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3151 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3152 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3153 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003154 llvm::StringRef ExportVarName =
3155 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003156 CodeEmitter::global_addresses_const_iterator I, E;
3157 for (I = mCodeEmitter->global_address_begin(),
3158 E = mCodeEmitter->global_address_end();
3159 I != E;
3160 I++) {
3161 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003162 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003163 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003164 mExportVars.push_back(I->second);
3165 break;
3166 }
3167 }
Zonr Chang932648d2010-10-13 22:23:56 +08003168 if (I != mCodeEmitter->global_address_end())
3169 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003170 }
3171 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003172 // if reaching here, we know the global variable record in metadata is
3173 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003174 mExportVars.push_back(NULL);
3175 }
3176 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3177 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003178 }
3179
Zonr Chang932648d2010-10-13 22:23:56 +08003180 if (ExportFuncMetadata) {
3181 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3182 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3183 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3184 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3185 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003186 llvm::StringRef ExportFuncName =
3187 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3188 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3189 }
3190 }
3191 }
3192 }
3193
Zonr Chang932648d2010-10-13 22:23:56 +08003194 // Tell code emitter now can release the memory using during the JIT since
3195 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003196 mCodeEmitter->releaseUnnecessary();
3197
Zonr Chang932648d2010-10-13 22:23:56 +08003198 // Finally, read pragma information from the metadata node of the @Module if
3199 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003200 if (PragmaMetadata)
3201 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3202 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3203 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003204 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003205 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3206 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003207
Zonr Chang932648d2010-10-13 22:23:56 +08003208 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003209 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3210 llvm::StringRef PragmaName =
3211 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3212 llvm::StringRef PragmaValue =
3213 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3214
Zonr Chang932648d2010-10-13 22:23:56 +08003215 mPragmas.push_back(
3216 std::make_pair(std::string(PragmaName.data(),
3217 PragmaName.size()),
3218 std::string(PragmaValue.data(),
3219 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003220 }
3221 }
3222 }
3223
3224 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003225 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003226 if (CodeGenPasses) {
3227 delete CodeGenPasses;
3228 } else if (TD) {
3229 delete TD;
3230 }
3231 if (TM)
3232 delete TM;
3233
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003234 if (mError.empty()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003235#if !USE_RELOCATE
3236 if (mUseCache && mCacheFd >= 0 && mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003237 genCacheFile();
3238 flock(mCacheFd, LOCK_UN);
3239 }
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003240#else
3241 // TODO(sliao)
3242#endif
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003243 return false;
3244 }
3245
Zonr Chang932648d2010-10-13 22:23:56 +08003246 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003247 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003248 }
3249
Zonr Chang932648d2010-10-13 22:23:56 +08003250 // interface for bccGetScriptInfoLog()
3251 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003252 return const_cast<char*>(mError.c_str());
3253 }
3254
Zonr Chang932648d2010-10-13 22:23:56 +08003255 // interface for bccGetScriptLabel()
3256 void *lookup(const char *name) {
3257 void *addr = NULL;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003258 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003259 if (!strcmp(name, "root")) {
3260 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3261 } else if (!strcmp(name, "init")) {
3262 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3263 }
3264 return addr;
3265 }
3266
Zonr Chang932648d2010-10-13 22:23:56 +08003267 if (mCodeEmitter.get())
3268 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003269 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003270 return addr;
3271 }
3272
Zonr Chang932648d2010-10-13 22:23:56 +08003273 // Interface for bccGetExportVars()
3274 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003275 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003276 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003277 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003278
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003279 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003280 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3281 if (actualVarCount)
3282 *actualVarCount = varCount;
3283 if (varCount > maxVarCount)
3284 varCount = maxVarCount;
3285 if (vars) {
3286 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3287 mCacheHdr->exportVarsOffset);
3288
3289 for (int i = 0; i < varCount; i++) {
3290 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3291 mCacheDiff);
3292 cachedVars++;
3293 }
3294 }
3295 return;
3296 }
3297
3298 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003299 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003300 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003301 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003302 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003303 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003304 for (ExportVarList::const_iterator I = mExportVars.begin(),
3305 E = mExportVars.end();
3306 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003307 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003308 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003309 }
3310 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003311
3312 return;
3313 }
3314
Zonr Chang932648d2010-10-13 22:23:56 +08003315 // Interface for bccGetExportFuncs()
3316 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003317 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003318 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003319 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003320
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003321 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003322 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3323 if (actualFuncCount)
3324 *actualFuncCount = funcCount;
3325 if (funcCount > maxFuncCount)
3326 funcCount = maxFuncCount;
3327 if (funcs) {
3328 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3329 mCacheHdr->exportFuncsOffset);
3330
3331 for (int i = 0; i < funcCount; i++) {
3332 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3333 mCacheDiff);
3334 cachedFuncs++;
3335 }
3336 }
3337 return;
3338 }
3339
3340 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003341 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003342 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003343 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003344 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003345 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003346 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3347 E = mExportFuncs.end();
3348 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003349 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003350 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003351 }
3352 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003353
3354 return;
3355 }
3356
Zonr Chang932648d2010-10-13 22:23:56 +08003357 // Interface for bccGetPragmas()
3358 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003359 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003360 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003361 int stringCount;
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003362 if (mUseCache && mCacheFd >= 0 && !mCacheNew) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003363 if (actualStringCount)
3364 *actualStringCount = 0; // XXX
3365 return;
3366 }
3367
3368 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003369
Zonr Chang932648d2010-10-13 22:23:56 +08003370 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003371 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003372 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003373 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003374 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003375 for (PragmaList::const_iterator it = mPragmas.begin();
3376 stringCount > 0;
3377 stringCount -= 2, it++) {
3378 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3379 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003380 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003381 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003382
3383 return;
3384 }
3385
Zonr Chang932648d2010-10-13 22:23:56 +08003386 // Interface for bccGetFunctions()
3387 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003388 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003389 BCCchar **functions) {
3390 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003391 mCodeEmitter->getFunctionNames(actualFunctionCount,
3392 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003393 functions);
3394 else
3395 *actualFunctionCount = 0;
3396
3397 return;
3398 }
3399
Zonr Chang932648d2010-10-13 22:23:56 +08003400 // Interface for bccGetFunctionBinary()
3401 void getFunctionBinary(BCCchar *function,
3402 BCCvoid **base,
3403 BCCsizei *length) {
3404 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003405 mCodeEmitter->getFunctionBinary(function, base, length);
3406 } else {
3407 *base = NULL;
3408 *length = 0;
3409 }
3410 return;
3411 }
3412
Zonr Chang932648d2010-10-13 22:23:56 +08003413 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003414 return mModule;
3415 }
3416
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003417 ~Compiler() {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003418 if (!mCodeMemMgr.get()) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003419 // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003420 // managed by CodeMemoryManager.
3421
3422 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3423 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3424 LOGE("munmap failed while releasing mCodeDataAddr\n");
3425 }
3426
3427 mCodeDataAddr = 0;
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003428 }
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003429
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003430 if (mCacheMapAddr) {
3431 free(mCacheMapAddr);
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003432 mCacheMapAddr = 0;
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003433 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003434 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003435
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003436 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003437 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003438 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003439 return;
3440 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003441
3442 private:
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003443 // Note: loadCacheFile() and genCacheFile() go hand in hand
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003444 void genCacheFile() {
3445 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3446 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3447 return;
3448 }
3449
3450 bool codeOffsetNeedPadding = false;
3451
3452 uint32_t offset = sizeof(oBCCHeader);
3453
3454 // BCC Cache File Header
3455 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3456
3457 if (!hdr) {
3458 LOGE("Unable to allocate oBCCHeader.\n");
3459 return;
3460 }
3461
3462 // Magic Words
3463 memcpy(hdr->magic, OBCC_MAGIC, 4);
3464 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3465
3466 // Timestamp
3467 hdr->sourceWhen = 0; // TODO(all)
3468 hdr->rslibWhen = 0; // TODO(all)
3469 hdr->libRSWhen = 0; // TODO(all)
3470 hdr->libbccWhen = 0; // TODO(all)
3471
3472 // Current Memory Address (Saved for Recalculation)
3473 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3474 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3475 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3476
3477 // Relocation Table Offset and Entry Count
3478 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003479 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003480
Logan824dd0a2010-11-20 01:45:54 +08003481 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003482
3483 // Export Variable Table Offset and Entry Count
3484 hdr->exportVarsOffset = offset;
3485 hdr->exportVarsCount = mExportVars.size();
3486
3487 offset += hdr->exportVarsCount * sizeof(uint32_t);
3488
3489 // Export Function Table Offset and Entry Count
3490 hdr->exportFuncsOffset = offset;
3491 hdr->exportFuncsCount = mExportFuncs.size();
3492
3493 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3494
3495 // Export Pragmas Table Offset and Entry Count
3496 hdr->exportPragmasOffset = offset;
3497 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3498
3499 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3500
3501 // Code Offset and Size
3502
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003503 //#ifdef BCC_CODE_ADDR
3504 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003505 long pagesize = sysconf(_SC_PAGESIZE);
3506
3507 if (offset % pagesize > 0) {
3508 codeOffsetNeedPadding = true;
3509 offset += pagesize - (offset % pagesize);
3510 }
3511 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003512 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003513 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3514 codeOffsetNeedPadding = true;
3515 offset += 0x08 - (offset & 0x07);
3516 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003517 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003518
3519 hdr->codeOffset = offset;
3520 hdr->codeSize = MaxCodeSize;
3521
3522 offset += hdr->codeSize;
3523
3524 // Data (Global Variable) Offset and Size
3525 hdr->dataOffset = offset;
3526 hdr->dataSize = MaxGlobalVarSize;
3527
3528 offset += hdr->dataSize;
3529
3530 // Checksum
3531 hdr->checksum = 0; // Set Field checksum. TODO(all)
3532
3533 // Write Header
3534 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3535 sizeof(oBCCHeader), "Write oBCC header");
3536
Logan824dd0a2010-11-20 01:45:54 +08003537 // Write Relocation Entry Table
3538 {
3539 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003540
Logan824dd0a2010-11-20 01:45:54 +08003541 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3542
3543 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3544 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003545 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003546
3547 // Write Export Variables Table
3548 {
3549 uint32_t *record, *ptr;
3550
3551 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3552 ptr = record;
3553
3554 if (!record) {
3555 goto bail;
3556 }
3557
3558 for (ExportVarList::const_iterator I = mExportVars.begin(),
3559 E = mExportVars.end(); I != E; I++) {
3560 *ptr++ = reinterpret_cast<uint32_t>(*I);
3561 }
3562
3563 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3564 hdr->exportVarsCount * sizeof(uint32_t),
3565 "Write ExportVars");
3566
3567 free(record);
3568 }
3569
3570 // Write Export Functions Table
3571 {
3572 uint32_t *record, *ptr;
3573
3574 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3575 ptr = record;
3576
3577 if (!record) {
3578 goto bail;
3579 }
3580
3581 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3582 E = mExportFuncs.end(); I != E; I++) {
3583 *ptr++ = reinterpret_cast<uint32_t>(*I);
3584 }
3585
3586 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3587 hdr->exportFuncsCount * sizeof(uint32_t),
3588 "Write ExportFuncs");
3589
3590 free(record);
3591 }
3592
3593
3594 // TODO(all): Write Export Pragmas Table
3595#if 0
3596#else
3597 // Note: As long as we have comment out export pragmas table code,
3598 // we have to seek the position to correct offset.
3599
3600 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3601#endif
3602
3603 if (codeOffsetNeedPadding) {
3604 // requires additional padding
3605 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3606 }
3607
3608 // Write Generated Code and Global Variable
3609 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3610 "Write code and global variable");
3611
3612 goto close_return;
3613
3614 bail:
3615 if (ftruncate(mCacheFd, 0) != 0) {
3616 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3617 }
3618
3619 close_return:
3620 free(hdr);
3621 close(mCacheFd);
3622 mCacheFd = -1;
3623 return;
3624 }
3625
3626 // OpenCacheFile() returns fd of the cache file.
3627 // Input:
3628 // BCCchar *resName: Used to genCacheFileName()
3629 // bool createIfMissing: If false, turn off caching
3630 // Output:
3631 // returns fd: If -1: Failed
3632 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3633 // cache file's file descriptor
3634 // Note: openCacheFile() will check the cache file's validity,
3635 // such as Magic number, sourceWhen... dependencies.
3636 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3637 int fd, cc;
3638 struct stat fdStat, fileStat;
3639 bool readOnly = false;
3640
3641 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3642
3643 mCacheNew = false;
3644
3645 retry:
3646 /*
3647 * Try to open the cache file. If we've been asked to,
3648 * create it if it doesn't exist.
3649 */
3650 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3651 if (fd < 0) {
3652 fd = open(cacheFileName, O_RDONLY, 0);
3653 if (fd < 0) {
3654 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08003655 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003656 cacheFileName, strerror(errno));
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003657 mUseCache = false;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003658 }
3659 return fd;
3660 }
3661 readOnly = true;
3662 }
3663
3664 /*
3665 * Grab an exclusive lock on the cache file. If somebody else is
3666 * working on it, we'll block here until they complete.
3667 */
3668 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3669 cacheFileName, fd);
3670
3671 cc = flock(fd, LOCK_EX | LOCK_NB);
3672 if (cc != 0) {
3673 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3674 cc = flock(fd, LOCK_EX);
3675 }
3676
3677 if (cc != 0) {
3678 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3679 close(fd);
3680 return -1;
3681 }
3682 LOGV("bcc: locked cache file\n");
3683
3684 /*
3685 * Check to see if the fd we opened and locked matches the file in
3686 * the filesystem. If they don't, then somebody else unlinked ours
3687 * and created a new file, and we need to use that one instead. (If
3688 * we caught them between the unlink and the create, we'll get an
3689 * ENOENT from the file stat.)
3690 */
3691 cc = fstat(fd, &fdStat);
3692 if (cc != 0) {
3693 LOGE("Can't stat open file '%s'\n", cacheFileName);
3694 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3695 goto close_fail;
3696 }
3697 cc = stat(cacheFileName, &fileStat);
3698 if (cc != 0 ||
3699 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3700 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3701 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3702 flock(fd, LOCK_UN);
3703 close(fd);
3704 usleep(250 * 1000); // if something is hosed, don't peg machine
3705 goto retry;
3706 }
3707
3708 /*
3709 * We have the correct file open and locked. If the file size is zero,
3710 * then it was just created by us, and we want to fill in some fields
3711 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3712 * verify that the fields in the header match our expectations, and
3713 * reset the file if they don't.
3714 */
3715 if (fdStat.st_size == 0) {
3716 if (readOnly) { // The device is readOnly --> close_fail
3717 LOGW("bcc: file has zero length and isn't writable\n");
3718 goto close_fail;
3719 }
3720 /*cc = createEmptyHeader(fd);
3721 if (cc != 0)
3722 goto close_fail;
3723 */
3724 mCacheNew = true;
3725 LOGV("bcc: successfully initialized new cache file\n");
3726 } else {
3727 // Calculate sourceWhen
3728 // XXX
3729 uint32_t sourceWhen = 0;
3730 uint32_t rslibWhen = 0;
3731 uint32_t libRSWhen = 0;
3732 uint32_t libbccWhen = 0;
3733 if (!checkHeaderAndDependencies(fd,
3734 sourceWhen,
3735 rslibWhen,
3736 libRSWhen,
3737 libbccWhen)) {
3738 // If checkHeaderAndDependencies returns 0: FAILED
3739 // Will truncate the file and retry to createIfMissing the file
3740
3741 if (readOnly) { // Shouldn't be readonly.
3742 /*
3743 * We could unlink and rewrite the file if we own it or
3744 * the "sticky" bit isn't set on the directory. However,
3745 * we're not able to truncate it, which spoils things. So,
3746 * give up now.
3747 */
3748 if (createIfMissing) {
3749 LOGW("Cached file %s is stale and not writable\n",
3750 cacheFileName);
3751 }
3752 goto close_fail;
3753 }
3754
3755 /*
3756 * If we truncate the existing file before unlinking it, any
3757 * process that has it mapped will fail when it tries to touch
3758 * the pages? Probably OK because we use MAP_PRIVATE.
3759 */
3760 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3761 cacheFileName);
3762 if (ftruncate(fd, 0) != 0) {
3763 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3764 cacheFileName, strerror(errno));
3765 /* keep going */
3766 }
3767 if (unlink(cacheFileName) != 0) {
3768 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3769 cacheFileName, errno, strerror(errno));
3770 /* keep going; permission failure should probably be fatal */
3771 }
3772 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3773 flock(fd, LOCK_UN);
3774 close(fd);
3775 goto retry;
3776 } else {
3777 // Got cacheFile! Good to go.
3778 LOGV("Good cache file\n");
3779 }
3780 }
3781
3782 assert(fd >= 0);
3783 return fd;
3784
3785 close_fail:
3786 flock(fd, LOCK_UN);
3787 close(fd);
3788 return -1;
3789 } // End of openCacheFile()
3790
3791 char *genCacheFileName(const char *fileName, const char *subFileName) {
3792 char nameBuf[512];
3793 static const char kCachePath[] = "bcc-cache";
3794 char absoluteFile[sizeof(nameBuf)];
3795 const size_t kBufLen = sizeof(nameBuf) - 1;
3796 const char *dataRoot;
3797 char *cp;
3798
3799 // Get the absolute path of the raw/***.bc file.
3800 absoluteFile[0] = '\0';
3801 if (fileName[0] != '/') {
3802 /*
3803 * Generate the absolute path. This doesn't do everything it
3804 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3805 * the leading "./" out, but it'll do.
3806 */
3807 if (getcwd(absoluteFile, kBufLen) == NULL) {
3808 LOGE("Can't get CWD while opening raw/***.bc file\n");
3809 return NULL;
3810 }
3811 // TODO(srhines): strncat() is a bit dangerous
3812 strncat(absoluteFile, "/", kBufLen);
3813 }
3814 strncat(absoluteFile, fileName, kBufLen);
3815
3816 if (subFileName != NULL) {
3817 strncat(absoluteFile, "/", kBufLen);
3818 strncat(absoluteFile, subFileName, kBufLen);
3819 }
3820
3821 /* Turn the path into a flat filename by replacing
3822 * any slashes after the first one with '@' characters.
3823 */
3824 cp = absoluteFile + 1;
3825 while (*cp != '\0') {
3826 if (*cp == '/') {
3827 *cp = '@';
3828 }
3829 cp++;
3830 }
3831
3832 /* Build the name of the cache directory.
3833 */
3834 dataRoot = getenv("ANDROID_DATA");
3835 if (dataRoot == NULL)
3836 dataRoot = "/data";
3837 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3838
3839 /* Tack on the file name for the actual cache file path.
3840 */
3841 strncat(nameBuf, absoluteFile, kBufLen);
3842
3843 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3844 return strdup(nameBuf);
3845 }
3846
3847 /*
3848 * Read the oBCC header, verify it, then read the dependent section
3849 * and verify that data as well.
3850 *
3851 * On successful return, the file will be seeked immediately past the
3852 * oBCC header.
3853 */
3854 bool checkHeaderAndDependencies(int fd,
3855 uint32_t sourceWhen,
3856 uint32_t rslibWhen,
3857 uint32_t libRSWhen,
3858 uint32_t libbccWhen) {
3859 ssize_t actual;
3860 oBCCHeader optHdr;
3861 uint32_t val;
3862 uint8_t const *magic, *magicVer;
3863
3864 /*
3865 * Start at the start. The "bcc" header, when present, will always be
3866 * the first thing in the file.
3867 */
3868 if (lseek(fd, 0, SEEK_SET) != 0) {
3869 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3870 goto bail;
3871 }
3872
3873 /*
3874 * Read and do trivial verification on the bcc header. The header is
3875 * always in host byte order.
3876 */
3877 actual = read(fd, &optHdr, sizeof(optHdr));
3878 if (actual < 0) {
3879 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3880 goto bail;
3881 } else if (actual != sizeof(optHdr)) {
3882 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3883 (int) actual, sizeof(optHdr));
3884 goto bail;
3885 }
3886
3887 magic = optHdr.magic;
3888 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3889 /* not an oBCC file, or previous attempt was interrupted */
3890 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3891 magic[0], magic[1], magic[2], magic[3]);
3892 goto bail;
3893 }
3894
3895 magicVer = optHdr.magicVersion;
3896 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3897 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3898 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3899 goto bail;
3900 }
3901
3902 /*
3903 * Do the header flags match up with what we want?
3904 *
3905 * This is useful because it allows us to automatically regenerate
3906 * a file when settings change (e.g. verification is now mandatory),
3907 * but can cause difficulties if the thing we depend upon
3908 * were handled differently than the current options specify.
3909 *
3910 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3911 * by limiting the match mask.
3912 *
3913 * The only thing we really can't handle is incorrect byte-ordering.
3914 */
3915
3916 val = optHdr.sourceWhen;
3917 if (val && (val != sourceWhen)) {
3918 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3919 val, sourceWhen);
3920 goto bail;
3921 }
3922 val = optHdr.rslibWhen;
3923 if (val && (val != rslibWhen)) {
3924 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3925 val, rslibWhen);
3926 goto bail;
3927 }
3928 val = optHdr.libRSWhen;
3929 if (val && (val != libRSWhen)) {
3930 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3931 val, libRSWhen);
3932 goto bail;
3933 }
3934 val = optHdr.libbccWhen;
3935 if (val && (val != libbccWhen)) {
3936 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3937 val, libbccWhen);
3938 goto bail;
3939 }
3940
3941 return true;
3942
3943 bail:
3944 return false;
3945 }
3946
Zonr Chang932648d2010-10-13 22:23:56 +08003947};
3948// End of Class Compiler
3949////////////////////////////////////////////////////////////////////////////////
3950
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003951
3952bool Compiler::GlobalInitialized = false;
3953
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08003954char *Compiler::BccCodeAddr = BCC_CODE_ADDR;
Loganad7e8e12010-11-22 20:43:43 +08003955
Zonr Chang932648d2010-10-13 22:23:56 +08003956// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003957llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3958
3959std::string Compiler::Triple;
3960
3961std::string Compiler::CPU;
3962
3963std::vector<std::string> Compiler::Features;
3964
Zonr Chang932648d2010-10-13 22:23:56 +08003965// The named of metadata node that pragma resides (should be synced with
3966// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003967const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3968
Zonr Chang932648d2010-10-13 22:23:56 +08003969// The named of metadata node that export variable name resides (should be
3970// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003971const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3972
Zonr Chang932648d2010-10-13 22:23:56 +08003973// The named of metadata node that export function name resides (should be
3974// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003975const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3976
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003977struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003978 //////////////////////////////////////////////////////////////////////////////
3979 // Part I. Compiler
3980 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003981 Compiler compiler;
3982
Zonr Chang932648d2010-10-13 22:23:56 +08003983 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003984 compiler.registerSymbolCallback(pFn, pContext);
3985 }
3986
Zonr Chang932648d2010-10-13 22:23:56 +08003987 //////////////////////////////////////////////////////////////////////////////
3988 // Part II. Logistics & Error handling
3989 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003990 BCCscript() {
3991 bccError = BCC_NO_ERROR;
3992 }
3993
3994 ~BCCscript() {
3995 }
3996
3997 void setError(BCCenum error) {
3998 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3999 bccError = error;
4000 }
4001 }
4002
4003 BCCenum getError() {
4004 BCCenum result = bccError;
4005 bccError = BCC_NO_ERROR;
4006 return result;
4007 }
4008
4009 BCCenum bccError;
4010};
4011
4012
4013extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004014BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004015 return new BCCscript();
4016}
4017
4018extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004019BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004020 return script->getError();
4021}
4022
4023extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004024void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004025 delete script;
4026}
4027
4028extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004029void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004030 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08004031 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004032 script->registerSymbolCallback(pFn, pContext);
4033}
4034
4035extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004036int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08004037 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004038 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08004039}
4040
4041extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004042int bccReadBC(BCCscript *script,
4043 const BCCchar *bitcode,
4044 BCCint size,
4045 const BCCchar *resName) {
4046 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004047}
4048
4049extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004050void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08004051 const BCCchar *bitcode,
4052 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004053 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08004054}
4055
4056extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004057void bccLoadBinary(BCCscript *script) {
Shih-wei Liaobc5ed672010-11-24 01:53:02 -08004058 int result = script->compiler.loadCacheFile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004059 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004060 script->setError(BCC_INVALID_OPERATION);
4061}
4062
4063extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08004064void bccCompileBC(BCCscript *script) {
4065 {
4066#if defined(__arm__)
4067 android::StopWatch compileTimer("RenderScript compile time");
4068#endif
4069 int result = script->compiler.compile();
4070 if (result)
4071 script->setError(BCC_INVALID_OPERATION);
4072 }
4073}
4074
4075extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004076void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004077 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08004078 BCCsizei *length,
4079 BCCchar *infoLog) {
4080 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004081 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004082 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004083 *length = messageLength;
4084
4085 if (infoLog && maxLength > 0) {
4086 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4087 memcpy(infoLog, message, trimmedLength);
4088 infoLog[trimmedLength] = 0;
4089 }
4090}
4091
4092extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004093void bccGetScriptLabel(BCCscript *script,
4094 const BCCchar *name,
4095 BCCvoid **address) {
4096 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004097 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004098 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004099 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004100 script->setError(BCC_INVALID_VALUE);
4101}
4102
4103extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004104void bccGetExportVars(BCCscript *script,
4105 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004106 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004107 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004108 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4109}
4110
4111extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004112void bccGetExportFuncs(BCCscript *script,
4113 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004114 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004115 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004116 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4117}
4118
4119extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004120void bccGetPragmas(BCCscript *script,
4121 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004122 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004123 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004124 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4125}
4126
4127extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004128void bccGetFunctions(BCCscript *script,
4129 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004130 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004131 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004132 script->compiler.getFunctions(actualFunctionCount,
4133 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004134 functions);
4135}
4136
4137extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004138void bccGetFunctionBinary(BCCscript *script,
4139 BCCchar *function,
4140 BCCvoid **base,
4141 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004142 script->compiler.getFunctionBinary(function, base, length);
4143}
4144
4145struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004146 const Compiler *compiler;
4147 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004148};
4149
Zonr Chang932648d2010-10-13 22:23:56 +08004150} // namespace bcc