blob: ac41041bb05f1cd6a15ff14c218e43bdd5dbcb13 [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 Liao1c6ac2b2010-11-23 00:32:32 -080020// Beginning of mmap region to generate EXE to and to load EXE from disk cache
Shih-wei Liao3d77c422010-11-21 19:51:59 -080021#define BCC_CODE_ADDR 0x7e00000
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080022
Shih-wei Liao1c6ac2b2010-11-23 00:32:32 -080023// Design of caching EXE
24// 1. Each process will have virtual address available starting at 0x7e00000.
25// E.g., Books and Youtube all have its own 0x7e00000. Next, we should
26// minimize the chance of needing to do relocation INSIDE an app too.
27//
28// 2. Each process will have ONE class static variable called BccCodeAddr.
29// I.e., even though the Compiler class will have multiple Compiler objects,
30// e.g, one object for carousel.rs and the other for pageturn.rs,
31// both Compiler objects will share 1 static variable called BccCodeAddr.
32//
33// Key observation: Every app (process) initiates, say 3, scripts (which
34// correspond to 3 Compiler objects) in the same order, usually.
35//
36// So, we should mmap to, e.g., 0x7e00000, 0x7e40000, 0x7e80000 for the 3
37// scripts, respectively. Each time, BccCodeAddr should be updated after
38// JITTing a script. BTW, in ~Compiler(), BccCodeAddr should NOT be
39// decremented back by CodeDataSize. I.e., for 3 scripts: A, B, C,
40// even if it's A -> B -> ~B -> C -> ~C -> B -> C ... no relocation will
41// ever be needed.)
42//
43// If we are lucky, then we don't need relocation ever, since next time the
44// application gets run, the 3 scripts are likely created in the SAME order.
45
Shih-wei Liao77ed6142010-04-07 12:21:42 -070046#define LOG_TAG "bcc"
47#include <cutils/log.h>
48
49#include <ctype.h>
50#include <errno.h>
51#include <limits.h>
52#include <stdarg.h>
53#include <stdint.h>
54#include <stdio.h>
55#include <stdlib.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080056#include <stddef.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070057#include <string.h>
58#include <unistd.h>
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -070059#include <sys/mman.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080060#include <sys/file.h>
61#include <sys/stat.h>
62#include <sys/types.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070063
64#include <cutils/hashmap.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080065#include <utils/StopWatch.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070066
Shih-wei Liao77ed6142010-04-07 12:21:42 -070067#if defined(__arm__)
Zonr Chang932648d2010-10-13 22:23:56 +080068# define DEFAULT_ARM_CODEGEN
69# define PROVIDE_ARM_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070070#elif defined(__i386__)
Zonr Chang932648d2010-10-13 22:23:56 +080071# define DEFAULT_X86_CODEGEN
72# define PROVIDE_X86_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070073#elif defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +080074# define DEFAULT_X64_CODEGEN
75# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070076#endif
77
78#if defined(FORCE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080079# define DEFAULT_ARM_CODEGEN
80# undef DEFAULT_X86_CODEGEN
81# undef DEFAULT_X64_CODEGEN
82# define PROVIDE_ARM_CODEGEN
83# undef PROVIDE_X86_CODEGEN
84# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070085#elif defined(FORCE_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080086# undef DEFAULT_ARM_CODEGEN
87# define DEFAULT_X86_CODEGEN
88# undef DEFAULT_X64_CODEGEN
89# undef PROVIDE_ARM_CODEGEN
90# define PROVIDE_X86_CODEGEN
91# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070092#elif defined(FORCE_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080093# undef DEFAULT_ARM_CODEGEN
94# undef DEFAULT_X86_CODEGEN
95# define DEFAULT_X64_CODEGEN
96# undef PROVIDE_ARM_CODEGEN
97# undef PROVIDE_X86_CODEGEN
98# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070099#endif
100
101#if defined(DEFAULT_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800102# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700103#elif defined(DEFAULT_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800104# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700105#elif defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800106# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700107#endif
108
109#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
Zonr Chang932648d2010-10-13 22:23:56 +0800110# define ARM_USE_VFP
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700111#endif
112
113#include <bcc/bcc.h>
114#include "bcc_runtime.h"
115
Zonr Chang932648d2010-10-13 22:23:56 +0800116#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700117// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
118
Zonr Chang932648d2010-10-13 22:23:56 +0800119#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700120// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
121
122// #define PROVIDE_TRACE_CODEGEN
123
124#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +0800125# include "llvm/MC/MCInst.h"
126# include "llvm/MC/MCAsmInfo.h"
127# include "llvm/MC/MCInstPrinter.h"
128# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700129// If you want the disassemble results written to file, define this:
130# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700131#endif
132
133#include <set>
134#include <map>
135#include <list>
136#include <cmath>
137#include <string>
138#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800139#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700140
Zonr Chang932648d2010-10-13 22:23:56 +0800141// VMCore
142#include "llvm/Use.h"
143#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800144#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800145#include "llvm/Module.h"
146#include "llvm/Function.h"
147#include "llvm/Constant.h"
148#include "llvm/Constants.h"
149#include "llvm/Instruction.h"
150#include "llvm/PassManager.h"
151#include "llvm/LLVMContext.h"
152#include "llvm/GlobalValue.h"
153#include "llvm/Instructions.h"
154#include "llvm/OperandTraits.h"
155#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700156
157// System
Zonr Chang932648d2010-10-13 22:23:56 +0800158#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700159
160// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800161#include "llvm/ADT/APInt.h"
162#include "llvm/ADT/APFloat.h"
163#include "llvm/ADT/DenseMap.h"
164#include "llvm/ADT/ValueMap.h"
165#include "llvm/ADT/StringMap.h"
166#include "llvm/ADT/OwningPtr.h"
167#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700168
169// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800170#include "llvm/Target/TargetData.h"
171#include "llvm/Target/TargetSelect.h"
172#include "llvm/Target/TargetOptions.h"
173#include "llvm/Target/TargetMachine.h"
174#include "llvm/Target/TargetJITInfo.h"
175#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700176#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700177
178// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800179#include "llvm/Support/Casting.h"
180#include "llvm/Support/raw_ostream.h"
181#include "llvm/Support/ValueHandle.h"
182#include "llvm/Support/MemoryBuffer.h"
183#include "llvm/Support/MemoryObject.h"
184#include "llvm/Support/ManagedStatic.h"
185#include "llvm/Support/ErrorHandling.h"
186#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700187#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700188
189// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800190#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700191
192// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800193#include "llvm/CodeGen/Passes.h"
194#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700195#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700196#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700197#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700198#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700199#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700200#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700201#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700202#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700203
204// ExecutionEngine
205#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700206#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700207
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700208extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700209
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800210// For caching
211struct oBCCHeader {
212 uint8_t magic[4]; // includes version number
213 uint8_t magicVersion[4];
214
215 uint32_t sourceWhen;
216 uint32_t rslibWhen;
217 uint32_t libRSWhen;
218 uint32_t libbccWhen;
219
220 uint32_t cachedCodeDataAddr;
221 uint32_t rootAddr;
222 uint32_t initAddr;
223
224 uint32_t relocOffset; // offset of reloc table.
225 uint32_t relocCount;
226 uint32_t exportVarsOffset; // offset of export var table
227 uint32_t exportVarsCount;
228 uint32_t exportFuncsOffset; // offset of export func table
229 uint32_t exportFuncsCount;
230 uint32_t exportPragmasOffset; // offset of export pragma table
231 uint32_t exportPragmasCount;
232
233 uint32_t codeOffset; // offset of code: 64-bit alignment
234 uint32_t codeSize;
235 uint32_t dataOffset; // offset of data section
236 uint32_t dataSize;
237
238 // uint32_t flags; // some info flags
239 uint32_t checksum; // adler32 checksum covering deps/opt
240};
241
Logan824dd0a2010-11-20 01:45:54 +0800242struct oBCCRelocEntry {
243 uint32_t relocType; // target instruction relocation type
244 uint32_t relocOffset; // offset of hole (holeAddr - codeAddr)
245 uint32_t cachedResultAddr; // address resolved at compile time
246
Logan634bd832010-11-20 09:00:36 +0800247 oBCCRelocEntry(uint32_t ty, uintptr_t off, void *addr)
Logan824dd0a2010-11-20 01:45:54 +0800248 : relocType(ty),
249 relocOffset(static_cast<uint32_t>(off)),
250 cachedResultAddr(reinterpret_cast<uint32_t>(addr)) {
251 }
252};
253
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800254/* oBCCHeader Offset Table */
255#define k_magic offsetof(oBCCHeader, magic)
256#define k_magicVersion offsetof(oBCCHeader, magicVersion)
257#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
258#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
259#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
260#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
261#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
262#define k_rootAddr offsetof(oBCCHeader, rootAddr)
263#define k_initAddr offsetof(oBCCHeader, initAddr)
264#define k_relocOffset offsetof(oBCCHeader, relocOffset)
265#define k_relocCount offsetof(oBCCHeader, relocCount)
266#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
267#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
268#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
269#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
270#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
271#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
272#define k_codeOffset offsetof(oBCCHeader, codeOffset)
273#define k_codeSize offsetof(oBCCHeader, codeSize)
274#define k_dataOffset offsetof(oBCCHeader, dataOffset)
275#define k_dataSize offsetof(oBCCHeader, dataSize)
276#define k_checksum offsetof(oBCCHeader, checksum)
277
278/* oBCC file magic number */
279#define OBCC_MAGIC "bcc\n"
280/* version, encoded in 4 bytes of ASCII */
281#define OBCC_MAGIC_VERS "001\0"
282
283#define TEMP_FAILURE_RETRY1(exp) ({ \
284 typeof (exp) _rc; \
285 do { \
286 _rc = (exp); \
287 } while (_rc == -1 && errno == EINTR); \
288 _rc; })
289
290static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
291{
292 while (count != 0) {
293 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
294 if (actual < 0) {
295 int err = errno;
296 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
297 return err;
298 } else if (actual != (ssize_t) count) {
299 LOGD("%s: partial write (will retry): (%d of %zd)\n",
300 logMsg, (int) actual, count);
301 buf = (const void*) (((const uint8_t*) buf) + actual);
302 }
303 count -= actual;
304 }
305
306 return 0;
307}
308
Zonr Chang932648d2010-10-13 22:23:56 +0800309//
310// Compilation class that suits Android's needs.
311// (Support: no argument passed, ...)
312//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700313namespace bcc {
314
315class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800316 // This part is designed to be orthogonal to those exported bcc*() functions
317 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700318
Zonr Chang932648d2010-10-13 22:23:56 +0800319 //////////////////////////////////////////////////////////////////////////////
320 // The variable section below (e.g., Triple, CodeGenOptLevel)
321 // is initialized in GlobalInitialization()
322 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700323 static bool GlobalInitialized;
Loganad7e8e12010-11-22 20:43:43 +0800324 static bool BccCodeAddrTaken;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700325
Zonr Chang932648d2010-10-13 22:23:56 +0800326 // If given, this will be the name of the target triple to compile for.
327 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700328 static std::string Triple;
329
330 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700331
Zonr Chang932648d2010-10-13 22:23:56 +0800332 // End of section of GlobalInitializing variables
333 //////////////////////////////////////////////////////////////////////////////
334
335 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700336 static std::string CPU;
337
Zonr Chang932648d2010-10-13 22:23:56 +0800338 // The list of target specific features to enable or disable -- this should
339 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700340 static std::vector<std::string> Features;
341
342 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800343 const char *mName;
344 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700345 };
346 static struct Runtime Runtimes[];
347
348 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800349 if (GlobalInitialized)
350 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700351
Zonr Chang932648d2010-10-13 22:23:56 +0800352 // if (!llvm::llvm_is_multithreaded())
353 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700354
Zonr Chang932648d2010-10-13 22:23:56 +0800355 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700356 Triple = TARGET_TRIPLE_STRING;
357
Zonr Chang932648d2010-10-13 22:23:56 +0800358 // TODO(zonr): NEON for JIT
359 // Features.push_back("+neon");
360 // Features.push_back("+vmlx");
361 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700362 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700363 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700364
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700365#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
366 LLVMInitializeARMTargetInfo();
367 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700368#if defined(USE_DISASSEMBLER)
369 LLVMInitializeARMDisassembler();
370 LLVMInitializeARMAsmPrinter();
371#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700372#endif
373
374#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
375 LLVMInitializeX86TargetInfo();
376 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700377#if defined(USE_DISASSEMBLER)
378 LLVMInitializeX86Disassembler();
379 LLVMInitializeX86AsmPrinter();
380#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700381#endif
382
383#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
384 LLVMInitializeX86TargetInfo();
385 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700386#if defined(USE_DISASSEMBLER)
387 LLVMInitializeX86Disassembler();
388 LLVMInitializeX86AsmPrinter();
389#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700390#endif
391
Zonr Chang932648d2010-10-13 22:23:56 +0800392 // -O0: llvm::CodeGenOpt::None
393 // -O1: llvm::CodeGenOpt::Less
394 // -O2: llvm::CodeGenOpt::Default
395 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700396 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700397
Zonr Chang932648d2010-10-13 22:23:56 +0800398 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700399
Zonr Chang932648d2010-10-13 22:23:56 +0800400 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700401 llvm::NoFramePointerElim = false;
402
Zonr Chang932648d2010-10-13 22:23:56 +0800403 // Use hardfloat ABI
404 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800405 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800406 // softfp. To use softfp, change following 2 lines to
407 //
408 // llvm::FloatABIType = llvm::FloatABI::Soft;
409 // llvm::UseSoftFloat = true;
410 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700411 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700412 llvm::UseSoftFloat = false;
413
Zonr Chang932648d2010-10-13 22:23:56 +0800414 // BCC needs all unknown symbols resolved at JIT/compilation time.
415 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700416 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
417
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700418#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800419 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700420 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
421#else
Zonr Chang932648d2010-10-13 22:23:56 +0800422 // This is set for the linker (specify how large of the virtual addresses
423 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700424 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
425#endif
426
Zonr Chang932648d2010-10-13 22:23:56 +0800427 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700428 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
429
Zonr Chang932648d2010-10-13 22:23:56 +0800430 // Register allocation policy:
431 // createFastRegisterAllocator: fast but bad quality
432 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700433 llvm::RegisterRegAlloc::setDefault
434 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700435 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700436 llvm::createLinearScanRegisterAllocator);
437
438 GlobalInitialized = true;
439 return;
440 }
441
442 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800443 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700444 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700445 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800446 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700447 }
448
449 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700450 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700451 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700452
453 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700454 std::string mError;
455
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700456 inline bool hasError() const {
457 return !mError.empty();
458 }
Zonr Chang932648d2010-10-13 22:23:56 +0800459 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700460 mError.assign(Error); // Copying
461 return;
462 }
Zonr Chang932648d2010-10-13 22:23:56 +0800463 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700464 mError = Error;
465 return;
466 }
467
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800468 bool mNeverCache; // Set by readBC()
469 bool mCacheNew; // Set by readBC()
470 int mCacheFd; // Set by readBC()
471 char *mCacheMapAddr; // Set by loader() if mCacheNew is false
472 oBCCHeader *mCacheHdr; // Set by loader()
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800473 size_t mCacheSize; // Set by loader()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800474 ptrdiff_t mCacheDiff; // Set by loader()
475 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
476 // Used by genCacheFile() for dumping
477
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700478 typedef std::list< std::pair<std::string, std::string> > PragmaList;
479 PragmaList mPragmas;
480
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700481 typedef std::list<void*> ExportVarList;
482 ExportVarList mExportVars;
483
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700484 typedef std::list<void*> ExportFuncList;
485 ExportFuncList mExportFuncs;
486
Zonr Chang932648d2010-10-13 22:23:56 +0800487 //////////////////////////////////////////////////////////////////////////////
488 // Memory manager for the code reside in memory
489 //
490 // The memory for our code emitter is very simple and is conforming to the
491 // design decisions of Android RenderScript's Exection Environment:
492 // The code, data, and symbol sizes are limited (currently 100KB.)
493 //
494 // It's very different from typical compiler, which has no limitation
495 // on the code size. How does code emitter know the size of the code
496 // it is about to emit? It does not know beforehand. We want to solve
497 // this without complicating the code emitter too much.
498 //
499 // We solve this by pre-allocating a certain amount of memory,
500 // and then start the code emission. Once the buffer overflows, the emitter
501 // simply discards all the subsequent emission but still has a counter
502 // on how many bytes have been emitted.
503 //
504 // So once the whole emission is done, if there's a buffer overflow,
505 // it re-allocates the buffer with enough size (based on the
506 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800507
508 // 128 KiB for code
509 static const unsigned int MaxCodeSize = 128 * 1024;
510 // 1 KiB for global offset table (GOT)
511 static const unsigned int MaxGOTSize = 1 * 1024;
512 // 128 KiB for global variable
513 static const unsigned int MaxGlobalVarSize = 128 * 1024;
514
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700515 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700516 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800517 //
518 // Our memory layout is as follows:
519 //
520 // The direction of arrows (-> and <-) shows memory's growth direction
521 // when more space is needed.
522 //
523 // @mpCodeMem:
524 // +--------------------------------------------------------------+
525 // | Function Memory ... -> <- ... Stub/GOT |
526 // +--------------------------------------------------------------+
527 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
528 //
529 // Where size of GOT is @MaxGOTSize KiB.
530 //
531 // @mpGVMem:
532 // +--------------------------------------------------------------+
533 // | Global variable ... -> |
534 // +--------------------------------------------------------------+
535 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
536 //
537 //
538 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
539 // of function code's memory usage
540 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
541 // of stub/GOT's memory usage
542 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
543 // of global variable's memory usage
544 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700545 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700546 uintptr_t mCurSGMemIdx;
547 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800548 void *mpCodeMem;
549 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700550
Zonr Chang932648d2010-10-13 22:23:56 +0800551 // GOT Base
552 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700553
554 typedef std::map<const llvm::Function*, pair<void* /* start address */,
555 void* /* end address */>
556 > FunctionMapTy;
557 FunctionMapTy mFunctionMap;
558
Zonr Chang932648d2010-10-13 22:23:56 +0800559 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700560 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700561 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700562
Zonr Chang932648d2010-10-13 22:23:56 +0800563 uint8_t *allocateSGMemory(uintptr_t Size,
564 unsigned Alignment = 1 /* no alignment */) {
565 intptr_t FreeMemSize = getFreeCodeMemSize();
566 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
567 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700568 return NULL;
569
Zonr Chang932648d2010-10-13 22:23:56 +0800570 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700571 Alignment = 1;
572
Zonr Chang932648d2010-10-13 22:23:56 +0800573 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700574 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
575
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700576 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700577
578 return result;
579 }
580
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700581 inline uintptr_t getFreeGVMemSize() const {
582 return MaxGlobalVarSize - mCurGVMemIdx;
583 }
Zonr Chang932648d2010-10-13 22:23:56 +0800584 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700585 return reinterpret_cast<uint8_t*>(mpGVMem);
586 }
587
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700588 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700589 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700590 reset();
591 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700592
Loganad7e8e12010-11-22 20:43:43 +0800593 if (!Compiler::BccCodeAddrTaken) { // Try to use BCC_CODE_ADDR
594 mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
595 MaxCodeSize + MaxGlobalVarSize,
596 PROT_READ | PROT_EXEC | PROT_WRITE,
597 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
598 -1, 0);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800599
Loganad7e8e12010-11-22 20:43:43 +0800600 if (mpCodeMem == MAP_FAILED) {
601 LOGE("Mmap mpCodeMem at %p failed with reason: %s.\n",
602 reinterpret_cast<void *>(BCC_CODE_ADDR), strerror(errno));
603 LOGE("Retry to mmap mpCodeMem at arbitary address\n");
604 }
605 }
606
607 if (Compiler::BccCodeAddrTaken || mpCodeMem == MAP_FAILED) {
608 // If BCC_CODE_ADDR has been occuppied, or we can't allocate
609 // mpCodeMem in previous mmap, then allocate them in arbitary
610 // location.
611
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800612 mpCodeMem = mmap(NULL,
613 MaxCodeSize + MaxGlobalVarSize,
614 PROT_READ | PROT_EXEC | PROT_WRITE,
615 MAP_PRIVATE | MAP_ANON,
Loganad7e8e12010-11-22 20:43:43 +0800616 -1, 0);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800617
Loganad7e8e12010-11-22 20:43:43 +0800618 if (mpCodeMem == MAP_FAILED) {
619 LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
620 llvm::report_fatal_error("Failed to allocate memory for emitting "
621 "codes\n" + ErrMsg);
622 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800623 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800624
Loganad7e8e12010-11-22 20:43:43 +0800625 // One instance of script is occupping BCC_CODE_ADDR
626 Compiler::BccCodeAddrTaken = true;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700627
Loganad7e8e12010-11-22 20:43:43 +0800628 // Set global variable pool
629 mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
630
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700631 return;
632 }
633
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800634 inline uint8_t *getCodeMemBase() const {
635 return reinterpret_cast<uint8_t*>(mpCodeMem);
636 }
637
Zonr Chang932648d2010-10-13 22:23:56 +0800638 // setMemoryWritable - When code generation is in progress, the code pages
639 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700640 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700641 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700642 return;
643 }
644
Zonr Chang932648d2010-10-13 22:23:56 +0800645 // When code generation is done and we're ready to start execution, the
646 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700647 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700648 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700649 return;
650 }
651
Zonr Chang932648d2010-10-13 22:23:56 +0800652 // Setting this flag to true makes the memory manager garbage values over
653 // freed memory. This is useful for testing and debugging, and is to be
654 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700655 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800656 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700657 return;
658 }
659
Zonr Chang932648d2010-10-13 22:23:56 +0800660 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700661
Zonr Chang932648d2010-10-13 22:23:56 +0800662 // If the current table requires a Global Offset Table, this method is
663 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700664 void AllocateGOT() {
665 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700666 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700667 HasGOT = true;
668 return;
669 }
670
Zonr Chang932648d2010-10-13 22:23:56 +0800671 // If this is managing a Global Offset Table, this method should return a
672 // pointer to its base.
673 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700674 return mpGOTBase;
675 }
676
Zonr Chang932648d2010-10-13 22:23:56 +0800677 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700678
Zonr Chang932648d2010-10-13 22:23:56 +0800679 // When we start JITing a function, the JIT calls this method to allocate a
680 // block of free RWX memory, which returns a pointer to it. If the JIT wants
681 // to request a block of memory of at least a certain size, it passes that
682 // value as ActualSize, and this method returns a block with at least that
683 // much space. If the JIT doesn't know ahead of time how much space it will
684 // need to emit the function, it passes 0 for the ActualSize. In either
685 // case, this method is required to pass back the size of the allocated
686 // block through ActualSize. The JIT will be careful to not write more than
687 // the returned ActualSize bytes of memory.
688 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
689 intptr_t FreeMemSize = getFreeCodeMemSize();
690 if ((FreeMemSize < 0) ||
691 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
692 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700693 return NULL;
694
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700695 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700696 return (getCodeMemBase() + mCurFuncMemIdx);
697 }
698
Zonr Chang932648d2010-10-13 22:23:56 +0800699 // This method is called by the JIT to allocate space for a function stub
700 // (used to handle limited branch displacements) while it is JIT compiling a
701 // function. For example, if foo calls bar, and if bar either needs to be
702 // lazily compiled or is a native function that exists too far away from the
703 // call site to work, this method will be used to make a thunk for it. The
704 // stub should be "close" to the current function body, but should not be
705 // included in the 'actualsize' returned by startFunctionBody.
706 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700707 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700708 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700709 }
710
Zonr Chang932648d2010-10-13 22:23:56 +0800711 // This method is called when the JIT is done codegen'ing the specified
712 // function. At this point we know the size of the JIT compiled function.
713 // This passes in FunctionStart (which was returned by the startFunctionBody
714 // method) and FunctionEnd which is a pointer to the actual end of the
715 // function. This method should mark the space allocated and remember where
716 // it is in case the client wants to deallocate it.
717 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
718 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700719 assert(FunctionEnd > FunctionStart);
720 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
721 "Mismatched function start/end!");
722
Zonr Chang932648d2010-10-13 22:23:56 +0800723 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700724 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700725 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700726 "Code size excess the limitation!");
727 mCurFuncMemIdx += FunctionCodeSize;
728
Zonr Chang932648d2010-10-13 22:23:56 +0800729 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700730 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
731 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800732 mFunctionMap.insert(
733 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
734 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700735
736 return;
737 }
738
Zonr Chang932648d2010-10-13 22:23:56 +0800739 // Allocate a (function code) memory block of the given size. This method
740 // cannot be called between calls to startFunctionBody and endFunctionBody.
741 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
742 if (getFreeCodeMemSize() < Size)
743 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700744 return NULL;
745
Zonr Chang932648d2010-10-13 22:23:56 +0800746 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700747 Alignment = 1;
748
Zonr Chang932648d2010-10-13 22:23:56 +0800749 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700750 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800751 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700752
753 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
754
755 return result;
756 }
757
Zonr Chang932648d2010-10-13 22:23:56 +0800758 // Allocate memory for a global variable.
759 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700760 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800761 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700762 LOGE("No Global Memory");
763 return NULL;
764 }
765
Zonr Chang932648d2010-10-13 22:23:56 +0800766 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700767 Alignment = 1;
768
Zonr Chang932648d2010-10-13 22:23:56 +0800769 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700770 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800771 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700772
773 mCurGVMemIdx = (result + Size) - getGVMemBase();
774
775 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700776 }
777
Zonr Chang932648d2010-10-13 22:23:56 +0800778 // Free the specified function body. The argument must be the return value
779 // from a call to startFunctionBody() that hasn't been deallocated yet. This
780 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700781 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800782 // linear search
783 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
784 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
785 E = mFunctionMap.end();
786 I != E;
787 I++)
788 if (I->second.first == Body) {
789 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
790 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700791 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800792 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700793
Zonr Chang932648d2010-10-13 22:23:56 +0800794 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700795
Zonr Chang932648d2010-10-13 22:23:56 +0800796 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700797 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
798
799 assert(SizeNeedMove >= 0 &&
800 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
801 " be correctly calculated!");
802
Zonr Chang932648d2010-10-13 22:23:56 +0800803 if (SizeNeedMove > 0)
804 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700805 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
806 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
807
808 return;
809 }
810
Zonr Chang932648d2010-10-13 22:23:56 +0800811 // When we finished JITing the function, if exception handling is set, we
812 // emit the exception table.
813 uint8_t *startExceptionTable(const llvm::Function *F,
814 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700815 assert(false && "Exception is not allowed in our language specification");
816 return NULL;
817 }
818
Zonr Chang932648d2010-10-13 22:23:56 +0800819 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700820 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800821 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700822 assert(false && "Exception is not allowed in our language specification");
823 return;
824 }
825
Zonr Chang932648d2010-10-13 22:23:56 +0800826 // Free the specified exception table's memory. The argument must be the
827 // return value from a call to startExceptionTable() that hasn't been
828 // deallocated yet. This is never called when the JIT is currently emitting
829 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700830 void deallocateExceptionTable(void *ET) {
831 assert(false && "Exception is not allowed in our language specification");
832 return;
833 }
834
Zonr Chang932648d2010-10-13 22:23:56 +0800835 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700836 void reset() {
837 mpGOTBase = NULL;
838 HasGOT = false;
839
840 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700841 mCurSGMemIdx = MaxCodeSize - 1;
842 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700843
844 mFunctionMap.clear();
845
846 return;
847 }
848
849 ~CodeMemoryManager() {
Loganad7e8e12010-11-22 20:43:43 +0800850 if (mpCodeMem != NULL && mpCodeMem != MAP_FAILED)
851 munmap(mpCodeMem, MaxCodeSize + MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700852 return;
853 }
Zonr Chang932648d2010-10-13 22:23:56 +0800854 };
855 // End of class CodeMemoryManager
856 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700857
Zonr Chang932648d2010-10-13 22:23:56 +0800858 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700859 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800860 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700861 mCodeMemMgr.reset(new CodeMemoryManager());
862 return mCodeMemMgr.get();
863 }
864
Zonr Chang932648d2010-10-13 22:23:56 +0800865 //////////////////////////////////////////////////////////////////////////////
866 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700867 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700868 public:
869 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
870 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
871
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800872 GlobalAddressMapTy mGlobalAddressMap;
873
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700874 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800875 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700876
Zonr Chang932648d2010-10-13 22:23:56 +0800877 // The JITInfo for the target we are compiling to
878 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700879
Zonr Chang932648d2010-10-13 22:23:56 +0800880 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700881
Zonr Chang932648d2010-10-13 22:23:56 +0800882 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700883
884 class EmittedFunctionCode {
885 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800886 // Beginning of the function's allocation.
887 void *FunctionBody;
888
889 // The address the function's code actually starts at.
890 void *Code;
891
892 // The size of the function code
893 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700894
895 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
896 };
Zonr Chang932648d2010-10-13 22:23:56 +0800897 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700898
Zonr Chang932648d2010-10-13 22:23:56 +0800899 typedef std::map<const std::string,
900 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700901 EmittedFunctionsMapTy mEmittedFunctions;
902
Zonr Chang932648d2010-10-13 22:23:56 +0800903 // This vector is a mapping from MBB ID's to their address. It is filled in
904 // by the StartMachineBasicBlock callback and queried by the
905 // getMachineBasicBlockAddress callback.
906 std::vector<uintptr_t> mMBBLocations;
907
908 // The constant pool for the current function.
909 llvm::MachineConstantPool *mpConstantPool;
910
911 // A pointer to the first entry in the constant pool.
912 void *mpConstantPoolBase;
913
914 // Addresses of individual constant pool entries.
915 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
916
917 // The jump tables for the current function.
918 llvm::MachineJumpTableInfo *mpJumpTable;
919
920 // A pointer to the first entry in the jump table.
921 void *mpJumpTableBase;
922
923 // When outputting a function stub in the context of some other function, we
924 // save BufferBegin/BufferEnd/CurBufferPtr here.
925 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
926
927 // These are the relocations that the function needs, as emitted.
928 std::vector<llvm::MachineRelocation> mRelocations;
929
Logan824dd0a2010-11-20 01:45:54 +0800930 std::vector<oBCCRelocEntry> mCachingRelocations;
931
Zonr Chang932648d2010-10-13 22:23:56 +0800932 // This vector is a mapping from Label ID's to their address.
933 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
934
935 // Machine module info for exception informations
936 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700937
Zonr Chang932648d2010-10-13 22:23:56 +0800938 // Replace an existing mapping for GV with a new address. This updates both
939 // maps as required. If Addr is null, the entry for the global is removed
940 // from the mappings.
941 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
942 if (Addr == NULL) {
943 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700944 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
945 void *OldVal;
946
Zonr Chang932648d2010-10-13 22:23:56 +0800947 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700948 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800949 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700950 OldVal = I->second;
951 mGlobalAddressMap.erase(I);
952 }
953
954 return OldVal;
955 }
956
Zonr Chang932648d2010-10-13 22:23:56 +0800957 void *&CurVal = mGlobalAddressMap[GV];
958 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700959
960 CurVal = Addr;
961
962 return OldVal;
963 }
964
Zonr Chang932648d2010-10-13 22:23:56 +0800965 // Tell the execution engine that the specified global is at the specified
966 // location. This is used internally as functions are JIT'd and as global
967 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700968 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800969 void *&CurVal = mGlobalAddressMap[GV];
970 assert((CurVal == 0 || Addr == 0) &&
971 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700972 CurVal = Addr;
973 return;
974 }
975
Zonr Chang932648d2010-10-13 22:23:56 +0800976 // This returns the address of the specified global value if it is has
977 // already been codegen'd, otherwise it returns null.
978 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700979 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700980 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
981 }
982
Zonr Chang932648d2010-10-13 22:23:56 +0800983 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
984 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700985 MCP->getConstants();
986
Zonr Chang932648d2010-10-13 22:23:56 +0800987 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700988 return 0;
989
990 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800991 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700992 llvm::MachineConstantPoolEntry CPE = Constants[i];
993 unsigned int AlignMask = CPE.getAlignment() - 1;
994 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800995 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700996 Size += mpTD->getTypeAllocSize(Ty);
997 }
998
999 return Size;
1000 }
1001
Zonr Chang932648d2010-10-13 22:23:56 +08001002 // This function converts a Constant* into a GenericValue. The interesting
1003 // part is if C is a ConstantExpr.
1004 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
1005 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001006 return;
Zonr Chang932648d2010-10-13 22:23:56 +08001007 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
1008 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
1009 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001010
Zonr Chang932648d2010-10-13 22:23:56 +08001011 switch (CE->getOpcode()) {
1012 case llvm::Instruction::GetElementPtr: {
1013 // Compute the index
1014 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
1015 CE->op_end());
1016 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
1017 &Indices[0],
1018 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001019
Zonr Chang932648d2010-10-13 22:23:56 +08001020 GetConstantValue(Op0, Result);
1021 Result.PointerVal =
1022 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001023
Zonr Chang932648d2010-10-13 22:23:56 +08001024 return;
1025 }
1026 case llvm::Instruction::Trunc: {
1027 uint32_t BitWidth =
1028 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1029
1030 GetConstantValue(Op0, Result);
1031 Result.IntVal = Result.IntVal.trunc(BitWidth);
1032
1033 return;
1034 }
1035 case llvm::Instruction::ZExt: {
1036 uint32_t BitWidth =
1037 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1038
1039 GetConstantValue(Op0, Result);
1040 Result.IntVal = Result.IntVal.zext(BitWidth);
1041
1042 return;
1043 }
1044 case llvm::Instruction::SExt: {
1045 uint32_t BitWidth =
1046 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1047
1048 GetConstantValue(Op0, Result);
1049 Result.IntVal = Result.IntVal.sext(BitWidth);
1050
1051 return;
1052 }
1053 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001054 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001055 GetConstantValue(Op0, Result);
1056 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1057 return;
1058 }
1059 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001060 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001061 GetConstantValue(Op0, Result);
1062 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1063 return;
1064 }
1065 case llvm::Instruction::UIToFP: {
1066 GetConstantValue(Op0, Result);
1067 if (CE->getType()->isFloatTy())
1068 Result.FloatVal =
1069 static_cast<float>(Result.IntVal.roundToDouble());
1070 else if (CE->getType()->isDoubleTy())
1071 Result.DoubleVal = Result.IntVal.roundToDouble();
1072 else if (CE->getType()->isX86_FP80Ty()) {
1073 const uint64_t zero[] = { 0, 0 };
1074 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1075 apf.convertFromAPInt(Result.IntVal,
1076 false,
1077 llvm::APFloat::rmNearestTiesToEven);
1078 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001079 }
Zonr Chang932648d2010-10-13 22:23:56 +08001080 return;
1081 }
1082 case llvm::Instruction::SIToFP: {
1083 GetConstantValue(Op0, Result);
1084 if (CE->getType()->isFloatTy())
1085 Result.FloatVal =
1086 static_cast<float>(Result.IntVal.signedRoundToDouble());
1087 else if (CE->getType()->isDoubleTy())
1088 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1089 else if (CE->getType()->isX86_FP80Ty()) {
1090 const uint64_t zero[] = { 0, 0 };
1091 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1092 apf.convertFromAPInt(Result.IntVal,
1093 true,
1094 llvm::APFloat::rmNearestTiesToEven);
1095 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001096 }
Zonr Chang932648d2010-10-13 22:23:56 +08001097 return;
1098 }
1099 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001100 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001101 case llvm::Instruction::FPToSI: {
1102 uint32_t BitWidth =
1103 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001104
Zonr Chang932648d2010-10-13 22:23:56 +08001105 GetConstantValue(Op0, Result);
1106 if (Op0->getType()->isFloatTy())
1107 Result.IntVal =
1108 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1109 else if (Op0->getType()->isDoubleTy())
1110 Result.IntVal =
1111 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1112 BitWidth);
1113 else if (Op0->getType()->isX86_FP80Ty()) {
1114 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1115 uint64_t V;
1116 bool Ignored;
1117 apf.convertToInteger(&V,
1118 BitWidth,
1119 CE->getOpcode() == llvm::Instruction::FPToSI,
1120 llvm::APFloat::rmTowardZero,
1121 &Ignored);
1122 Result.IntVal = V; // endian?
1123 }
1124 return;
1125 }
1126 case llvm::Instruction::PtrToInt: {
1127 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1128
1129 GetConstantValue(Op0, Result);
1130 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1131 (Result.PointerVal));
1132
1133 return;
1134 }
1135 case llvm::Instruction::IntToPtr: {
1136 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1137
1138 GetConstantValue(Op0, Result);
1139 if (PtrWidth != Result.IntVal.getBitWidth())
1140 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1141 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1142
1143 Result.PointerVal =
1144 llvm::PointerTy(
1145 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1146
1147 return;
1148 }
1149 case llvm::Instruction::BitCast: {
1150 GetConstantValue(Op0, Result);
1151 const llvm::Type *DestTy = CE->getType();
1152
1153 switch (Op0->getType()->getTypeID()) {
1154 case llvm::Type::IntegerTyID: {
1155 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1156 if (DestTy->isFloatTy())
1157 Result.FloatVal = Result.IntVal.bitsToFloat();
1158 else if (DestTy->isDoubleTy())
1159 Result.DoubleVal = Result.IntVal.bitsToDouble();
1160 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001161 }
Zonr Chang932648d2010-10-13 22:23:56 +08001162 case llvm::Type::FloatTyID: {
1163 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1164 Result.IntVal.floatToBits(Result.FloatVal);
1165 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001166 }
Zonr Chang932648d2010-10-13 22:23:56 +08001167 case llvm::Type::DoubleTyID: {
1168 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1169 Result.IntVal.doubleToBits(Result.DoubleVal);
1170 break;
1171 }
1172 case llvm::Type::PointerTyID: {
1173 assert(DestTy->isPointerTy() && "Invalid bitcast");
1174 break; // getConstantValue(Op0) above already converted it
1175 }
1176 default: {
1177 llvm_unreachable("Invalid bitcast operand");
1178 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001179 }
Zonr Chang932648d2010-10-13 22:23:56 +08001180 return;
1181 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001182 case llvm::Instruction::Add:
1183 case llvm::Instruction::FAdd:
1184 case llvm::Instruction::Sub:
1185 case llvm::Instruction::FSub:
1186 case llvm::Instruction::Mul:
1187 case llvm::Instruction::FMul:
1188 case llvm::Instruction::UDiv:
1189 case llvm::Instruction::SDiv:
1190 case llvm::Instruction::URem:
1191 case llvm::Instruction::SRem:
1192 case llvm::Instruction::And:
1193 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001194 case llvm::Instruction::Xor: {
1195 llvm::GenericValue LHS, RHS;
1196 GetConstantValue(Op0, LHS);
1197 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001198
Zonr Chang932648d2010-10-13 22:23:56 +08001199 switch (Op0->getType()->getTypeID()) {
1200 case llvm::Type::IntegerTyID: {
1201 switch (CE->getOpcode()) {
1202 case llvm::Instruction::Add: {
1203 Result.IntVal = LHS.IntVal + RHS.IntVal;
1204 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001205 }
Zonr Chang932648d2010-10-13 22:23:56 +08001206 case llvm::Instruction::Sub: {
1207 Result.IntVal = LHS.IntVal - RHS.IntVal;
1208 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001209 }
Zonr Chang932648d2010-10-13 22:23:56 +08001210 case llvm::Instruction::Mul: {
1211 Result.IntVal = LHS.IntVal * RHS.IntVal;
1212 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001213 }
Zonr Chang932648d2010-10-13 22:23:56 +08001214 case llvm::Instruction::UDiv: {
1215 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1216 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001217 }
Zonr Chang932648d2010-10-13 22:23:56 +08001218 case llvm::Instruction::SDiv: {
1219 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1220 break;
1221 }
1222 case llvm::Instruction::URem: {
1223 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1224 break;
1225 }
1226 case llvm::Instruction::SRem: {
1227 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1228 break;
1229 }
1230 case llvm::Instruction::And: {
1231 Result.IntVal = LHS.IntVal & RHS.IntVal;
1232 break;
1233 }
1234 case llvm::Instruction::Or: {
1235 Result.IntVal = LHS.IntVal | RHS.IntVal;
1236 break;
1237 }
1238 case llvm::Instruction::Xor: {
1239 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1240 break;
1241 }
1242 default: {
1243 llvm_unreachable("Invalid integer opcode");
1244 }
1245 }
1246 break;
1247 }
1248 case llvm::Type::FloatTyID: {
1249 switch (CE->getOpcode()) {
1250 case llvm::Instruction::FAdd: {
1251 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1252 break;
1253 }
1254 case llvm::Instruction::FSub: {
1255 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1256 break;
1257 }
1258 case llvm::Instruction::FMul: {
1259 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1260 break;
1261 }
1262 case llvm::Instruction::FDiv: {
1263 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1264 break;
1265 }
1266 case llvm::Instruction::FRem: {
1267 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1268 break;
1269 }
1270 default: {
1271 llvm_unreachable("Invalid float opcode");
1272 }
1273 }
1274 break;
1275 }
1276 case llvm::Type::DoubleTyID: {
1277 switch (CE->getOpcode()) {
1278 case llvm::Instruction::FAdd: {
1279 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1280 break;
1281 }
1282 case llvm::Instruction::FSub: {
1283 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1284 break;
1285 }
1286 case llvm::Instruction::FMul: {
1287 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1288 break;
1289 }
1290 case llvm::Instruction::FDiv: {
1291 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1292 break;
1293 }
1294 case llvm::Instruction::FRem: {
1295 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1296 break;
1297 }
1298 default: {
1299 llvm_unreachable("Invalid double opcode");
1300 }
1301 }
1302 break;
1303 }
1304 case llvm::Type::X86_FP80TyID:
1305 case llvm::Type::PPC_FP128TyID:
1306 case llvm::Type::FP128TyID: {
1307 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1308 switch (CE->getOpcode()) {
1309 case llvm::Instruction::FAdd: {
1310 apfLHS.add(llvm::APFloat(RHS.IntVal),
1311 llvm::APFloat::rmNearestTiesToEven);
1312 break;
1313 }
1314 case llvm::Instruction::FSub: {
1315 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1316 llvm::APFloat::rmNearestTiesToEven);
1317 break;
1318 }
1319 case llvm::Instruction::FMul: {
1320 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1321 llvm::APFloat::rmNearestTiesToEven);
1322 break;
1323 }
1324 case llvm::Instruction::FDiv: {
1325 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1326 llvm::APFloat::rmNearestTiesToEven);
1327 break;
1328 }
1329 case llvm::Instruction::FRem: {
1330 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1331 llvm::APFloat::rmNearestTiesToEven);
1332 break;
1333 }
1334 default: {
1335 llvm_unreachable("Invalid long double opcode");
1336 }
1337 }
1338 Result.IntVal = apfLHS.bitcastToAPInt();
1339 break;
1340 }
1341 default: {
1342 llvm_unreachable("Bad add type!");
1343 }
1344 } // End switch (Op0->getType()->getTypeID())
1345 return;
1346 }
1347 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001348 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001349 }
1350 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001351
1352 std::string msg;
1353 llvm::raw_string_ostream Msg(msg);
1354 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001355 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001356 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001357
1358 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001359 case llvm::Type::FloatTyID: {
1360 Result.FloatVal =
1361 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001362 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001363 }
1364 case llvm::Type::DoubleTyID: {
1365 Result.DoubleVal =
1366 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001367 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001368 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001369 case llvm::Type::X86_FP80TyID:
1370 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001371 case llvm::Type::PPC_FP128TyID: {
1372 Result.IntVal =
1373 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001374 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001375 }
1376 case llvm::Type::IntegerTyID: {
1377 Result.IntVal =
1378 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001379 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001380 }
1381 case llvm::Type::PointerTyID: {
1382 switch (C->getValueID()) {
1383 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001384 Result.PointerVal = NULL;
1385 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001386 }
1387 case llvm::Value::FunctionVal: {
1388 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1389 Result.PointerVal =
1390 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001391 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001392 }
1393 case llvm::Value::GlobalVariableVal: {
1394 const llvm::GlobalVariable *GV =
1395 static_cast<const llvm::GlobalVariable*>(C);
1396 Result.PointerVal =
1397 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001398 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001399 }
1400 case llvm::Value::BlockAddressVal: {
1401 assert(false && "JIT does not support address-of-label yet!");
1402 }
1403 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001404 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001405 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001406 }
1407 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001408 }
1409 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001410 std::string msg;
1411 llvm::raw_string_ostream Msg(msg);
1412 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001413 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001414 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001415 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001416 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001417 return;
1418 }
1419
Zonr Chang932648d2010-10-13 22:23:56 +08001420 // Stores the data in @Val of type @Ty at address @Addr.
1421 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001422 const llvm::Type *Ty) {
1423 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1424
Zonr Chang932648d2010-10-13 22:23:56 +08001425 switch (Ty->getTypeID()) {
1426 case llvm::Type::IntegerTyID: {
1427 const llvm::APInt &IntVal = Val.IntVal;
1428 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1429 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001430
Zonr Chang932648d2010-10-13 22:23:56 +08001431 const uint8_t *Src =
1432 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001433
Zonr Chang932648d2010-10-13 22:23:56 +08001434 if (llvm::sys::isLittleEndianHost()) {
1435 // Little-endian host - the source is ordered from LSB to MSB.
1436 // Order the destination from LSB to MSB: Do a straight copy.
1437 memcpy(Addr, Src, StoreBytes);
1438 } else {
1439 // Big-endian host - the source is an array of 64 bit words
1440 // ordered from LSW to MSW.
1441 //
1442 // Each word is ordered from MSB to LSB.
1443 //
1444 // Order the destination from MSB to LSB:
1445 // Reverse the word order, but not the bytes in a word.
1446 unsigned int i = StoreBytes;
1447 while (i > sizeof(uint64_t)) {
1448 i -= sizeof(uint64_t);
1449 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1450 Src,
1451 sizeof(uint64_t));
1452 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001453 }
Zonr Chang932648d2010-10-13 22:23:56 +08001454 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001455 }
1456 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001457 }
1458 case llvm::Type::FloatTyID: {
1459 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001460 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001461 }
1462 case llvm::Type::DoubleTyID: {
1463 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001464 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001465 }
1466 case llvm::Type::X86_FP80TyID: {
1467 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001468 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001469 }
1470 case llvm::Type::PointerTyID: {
1471 // Ensure 64 bit target pointers are fully initialized on 32 bit
1472 // hosts.
1473 if (StoreBytes != sizeof(llvm::PointerTy))
1474 memset(Addr, 0, StoreBytes);
1475 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001476 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001477 }
1478 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001479 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001480 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001481 }
1482
Zonr Chang932648d2010-10-13 22:23:56 +08001483 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1484 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1485 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001486
1487 return;
1488 }
1489
Zonr Chang932648d2010-10-13 22:23:56 +08001490 // Recursive function to apply a @Constant value into the specified memory
1491 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001492 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001493 switch (C->getValueID()) {
1494 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001495 // Nothing to do
1496 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001497 }
1498 case llvm::Value::ConstantVectorVal: {
1499 // dynamic cast may hurt performance
1500 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001501
Zonr Chang932648d2010-10-13 22:23:56 +08001502 unsigned int ElementSize = mpTD->getTypeAllocSize
1503 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001504
Zonr Chang932648d2010-10-13 22:23:56 +08001505 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1506 InitializeConstantToMemory(
1507 CP->getOperand(i),
1508 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001509 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001510 }
1511 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001512 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1513 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001514 }
1515 case llvm::Value::ConstantArrayVal: {
1516 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1517 unsigned int ElementSize = mpTD->getTypeAllocSize
1518 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001519
Zonr Chang932648d2010-10-13 22:23:56 +08001520 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1521 InitializeConstantToMemory(
1522 CPA->getOperand(i),
1523 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1524 break;
1525 }
1526 case llvm::Value::ConstantStructVal: {
1527 const llvm::ConstantStruct *CPS =
1528 static_cast<const llvm::ConstantStruct*>(C);
1529 const llvm::StructLayout *SL = mpTD->getStructLayout
1530 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001531
Zonr Chang932648d2010-10-13 22:23:56 +08001532 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1533 InitializeConstantToMemory(
1534 CPS->getOperand(i),
1535 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1536 break;
1537 }
1538 default: {
1539 if (C->getType()->isFirstClassType()) {
1540 llvm::GenericValue Val;
1541 GetConstantValue(C, Val);
1542 StoreValueToMemory(Val, Addr, C->getType());
1543 } else {
1544 llvm_unreachable("Unknown constant type to initialize memory "
1545 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001546 }
1547 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001548 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001549 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001550 return;
1551 }
1552
1553 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001554 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001555 return;
1556
Zonr Chang932648d2010-10-13 22:23:56 +08001557 // Constant pool address resolution is handled by the target itself in ARM
1558 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001559#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001560 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1561 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001562
Zonr Chang932648d2010-10-13 22:23:56 +08001563 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001564 return;
1565
1566 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1567 unsigned Align = MCP->getConstantPoolAlignment();
1568
1569 mpConstantPoolBase = allocateSpace(Size, Align);
1570 mpConstantPool = MCP;
1571
Zonr Chang932648d2010-10-13 22:23:56 +08001572 if (mpConstantPoolBase == NULL)
1573 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001574
1575 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001576 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001577 llvm::MachineConstantPoolEntry CPE = Constants[i];
1578 unsigned AlignMask = CPE.getAlignment() - 1;
1579 Offset = (Offset + AlignMask) & ~AlignMask;
1580
1581 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1582 mConstPoolAddresses.push_back(CAddr);
1583
Zonr Chang932648d2010-10-13 22:23:56 +08001584 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001585 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001586 ("Initialize memory with machine specific constant pool"
1587 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001588
1589 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1590
1591 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1592 Offset += mpTD->getTypeAllocSize(Ty);
1593 }
1594#endif
1595 return;
1596 }
1597
1598 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001599 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001600 return;
1601
Zonr Chang932648d2010-10-13 22:23:56 +08001602 const std::vector<llvm::MachineJumpTableEntry> &JT =
1603 MJTI->getJumpTables();
1604 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001605 return;
1606
1607 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001608 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001609 NumEntries += JT[i].MBBs.size();
1610
1611 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1612
Zonr Chang932648d2010-10-13 22:23:56 +08001613 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001614 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001615 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001616
1617 return;
1618 }
1619
1620 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001621 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001622 return;
1623
Zonr Chang932648d2010-10-13 22:23:56 +08001624 const std::vector<llvm::MachineJumpTableEntry> &JT =
1625 MJTI->getJumpTables();
1626 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001627 return;
1628
Zonr Chang932648d2010-10-13 22:23:56 +08001629 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1630 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1631 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001632
Zonr Chang932648d2010-10-13 22:23:56 +08001633 // For each jump table, map each target in the jump table to the
1634 // address of an emitted MachineBasicBlock.
1635 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1636 for (int i = 0, ie = JT.size(); i != ie; i++) {
1637 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1638 // Store the address of the basic block for this jump table slot in the
1639 // memory we allocated for the jump table in 'initJumpTableInfo'
1640 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001641 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1642 }
1643 }
1644
Zonr Chang932648d2010-10-13 22:23:56 +08001645 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1646 bool MayNeedFarStub) {
1647 switch (V->getValueID()) {
1648 case llvm::Value::FunctionVal: {
1649 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001650
Zonr Chang932648d2010-10-13 22:23:56 +08001651 // If we have code, go ahead and return that.
1652 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1653 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001654
Zonr Chang932648d2010-10-13 22:23:56 +08001655 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1656 // Return the function stub if it's already created.
1657 // We do this first so that:
1658 // we're returning the same address for the function as any
1659 // previous call.
1660 //
1661 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1662 // guaranteed to be close enough to call.
1663 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001664
Zonr Chang932648d2010-10-13 22:23:56 +08001665 // If we know the target can handle arbitrary-distance calls, try to
1666 // return a direct pointer.
1667 if (!MayNeedFarStub) {
1668 //
1669 // x86_64 architecture may encounter the bug:
1670 // http://llvm.org/bugs/show_bug.cgi?id=5201
1671 // which generate instruction "call" instead of "callq".
1672 //
1673 // And once the real address of stub is greater than 64-bit
1674 // long, the replacement will truncate to 32-bit resulting a
1675 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001676#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001677 // If this is an external function pointer, we can force the JIT
1678 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001679 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1680 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1681 // Changing to false because wanting to allow later calls to
1682 // mpTJI->relocate() without aborting. For caching purpose
1683 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001684#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001685 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001686
Zonr Chang932648d2010-10-13 22:23:56 +08001687 // Otherwise, we may need a to emit a stub, and, conservatively, we
1688 // always do so.
1689 return GetLazyFunctionStub(F);
1690 break;
1691 }
1692 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001693 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1694 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001695 }
1696 case llvm::Value::GlobalAliasVal: {
1697 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1698 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001699
Zonr Chang932648d2010-10-13 22:23:56 +08001700 switch (GV->getValueID()) {
1701 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001702 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001703 // code-gen'd?
1704 return GetPointerToFunction(
1705 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001706 /* AbortOnFailure = */false);
1707 // Changing to false because wanting to allow later calls to
1708 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001709 break;
1710 }
1711 case llvm::Value::GlobalVariableVal: {
1712 if (void *P = mGlobalAddressMap[GV])
1713 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001714
Zonr Chang932648d2010-10-13 22:23:56 +08001715 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1716 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001717
Zonr Chang932648d2010-10-13 22:23:56 +08001718 return mGlobalAddressMap[GV];
1719 break;
1720 }
1721 case llvm::Value::GlobalAliasVal: {
1722 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001723 }
1724 }
1725 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001726 }
1727 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001728 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001729 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001730 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001731 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001732 }
1733
Zonr Chang932648d2010-10-13 22:23:56 +08001734 // If the specified function has been code-gen'd, return a pointer to the
1735 // function. If not, compile it, or use a stub to implement lazy compilation
1736 // if available.
1737 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1738 // If we have already code generated the function, just return the
1739 // address.
1740 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001741 return Addr;
1742
Zonr Chang932648d2010-10-13 22:23:56 +08001743 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001744 return GetLazyFunctionStub(F);
1745 }
1746
Zonr Chang932648d2010-10-13 22:23:56 +08001747 typedef llvm::DenseMap<const llvm::Function*,
1748 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001749 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1750
Zonr Chang932648d2010-10-13 22:23:56 +08001751 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001752 return mFunctionToLazyStubMap.lookup(F);
1753 }
1754
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001755 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001756 void *GetLazyFunctionStub(llvm::Function *F) {
1757 // If we already have a lazy stub for this function, recycle it.
1758 void *&Stub = mFunctionToLazyStubMap[F];
1759 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001760 return Stub;
1761
Zonr Chang932648d2010-10-13 22:23:56 +08001762 // In any cases, we should NOT resolve function at runtime (though we are
1763 // able to). We resolve this right now.
1764 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001765 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1766 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1767 // Changing to false because wanting to allow later calls to
1768 // mpTJI->relocate() without aborting. For caching purpose
1769 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001770
Zonr Chang932648d2010-10-13 22:23:56 +08001771 // Codegen a new stub, calling the actual address of the external
1772 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001773 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1774 startGVStub(F, SL.Size, SL.Alignment);
1775 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1776 finishGVStub();
1777
Zonr Chang932648d2010-10-13 22:23:56 +08001778 // We really want the address of the stub in the GlobalAddressMap for the
1779 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001780 UpdateGlobalMapping(F, Stub);
1781
Zonr Chang932648d2010-10-13 22:23:56 +08001782 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001783 PendingFunctions.insert(F);
1784 else
Zonr Chang932648d2010-10-13 22:23:56 +08001785 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1786 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001787
1788 return Stub;
1789 }
1790
Zonr Chang932648d2010-10-13 22:23:56 +08001791 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1792 void *Addr = GetPointerToGlobalIfAvailable(F);
1793 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001794 return Addr;
1795
1796 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1797 "Internal error: only external defined function routes here!");
1798
Zonr Chang932648d2010-10-13 22:23:56 +08001799 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001800 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001801 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001802
Zonr Chang932648d2010-10-13 22:23:56 +08001803 // If we resolved the symbol to a null address (eg. a weak external)
1804 // return a null pointer let the application handle it.
1805 if (Addr == NULL) {
1806 if (AbortOnFailure)
1807 llvm::report_fatal_error("Could not resolve external function "
1808 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001809 else
1810 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001811 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001812
1813 AddGlobalMapping(F, Addr);
1814
1815 return Addr;
1816 }
1817
Zonr Chang932648d2010-10-13 22:23:56 +08001818 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001819 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001820 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001821 return Addr;
1822
Zonr Chang932648d2010-10-13 22:23:56 +08001823 if (mpSymbolLookupFn)
1824 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001825 return Addr;
1826
Zonr Chang932648d2010-10-13 22:23:56 +08001827 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001828 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001829 "' which could not be resolved!");
1830
1831 return NULL;
1832 }
1833
Zonr Chang932648d2010-10-13 22:23:56 +08001834 // Return the address of the specified global variable, possibly emitting it
1835 // to memory if needed. This is used by the Emitter.
1836 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1837 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1838 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001839 return Ptr;
1840
Zonr Chang932648d2010-10-13 22:23:56 +08001841 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1842 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001843 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1844 AddGlobalMapping(GV, Ptr);
1845 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001846 // If the global hasn't been emitted to memory yet, allocate space and
1847 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001848 Ptr = GetMemoryForGV(GV);
1849 AddGlobalMapping(GV, Ptr);
1850 EmitGlobalVariable(GV);
1851 }
1852
1853 return Ptr;
1854 }
1855
Zonr Chang932648d2010-10-13 22:23:56 +08001856 // This method abstracts memory allocation of global variable so that the
1857 // JIT can allocate thread local variables depending on the target.
1858 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1859 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001860
Zonr Chang932648d2010-10-13 22:23:56 +08001861 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001862 size_t S = mpTD->getTypeAllocSize(GlobalType);
1863 size_t A = mpTD->getPreferredAlignment(GV);
1864
Zonr Chang932648d2010-10-13 22:23:56 +08001865 if (GV->isThreadLocal()) {
1866 // We can support TLS by
1867 //
1868 // Ptr = TJI.allocateThreadLocalMemory(S);
1869 //
1870 // But I tend not to.
1871 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001872 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001873 ("Compilation of Thread Local Storage (TLS) is disabled!");
1874
Zonr Chang932648d2010-10-13 22:23:56 +08001875 } else if (mpTJI->allocateSeparateGVMemory()) {
1876 if (A <= 8) {
1877 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001878 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001879 // Allocate (S + A) bytes of memory, then use an aligned pointer
1880 // within that space.
1881 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001882 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001883 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1884 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001885 }
1886 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001887 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001888 }
1889
1890 return Ptr;
1891 }
1892
1893 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001894 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001895
Zonr Chang932648d2010-10-13 22:23:56 +08001896 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001897 llvm::report_fatal_error
1898 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001899
Zonr Chang932648d2010-10-13 22:23:56 +08001900 if (GA == NULL) {
1901 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001902 GA = GetMemoryForGV(GV);
1903 AddGlobalMapping(GV, GA);
1904 }
1905
1906 InitializeConstantToMemory(GV->getInitializer(), GA);
1907
Zonr Chang932648d2010-10-13 22:23:56 +08001908 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001909 return;
1910 }
1911
1912 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1913 > GlobalToIndirectSymMapTy;
1914 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1915
Zonr Chang932648d2010-10-13 22:23:56 +08001916 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1917 // Make sure GV is emitted first, and create a stub containing the fully
1918 // resolved address.
1919 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001920
Zonr Chang932648d2010-10-13 22:23:56 +08001921 // If we already have a stub for this global variable, recycle it.
1922 void *&IndirectSym = GlobalToIndirectSymMap[V];
1923 // Otherwise, codegen a new indirect symbol.
1924 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001925 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1926
1927 return IndirectSym;
1928 }
1929
Zonr Chang932648d2010-10-13 22:23:56 +08001930 // This is the equivalent of FunctionToLazyStubMap for external functions.
1931 //
1932 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1933 // It's actually here to make it more likely that far calls
1934 // succeed, but no single stub can guarantee that. I'll
1935 // remove this in a subsequent checkin when I actually fix
1936 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001937 std::map<void*, void*> ExternalFnToStubMap;
1938
Zonr Chang932648d2010-10-13 22:23:56 +08001939 // Return a stub for the function at the specified address.
1940 void *GetExternalFunctionStub(void *FnAddr) {
1941 void *&Stub = ExternalFnToStubMap[FnAddr];
1942 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001943 return Stub;
1944
1945 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1946 startGVStub(0, SL.Size, SL.Alignment);
1947 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1948 finishGVStub();
1949
1950 return Stub;
1951 }
1952
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001953#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001954 const llvm::MCAsmInfo *mpAsmInfo;
1955 const llvm::MCDisassembler *mpDisassmbler;
1956 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001957
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001958 class BufferMemoryObject : public llvm::MemoryObject {
1959 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001960 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001961 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001962
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001963 public:
1964 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1965 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001966
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001967 uint64_t getBase() const { return 0; }
1968 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001969
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001970 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001971 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001972 return -1;
1973 *Byte = mBytes[Addr];
1974 return 0;
1975 }
1976 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001977
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08001978 public:
Zonr Chang932648d2010-10-13 22:23:56 +08001979 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001980 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001981 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001982#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001983 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001984 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1985 ErrorInfo,
1986 llvm::raw_fd_ostream::F_Append);
1987 if (!ErrorInfo.empty()) { // some errors occurred
1988 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001989 delete OS;
1990 return;
1991 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001992#else
1993 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001994#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001995 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1996 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001997
Zonr Chang932648d2010-10-13 22:23:56 +08001998 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001999 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08002000 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002001 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08002002 if (mpIP == NULL)
2003 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
2004 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002005
Zonr Chang932648d2010-10-13 22:23:56 +08002006 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
2007 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002008 uint64_t Size;
2009 uint64_t Index;
2010
Zonr Chang932648d2010-10-13 22:23:56 +08002011 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002012 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002013
Zonr Chang932648d2010-10-13 22:23:56 +08002014 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2015 /* REMOVED */ llvm::nulls())) {
2016 (*OS).indent(4)
2017 .write("0x", 2)
2018 .write_hex((uint32_t) Start + Index)
2019 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002020 mpIP->printInst(&Inst, *OS);
2021 *OS << "\n";
2022 } else {
2023 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002024 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002025 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002026 }
2027
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002028 *OS << "\n";
2029 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002030
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002031#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002032 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002033 OS->close();
2034 delete OS;
2035#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002036 return;
2037 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002038#else
Zonr Chang932648d2010-10-13 22:23:56 +08002039 inline void Disassemble(const std::string &Name, uint8_t *Start,
2040 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002041 return;
2042 }
Zonr Chang932648d2010-10-13 22:23:56 +08002043#endif // defined(USE_DISASSEMBLER)
2044
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002045 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002046 // Resolver to undefined symbol in CodeEmitter
2047 BCCSymbolLookupFn mpSymbolLookupFn;
2048 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002049
2050 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002051 // Will take the ownership of @MemMgr
2052 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2053 : mpMemMgr(pMemMgr),
2054 mpTarget(NULL),
2055 mpTJI(NULL),
2056 mpTD(NULL),
2057 mpCurEmitFunction(NULL),
2058 mpConstantPool(NULL),
2059 mpJumpTable(NULL),
2060 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002061#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002062 mpAsmInfo(NULL),
2063 mpDisassmbler(NULL),
2064 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002065#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002066 mpSymbolLookupFn(NULL),
2067 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002068 return;
2069 }
2070
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002071 inline global_addresses_const_iterator global_address_begin() const {
2072 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002073 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002074 inline global_addresses_const_iterator global_address_end() const {
2075 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002076 }
2077
Logan824dd0a2010-11-20 01:45:54 +08002078 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2079 return mCachingRelocations;
2080 }
2081
Zonr Chang932648d2010-10-13 22:23:56 +08002082 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002083 mpSymbolLookupFn = pFn;
2084 mpSymbolLookupContext = pContext;
2085 return;
2086 }
2087
Zonr Chang932648d2010-10-13 22:23:56 +08002088 void setTargetMachine(llvm::TargetMachine &TM) {
2089 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002090 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002091 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002092 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002093 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002094 mpTD = TM.getTargetData();
2095
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002096 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2097
2098 return;
2099 }
2100
Zonr Chang932648d2010-10-13 22:23:56 +08002101 // This callback is invoked when the specified function is about to be code
2102 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002103 void startFunction(llvm::MachineFunction &F) {
2104 uintptr_t ActualSize = 0;
2105
2106 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002107
2108 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2109 // MachineCodeEmitter, which is the super class of the class
2110 // JITCodeEmitter.
2111 //
2112 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2113 // allocated for this code buffer.
2114 //
2115 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2116 // code. This is guranteed to be in the range
2117 // [BufferBegin, BufferEnd]. If this pointer is at
2118 // BufferEnd, it will never move due to code emission, and
2119 // all code emission requests will be ignored (this is the
2120 // buffer overflow condition).
2121 BufferBegin = CurBufferPtr =
2122 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002123 BufferEnd = BufferBegin + ActualSize;
2124
Zonr Chang932648d2010-10-13 22:23:56 +08002125 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002126 mpCurEmitFunction = new EmittedFunctionCode();
2127 mpCurEmitFunction->FunctionBody = BufferBegin;
2128
Zonr Chang932648d2010-10-13 22:23:56 +08002129 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002130 emitAlignment(16);
2131
2132 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002133 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002134 initJumpTableInfo(MJTI);
2135
Zonr Chang932648d2010-10-13 22:23:56 +08002136 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002137 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2138
2139 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2140
2141 mpCurEmitFunction->Code = CurBufferPtr;
2142
2143 mMBBLocations.clear();
2144
2145 return;
2146 }
2147
Zonr Chang932648d2010-10-13 22:23:56 +08002148 // This callback is invoked when the specified function has finished code
2149 // generation. If a buffer overflow has occurred, this method returns true
2150 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002151 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002152 if (CurBufferPtr == BufferEnd) {
2153 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002154 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2155 return false;
2156 }
2157
Zonr Chang932648d2010-10-13 22:23:56 +08002158 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002159 emitJumpTableInfo(MJTI);
2160
Zonr Chang932648d2010-10-13 22:23:56 +08002161 // FnStart is the start of the text, not the start of the constant pool
2162 // and other per-function data.
2163 uint8_t *FnStart =
2164 reinterpret_cast<uint8_t*>(
2165 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002166
Zonr Chang932648d2010-10-13 22:23:56 +08002167 // FnEnd is the end of the function's machine code.
2168 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002169
Zonr Chang932648d2010-10-13 22:23:56 +08002170 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002171 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2172
Zonr Chang932648d2010-10-13 22:23:56 +08002173 // Resolve the relocations to concrete pointers.
2174 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2175 llvm::MachineRelocation &MR = mRelocations[i];
2176 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002177
Zonr Chang932648d2010-10-13 22:23:56 +08002178 if (!MR.letTargetResolve()) {
2179 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002180 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002181
2182 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002183 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002184 }
2185
Zonr Chang932648d2010-10-13 22:23:56 +08002186 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002187 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2188 BufferBegin
2189 + MR.getMachineCodeOffset(),
2190 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002191 } else if (MR.isIndirectSymbol()) {
2192 ResultPtr =
2193 GetPointerToGVIndirectSym(
2194 MR.getGlobalValue(),
2195 BufferBegin + MR.getMachineCodeOffset());
2196 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002197 ResultPtr =
2198 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002199 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002200 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002201 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002202 } else {
2203 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2204 ResultPtr =
2205 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2206 }
2207
Logan824dd0a2010-11-20 01:45:54 +08002208 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2209 // TODO(logan): Cache external symbol relocation entry.
2210 // Currently, we are not caching them. But since Android
2211 // system is using prelink, it is not a problem.
2212
2213 // Cache the relocation result address
2214 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002215 oBCCRelocEntry(MR.getRelocationType(),
2216 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002217 ResultPtr));
2218 }
2219
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002220 MR.setResultPointer(ResultPtr);
2221 }
2222 }
2223
2224 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2225 mpMemMgr->getGOTBase());
2226 }
2227
2228 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002229 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2230 // global variables that were referenced in the relocations.
2231 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002232 return false;
2233
Zonr Chang932648d2010-10-13 22:23:56 +08002234 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002235 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2236 BufferBegin = CurBufferPtr = 0;
2237
Zonr Chang932648d2010-10-13 22:23:56 +08002238 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002239 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2240 mpCurEmitFunction = NULL;
2241
2242 mRelocations.clear();
2243 mConstPoolAddresses.clear();
2244
Zonr Chang932648d2010-10-13 22:23:56 +08002245 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002246 mpMMI->EndFunction();
2247
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002248 updateFunctionStub(F.getFunction());
2249
Zonr Chang932648d2010-10-13 22:23:56 +08002250 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002251 mpMemMgr->setMemoryExecutable();
2252
2253 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2254
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002255 return false;
2256 }
2257
Zonr Chang932648d2010-10-13 22:23:56 +08002258 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002259 unsigned Alignment) {
2260 mpSavedBufferBegin = BufferBegin;
2261 mpSavedBufferEnd = BufferEnd;
2262 mpSavedCurBufferPtr = CurBufferPtr;
2263
2264 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2265 Alignment);
2266 BufferEnd = BufferBegin + StubSize + 1;
2267
2268 return;
2269 }
2270
Zonr Chang932648d2010-10-13 22:23:56 +08002271 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002272 mpSavedBufferBegin = BufferBegin;
2273 mpSavedBufferEnd = BufferEnd;
2274 mpSavedCurBufferPtr = CurBufferPtr;
2275
Zonr Chang932648d2010-10-13 22:23:56 +08002276 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002277 BufferEnd = BufferBegin + StubSize + 1;
2278
2279 return;
2280 }
2281
2282 void finishGVStub() {
2283 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2284
Zonr Chang932648d2010-10-13 22:23:56 +08002285 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002286 BufferBegin = mpSavedBufferBegin;
2287 BufferEnd = mpSavedBufferEnd;
2288 CurBufferPtr = mpSavedCurBufferPtr;
2289
2290 return;
2291 }
2292
Zonr Chang932648d2010-10-13 22:23:56 +08002293 // Allocates and fills storage for an indirect GlobalValue, and returns the
2294 // address.
2295 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002296 const uint8_t *Buffer, size_t Size,
2297 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002298 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002299 memcpy(IndGV, Buffer, Size);
2300 return IndGV;
2301 }
2302
Zonr Chang932648d2010-10-13 22:23:56 +08002303 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002304 void emitLabel(llvm::MCSymbol *Label) {
2305 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002306 return;
2307 }
2308
Zonr Chang932648d2010-10-13 22:23:56 +08002309 // Allocate memory for a global. Unlike allocateSpace, this method does not
2310 // allocate memory in the current output buffer, because a global may live
2311 // longer than the current function.
2312 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2313 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002314 return mpMemMgr->allocateGlobal(Size, Alignment);
2315 }
2316
Zonr Chang932648d2010-10-13 22:23:56 +08002317 // This should be called by the target when a new basic block is about to be
2318 // emitted. This way the MCE knows where the start of the block is, and can
2319 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002320 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002321 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002322 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2323 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2324 return;
2325 }
2326
Zonr Chang932648d2010-10-13 22:23:56 +08002327 // Whenever a relocatable address is needed, it should be noted with this
2328 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002329 void addRelocation(const llvm::MachineRelocation &MR) {
2330 mRelocations.push_back(MR);
2331 return;
2332 }
2333
Zonr Chang932648d2010-10-13 22:23:56 +08002334 // Return the address of the @Index entry in the constant pool that was
2335 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002336 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2337 assert(Index < mpConstantPool->getConstants().size() &&
2338 "Invalid constant pool index!");
2339 return mConstPoolAddresses[Index];
2340 }
2341
Zonr Chang932648d2010-10-13 22:23:56 +08002342 // Return the address of the jump table with index @Index in the function
2343 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002344 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002345 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002346 mpJumpTable->getJumpTables();
2347
Zonr Chang932648d2010-10-13 22:23:56 +08002348 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002349
2350 unsigned int Offset = 0;
2351 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2352
Zonr Chang932648d2010-10-13 22:23:56 +08002353 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002354 Offset += JT[i].MBBs.size();
2355 Offset *= EntrySize;
2356
Zonr Chang932648d2010-10-13 22:23:56 +08002357 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002358 }
2359
Zonr Chang932648d2010-10-13 22:23:56 +08002360 // Return the address of the specified MachineBasicBlock, only usable after
2361 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002362 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2363 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002364 mMBBLocations[MBB->getNumber()] &&
2365 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002366 return mMBBLocations[MBB->getNumber()];
2367 }
2368
Zonr Chang932648d2010-10-13 22:23:56 +08002369 // Return the address of the specified LabelID, only usable after the
2370 // LabelID has been emitted.
2371 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002372 assert(mLabelLocations.count(Label) && "Label not emitted!");
2373 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002374 }
2375
Zonr Chang932648d2010-10-13 22:23:56 +08002376 // Specifies the MachineModuleInfo object. This is used for exception
2377 // handling purposes.
2378 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002379 mpMMI = Info;
2380 return;
2381 }
2382
Zonr Chang932648d2010-10-13 22:23:56 +08002383 void updateFunctionStub(const llvm::Function *F) {
2384 // Get the empty stub we generated earlier.
2385 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002386 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002387 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002388 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002389 else
2390 return;
2391
Zonr Chang932648d2010-10-13 22:23:56 +08002392 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002393
2394 assert(Addr != Stub &&
2395 "Function must have non-stub address to be updated.");
2396
Zonr Chang932648d2010-10-13 22:23:56 +08002397 // Tell the target jit info to rewrite the stub at the specified address,
2398 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002399 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2400 startGVStub(Stub, SL.Size);
2401 mpTJI->emitFunctionStub(F, Addr, *this);
2402 finishGVStub();
2403
Zonr Chang932648d2010-10-13 22:23:56 +08002404 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2405 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002406
2407 PendingFunctions.erase(I);
2408
2409 return;
2410 }
2411
Zonr Chang932648d2010-10-13 22:23:56 +08002412 // Once you finish the compilation on a translation unit, you can call this
2413 // function to recycle the memory (which is used at compilation time and not
2414 // needed for runtime).
2415 //
2416 // NOTE: You should not call this funtion until the code-gen passes for a
2417 // given module is done. Otherwise, the results is undefined and may
2418 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002419 void releaseUnnecessary() {
2420 mMBBLocations.clear();
2421 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002422 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002423 mFunctionToLazyStubMap.clear();
2424 GlobalToIndirectSymMap.clear();
2425 ExternalFnToStubMap.clear();
2426 PendingFunctions.clear();
2427
2428 return;
2429 }
2430
2431 void reset() {
2432 releaseUnnecessary();
2433
2434 mpSymbolLookupFn = NULL;
2435 mpSymbolLookupContext = NULL;
2436
2437 mpTJI = NULL;
2438 mpTD = NULL;
2439
Zonr Chang932648d2010-10-13 22:23:56 +08002440 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2441 E = mEmittedFunctions.end();
2442 I != E;
2443 I++)
2444 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002445 delete I->second;
2446 mEmittedFunctions.clear();
2447
2448 mpMemMgr->reset();
2449
2450 return;
2451 }
2452
Zonr Chang932648d2010-10-13 22:23:56 +08002453 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002454 return lookup( llvm::StringRef(Name) );
2455 }
2456
Zonr Chang932648d2010-10-13 22:23:56 +08002457 void *lookup(const llvm::StringRef &Name) {
2458 EmittedFunctionsMapTy::const_iterator I =
2459 mEmittedFunctions.find(Name.str());
2460 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002461 return NULL;
2462 else
2463 return I->second->Code;
2464 }
2465
Zonr Chang932648d2010-10-13 22:23:56 +08002466 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002467 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002468 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002469 int functionCount = mEmittedFunctions.size();
2470
Zonr Chang932648d2010-10-13 22:23:56 +08002471 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002472 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002473 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002474 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002475 if (functions)
2476 for (EmittedFunctionsMapTy::const_iterator
2477 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2478 (I != E) && (functionCount > 0);
2479 I++, functionCount--)
2480 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002481
2482 return;
2483 }
2484
Zonr Chang932648d2010-10-13 22:23:56 +08002485 void getFunctionBinary(BCCchar *label,
2486 BCCvoid **base,
2487 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002488 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002489 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002490 *base = NULL;
2491 *length = 0;
2492 } else {
2493 *base = I->second->Code;
2494 *length = I->second->Size;
2495 }
2496 return;
2497 }
2498
2499 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002500 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002501#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002502 delete mpAsmInfo;
2503 delete mpDisassmbler;
2504 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002505#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002506 return;
2507 }
Zonr Chang932648d2010-10-13 22:23:56 +08002508 };
2509 // End of Class CodeEmitter
2510 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002511
Zonr Chang932648d2010-10-13 22:23:56 +08002512 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002513 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002514 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002515 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2516 return mCodeEmitter.get();
2517 }
2518
2519 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002520 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002521
Zonr Chang932648d2010-10-13 22:23:56 +08002522 llvm::LLVMContext *mContext;
2523 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002524
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002525 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002526
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002527 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002528 Compiler()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002529 : mNeverCache(true),
2530 mCacheNew(false),
2531 mCacheFd(-1),
2532 mCacheMapAddr(NULL),
2533 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002534 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002535 mCacheDiff(0),
2536 mCodeDataAddr(NULL),
2537 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002538 mpSymbolLookupContext(NULL),
2539 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002540 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002541 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002542 llvm::remove_fatal_error_handler();
2543 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002544 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002545 return;
2546 }
2547
Zonr Chang932648d2010-10-13 22:23:56 +08002548 // interface for BCCscript::registerSymbolCallback()
2549 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002550 mpSymbolLookupFn = pFn;
2551 mpSymbolLookupContext = pContext;
2552 return;
2553 }
2554
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002555 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002556 GlobalInitialization();
2557 mModule = module;
2558 return hasError();
2559 }
2560
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002561 int readBC(const char *bitcode,
2562 size_t bitcodeSize,
2563 const BCCchar *resName) {
2564 GlobalInitialization();
2565
2566 if (resName) {
Loganad7e8e12010-11-22 20:43:43 +08002567 if (!BccCodeAddrTaken) {
2568 // Turn off the default NeverCaching mode
2569 mNeverCache = false;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002570
Loganad7e8e12010-11-22 20:43:43 +08002571 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2572 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2573 return -mCacheFd;
2574 }
2575 } else {
2576 mNeverCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002577 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002578 }
2579
2580 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002581
Zonr Chang932648d2010-10-13 22:23:56 +08002582 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002583 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002584
Zonr Chang932648d2010-10-13 22:23:56 +08002585 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002586 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002587 llvm::StringRef(bitcode, bitcodeSize)));
2588
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002589 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002590 setError("Error reading input program bitcode into memory");
2591 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002592 }
2593
Zonr Chang932648d2010-10-13 22:23:56 +08002594 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002595 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2596 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002597 return hasError();
2598 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002599
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002600 int linkBC(const char *bitcode, size_t bitcodeSize) {
2601 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002602
2603 if (bitcode == NULL || bitcodeSize <= 0)
2604 return 0;
2605
2606 if (mModule == NULL) {
2607 setError("No module presents for linking");
2608 return hasError();
2609 }
2610
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002611 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002612 llvm::StringRef(bitcode, bitcodeSize)));
2613
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002614 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002615 setError("Error reading input library bitcode into memory");
2616 return hasError();
2617 }
2618
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002619 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002620 *mContext,
2621 &mError));
2622 if (Lib.get() == NULL)
2623 return hasError();
2624
2625 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2626 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002627
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002628 // Everything for linking should be settled down here with no error occurs
2629 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002630 return hasError();
2631 }
2632
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002633
2634 // interface for bccLoadBinary()
2635 int loader() {
2636 // Check File Descriptor
2637 if (mCacheFd < 0) {
2638 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2639 goto giveup;
2640 }
2641
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002642 // Check File Size
2643 struct stat statCacheFd;
2644 if (fstat(mCacheFd, &statCacheFd) < 0) {
2645 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2646 goto giveup;
2647 }
2648
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002649 mCacheSize = statCacheFd.st_size;
2650
2651 if (mCacheSize < sizeof(oBCCHeader) ||
2652 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002653 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2654 goto giveup;
2655 }
2656
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002657 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2658 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2659 goto giveup;
2660 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002661
2662 // Read File Content
2663 {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002664 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002665 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Loganad7e8e12010-11-22 20:43:43 +08002666 LOGE("sliao@Loader: mCacheSize=%x, heuristicCodeOffset=%llx",
2667 (unsigned int)mCacheSize,
2668 (unsigned long long int)heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002669
2670 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002671 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002672 flock(mCacheFd, LOCK_UN);
2673 LOGE("allocation failed.\n");
2674 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002675 }
2676
2677 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2678 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002679 if (nread != (size_t)heuristicCodeOffset) {
2680 LOGE("read(mCacheFd) failed\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002681 goto bail;
2682 }
2683
2684 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002685 // Sanity check
2686 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2687 LOGE("assertion failed: heuristic code offset is not correct.\n");
2688 goto bail;
2689 }
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002690 LOGE("sliao: mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2691 LOGE("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2692 LOGE("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2693 LOGE("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2694 LOGE("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002695
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002696 // Verify the Cache File
2697 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2698 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002699 goto bail;
2700 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002701
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002702 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2703 LOGE("bad oBCC version 0x%08x\n",
2704 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2705 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002706 }
2707
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002708 if (mCacheSize < mCacheHdr->relocOffset +
2709 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2710 LOGE("relocate table overflow\n");
2711 goto bail;
2712 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002713
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002714 if (mCacheSize < mCacheHdr->exportVarsOffset +
2715 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2716 LOGE("export variables table overflow\n");
2717 goto bail;
2718 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002719
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002720 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2721 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2722 LOGE("export functions table overflow\n");
2723 goto bail;
2724 }
2725
2726 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2727 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2728 LOGE("export pragmas table overflow\n");
2729 goto bail;
2730 }
2731
2732 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2733 LOGE("code cache overflow\n");
2734 goto bail;
2735 }
2736
2737 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2738 LOGE("data (global variable) cache overflow\n");
2739 goto bail;
2740 }
2741
2742 // Part 2. Deal with the codedata section
2743 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2744 MaxCodeSize + MaxGlobalVarSize,
2745 PROT_READ | PROT_EXEC | PROT_WRITE,
2746 MAP_PRIVATE | MAP_FIXED,
2747 mCacheFd, heuristicCodeOffset);
2748 if (mCodeDataAddr != MAP_FAILED &&
2749 mCodeDataAddr ==
2750 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr)) {
2751 // relocate is avoidable
Loganad7e8e12010-11-22 20:43:43 +08002752 BccCodeAddrTaken = true;
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002753
2754 flock(mCacheFd, LOCK_UN);
2755 } else {
2756 mCacheMapAddr = (char *) mmap(0,
2757 mCacheSize,
2758 PROT_READ | PROT_EXEC | PROT_WRITE,
2759 MAP_PRIVATE,
2760 mCacheFd,
2761 0);
2762 if (mCacheMapAddr == MAP_FAILED) {
2763 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2764 flock(mCacheFd, LOCK_UN);
2765 goto giveup;
2766 }
2767
2768 flock(mCacheFd, LOCK_UN);
2769 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2770 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002771 }
2772
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002773 // Relocate
2774 {
2775 mCacheDiff = mCodeDataAddr -
2776 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2777
Loganad7e8e12010-11-22 20:43:43 +08002778 if (!BccCodeAddrTaken) { // To relocate
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002779 if (mCacheHdr->rootAddr) {
2780 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002781 }
2782
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002783 if (mCacheHdr->initAddr) {
2784 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002785 }
2786
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002787 oBCCRelocEntry *cachedRelocTable =
2788 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2789 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002790
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002791 std::vector<llvm::MachineRelocation> relocations;
2792
2793 // Read in the relocs
2794 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2795 oBCCRelocEntry *entry = &cachedRelocTable[i];
2796
2797 llvm::MachineRelocation reloc =
2798 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2799 (unsigned)entry->relocType, 0, 0);
2800
2801 reloc.setResultPointer(
2802 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2803
2804 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002805 }
2806
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002807 // Rewrite machine code using llvm::TargetJITInfo relocate
2808 {
2809 llvm::TargetMachine *TM = NULL;
2810 const llvm::Target *Target;
2811 std::string FeaturesStr;
2812
2813 // Create TargetMachine
2814 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2815 if (hasError())
2816 goto bail;
2817
2818 if (!CPU.empty() || !Features.empty()) {
2819 llvm::SubtargetFeatures F;
2820 F.setCPU(CPU);
2821 for (std::vector<std::string>::const_iterator I = Features.begin(),
2822 E = Features.end(); I != E; I++)
2823 F.AddFeature(*I);
2824 FeaturesStr = F.getString();
2825 }
2826
2827 TM = Target->createTargetMachine(Triple, FeaturesStr);
2828 if (TM == NULL) {
2829 setError("Failed to create target machine implementation for the"
2830 " specified triple '" + Triple + "'");
2831 goto bail;
2832 }
2833
2834 TM->getJITInfo()->relocate(mCodeDataAddr,
2835 &relocations[0], relocations.size(),
2836 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2837
2838 if (mCodeEmitter.get()) {
2839 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2840 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2841 2 * 1024 /*MaxCodeSize*/,
2842 false);
2843 }
2844
2845 delete TM;
2846 }
Loganad7e8e12010-11-22 20:43:43 +08002847 } // End of if (!BccCodeAddrTaken)
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002848 }
2849
2850 return 0;
2851
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002852 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002853 if (mCacheMapAddr) {
2854 free(mCacheMapAddr);
Loganad7e8e12010-11-22 20:43:43 +08002855 mCacheMapAddr = 0;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002856 }
Loganad7e8e12010-11-22 20:43:43 +08002857
2858 if (BccCodeAddrTaken) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002859 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2860 LOGE("munmap failed: %s\n", strerror(errno));
2861 }
Loganad7e8e12010-11-22 20:43:43 +08002862 mCodeDataAddr = 0;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002863 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002864
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002865 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002866 return 1;
2867 }
2868
2869 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002870 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002871 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002872
Zonr Chang932648d2010-10-13 22:23:56 +08002873 llvm::TargetMachine *TM = NULL;
2874 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002875 std::string FeaturesStr;
2876
Zonr Chang932648d2010-10-13 22:23:56 +08002877 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002878
Zonr Chang932648d2010-10-13 22:23:56 +08002879 const llvm::NamedMDNode *PragmaMetadata;
2880 const llvm::NamedMDNode *ExportVarMetadata;
2881 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002882
Zonr Chang932648d2010-10-13 22:23:56 +08002883 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002884 return 0;
2885
Zonr Chang932648d2010-10-13 22:23:56 +08002886 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002887 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002888 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002889 goto on_bcc_compile_error;
2890
Zonr Chang932648d2010-10-13 22:23:56 +08002891 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002892 llvm::SubtargetFeatures F;
2893 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002894 for (std::vector<std::string>::const_iterator I = Features.begin(),
2895 E = Features.end();
2896 I != E;
2897 I++)
2898 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002899 FeaturesStr = F.getString();
2900 }
2901
2902 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002903 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002904 setError("Failed to create target machine implementation for the"
2905 " specified triple '" + Triple + "'");
2906 goto on_bcc_compile_error;
2907 }
2908
Zonr Chang932648d2010-10-13 22:23:56 +08002909 // Create memory manager for creation of code emitter later.
2910 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002911 setError("Failed to startup memory management for further compilation");
2912 goto on_bcc_compile_error;
2913 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002914 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002915
Zonr Chang932648d2010-10-13 22:23:56 +08002916 // Create code emitter
2917 if (!mCodeEmitter.get()) {
2918 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002919 setError("Failed to create machine code emitter to complete"
2920 " the compilation");
2921 goto on_bcc_compile_error;
2922 }
2923 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002924 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002925 mCodeEmitter->reset();
2926 }
2927
2928 mCodeEmitter->setTargetMachine(*TM);
2929 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2930 mpSymbolLookupContext);
2931
Zonr Chang932648d2010-10-13 22:23:56 +08002932 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002933 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002934
Zonr Chang5d35b972010-10-23 14:36:47 +08002935 // Load named metadata
2936 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2937 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2938 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2939
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002940 // Create LTO passes and run them on the mModule
2941 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002942 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002943 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08002944 LTOPasses.add(new llvm::TargetData(*TD));
2945
2946 std::vector<const char*> ExportSymbols;
2947
2948 // A workaround for getting export variable and function name. Will refine
2949 // it soon.
2950 if (ExportVarMetadata) {
2951 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2952 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2953 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2954 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2955 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2956 llvm::StringRef ExportVarName =
2957 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2958 ExportSymbols.push_back(ExportVarName.data());
2959 }
2960 }
2961 }
2962 }
2963
2964 if (ExportFuncMetadata) {
2965 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2966 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2967 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2968 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2969 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2970 llvm::StringRef ExportFuncName =
2971 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2972 ExportSymbols.push_back(ExportFuncName.data());
2973 }
2974 }
2975 }
2976 }
2977 // root() and init() are born to be exported
2978 ExportSymbols.push_back("root");
2979 ExportSymbols.push_back("init");
2980
Zonr Change5c7a542010-10-24 01:07:27 +08002981 // We now create passes list performing LTO. These are copied from
2982 // (including comments) llvm::createStandardLTOPasses().
2983
2984 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08002985 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002986
Zonr Change5c7a542010-10-24 01:07:27 +08002987 // Propagate constants at call sites into the functions they call. This
2988 // opens opportunities for globalopt (and inlining) by substituting
2989 // function pointers passed as arguments to direct uses of functions.
2990 LTOPasses.add(llvm::createIPSCCPPass());
2991
2992 // Now that we internalized some globals, see if we can hack on them!
2993 LTOPasses.add(llvm::createGlobalOptimizerPass());
2994
2995 // Linking modules together can lead to duplicated global constants, only
2996 // keep one copy of each constant...
2997 LTOPasses.add(llvm::createConstantMergePass());
2998
2999 // Remove unused arguments from functions...
3000 LTOPasses.add(llvm::createDeadArgEliminationPass());
3001
3002 // Reduce the code after globalopt and ipsccp. Both can open up
3003 // significant simplification opportunities, and both can propagate
3004 // functions through function pointers. When this happens, we often have
3005 // to resolve varargs calls, etc, so let instcombine do this.
3006 LTOPasses.add(llvm::createInstructionCombiningPass());
3007
3008 // Inline small functions
3009 LTOPasses.add(llvm::createFunctionInliningPass());
3010
3011 // Remove dead EH info.
3012 LTOPasses.add(llvm::createPruneEHPass());
3013
3014 // Internalize the globals again after inlining
3015 LTOPasses.add(llvm::createGlobalOptimizerPass());
3016
3017 // Remove dead functions.
3018 LTOPasses.add(llvm::createGlobalDCEPass());
3019
3020 // If we didn't decide to inline a function, check to see if we can
3021 // transform it to pass arguments by value instead of by reference.
3022 LTOPasses.add(llvm::createArgumentPromotionPass());
3023
3024 // The IPO passes may leave cruft around. Clean up after them.
3025 LTOPasses.add(llvm::createInstructionCombiningPass());
3026 LTOPasses.add(llvm::createJumpThreadingPass());
3027
3028 // Break up allocas
3029 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3030
3031 // Run a few AA driven optimizations here and now, to cleanup the code.
3032 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3033 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3034
3035 // Hoist loop invariants.
3036 LTOPasses.add(llvm::createLICMPass());
3037
3038 // Remove redundancies.
3039 LTOPasses.add(llvm::createGVNPass());
3040
3041 // Remove dead memcpys.
3042 LTOPasses.add(llvm::createMemCpyOptPass());
3043
3044 // Nuke dead stores.
3045 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3046
3047 // Cleanup and simplify the code after the scalar optimizations.
3048 LTOPasses.add(llvm::createInstructionCombiningPass());
3049
3050 LTOPasses.add(llvm::createJumpThreadingPass());
3051
3052 // Delete basic blocks, which optimization passes may have killed.
3053 LTOPasses.add(llvm::createCFGSimplificationPass());
3054
3055 // Now that we have optimized the program, discard unreachable functions.
3056 LTOPasses.add(llvm::createGlobalDCEPass());
3057
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003058 LTOPasses.run(*mModule);
3059 }
3060
Zonr Chang932648d2010-10-13 22:23:56 +08003061 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003062 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003063 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003064
Zonr Chang932648d2010-10-13 22:23:56 +08003065 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3066 *mCodeEmitter,
3067 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003068 setError("The machine code emission is not supported by BCC on target '"
3069 + Triple + "'");
3070 goto on_bcc_compile_error;
3071 }
3072
Zonr Chang932648d2010-10-13 22:23:56 +08003073 // Run the pass (the code emitter) on every non-declaration function in the
3074 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003075 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003076 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3077 I != E;
3078 I++)
3079 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003080 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003081
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003082 CodeGenPasses->doFinalization();
3083
Zonr Chang932648d2010-10-13 22:23:56 +08003084 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003085 if (ExportVarMetadata) {
3086 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3087 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3088 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3089 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3090 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003091 llvm::StringRef ExportVarName =
3092 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003093 CodeEmitter::global_addresses_const_iterator I, E;
3094 for (I = mCodeEmitter->global_address_begin(),
3095 E = mCodeEmitter->global_address_end();
3096 I != E;
3097 I++) {
3098 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003099 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003100 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003101 mExportVars.push_back(I->second);
3102 break;
3103 }
3104 }
Zonr Chang932648d2010-10-13 22:23:56 +08003105 if (I != mCodeEmitter->global_address_end())
3106 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003107 }
3108 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003109 // if reaching here, we know the global variable record in metadata is
3110 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003111 mExportVars.push_back(NULL);
3112 }
3113 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3114 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003115 }
3116
Zonr Chang932648d2010-10-13 22:23:56 +08003117 if (ExportFuncMetadata) {
3118 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3119 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3120 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3121 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3122 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003123 llvm::StringRef ExportFuncName =
3124 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3125 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3126 }
3127 }
3128 }
3129 }
3130
Zonr Chang932648d2010-10-13 22:23:56 +08003131 // Tell code emitter now can release the memory using during the JIT since
3132 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003133 mCodeEmitter->releaseUnnecessary();
3134
Zonr Chang932648d2010-10-13 22:23:56 +08003135 // Finally, read pragma information from the metadata node of the @Module if
3136 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003137 if (PragmaMetadata)
3138 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3139 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3140 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003141 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003142 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3143 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003144
Zonr Chang932648d2010-10-13 22:23:56 +08003145 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003146 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3147 llvm::StringRef PragmaName =
3148 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3149 llvm::StringRef PragmaValue =
3150 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3151
Zonr Chang932648d2010-10-13 22:23:56 +08003152 mPragmas.push_back(
3153 std::make_pair(std::string(PragmaName.data(),
3154 PragmaName.size()),
3155 std::string(PragmaValue.data(),
3156 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003157 }
3158 }
3159 }
3160
3161 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003162 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003163 if (CodeGenPasses) {
3164 delete CodeGenPasses;
3165 } else if (TD) {
3166 delete TD;
3167 }
3168 if (TM)
3169 delete TM;
3170
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003171 if (mError.empty()) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003172 if (!mNeverCache && mCacheFd >= 0 && mCacheNew) {
3173 genCacheFile();
3174 flock(mCacheFd, LOCK_UN);
3175 }
3176
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003177 return false;
3178 }
3179
Zonr Chang932648d2010-10-13 22:23:56 +08003180 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003181 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003182 }
3183
Zonr Chang932648d2010-10-13 22:23:56 +08003184 // interface for bccGetScriptInfoLog()
3185 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003186 return const_cast<char*>(mError.c_str());
3187 }
3188
Zonr Chang932648d2010-10-13 22:23:56 +08003189 // interface for bccGetScriptLabel()
3190 void *lookup(const char *name) {
3191 void *addr = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003192 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3193 if (!strcmp(name, "root")) {
3194 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3195 } else if (!strcmp(name, "init")) {
3196 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3197 }
3198 return addr;
3199 }
3200
Zonr Chang932648d2010-10-13 22:23:56 +08003201 if (mCodeEmitter.get())
3202 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003203 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003204 return addr;
3205 }
3206
Zonr Chang932648d2010-10-13 22:23:56 +08003207 // Interface for bccGetExportVars()
3208 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003209 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003210 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003211 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003212
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003213 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3214 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3215 if (actualVarCount)
3216 *actualVarCount = varCount;
3217 if (varCount > maxVarCount)
3218 varCount = maxVarCount;
3219 if (vars) {
3220 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3221 mCacheHdr->exportVarsOffset);
3222
3223 for (int i = 0; i < varCount; i++) {
3224 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3225 mCacheDiff);
3226 cachedVars++;
3227 }
3228 }
3229 return;
3230 }
3231
3232 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003233 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003234 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003235 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003236 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003237 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003238 for (ExportVarList::const_iterator I = mExportVars.begin(),
3239 E = mExportVars.end();
3240 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003241 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003242 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003243 }
3244 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003245
3246 return;
3247 }
3248
Zonr Chang932648d2010-10-13 22:23:56 +08003249 // Interface for bccGetExportFuncs()
3250 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003251 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003252 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003253 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003254
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003255 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3256 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3257 if (actualFuncCount)
3258 *actualFuncCount = funcCount;
3259 if (funcCount > maxFuncCount)
3260 funcCount = maxFuncCount;
3261 if (funcs) {
3262 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3263 mCacheHdr->exportFuncsOffset);
3264
3265 for (int i = 0; i < funcCount; i++) {
3266 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3267 mCacheDiff);
3268 cachedFuncs++;
3269 }
3270 }
3271 return;
3272 }
3273
3274 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003275 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003276 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003277 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003278 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003279 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003280 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3281 E = mExportFuncs.end();
3282 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003283 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003284 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003285 }
3286 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003287
3288 return;
3289 }
3290
Zonr Chang932648d2010-10-13 22:23:56 +08003291 // Interface for bccGetPragmas()
3292 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003293 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003294 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003295 int stringCount;
3296 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3297 if (actualStringCount)
3298 *actualStringCount = 0; // XXX
3299 return;
3300 }
3301
3302 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003303
Zonr Chang932648d2010-10-13 22:23:56 +08003304 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003305 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003306 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003307 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003308 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003309 for (PragmaList::const_iterator it = mPragmas.begin();
3310 stringCount > 0;
3311 stringCount -= 2, it++) {
3312 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3313 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003314 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003315 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003316
3317 return;
3318 }
3319
Zonr Chang932648d2010-10-13 22:23:56 +08003320 // Interface for bccGetFunctions()
3321 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003322 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003323 BCCchar **functions) {
3324 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003325 mCodeEmitter->getFunctionNames(actualFunctionCount,
3326 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003327 functions);
3328 else
3329 *actualFunctionCount = 0;
3330
3331 return;
3332 }
3333
Zonr Chang932648d2010-10-13 22:23:56 +08003334 // Interface for bccGetFunctionBinary()
3335 void getFunctionBinary(BCCchar *function,
3336 BCCvoid **base,
3337 BCCsizei *length) {
3338 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003339 mCodeEmitter->getFunctionBinary(function, base, length);
3340 } else {
3341 *base = NULL;
3342 *length = 0;
3343 }
3344 return;
3345 }
3346
Zonr Chang932648d2010-10-13 22:23:56 +08003347 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003348 return mModule;
3349 }
3350
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003351 ~Compiler() {
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003352 if (!mCodeMemMgr.get()) {
3353 // mCodeDataAddr and mCacheMapAddr are from loader and not
3354 // managed by CodeMemoryManager.
3355
3356 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3357 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3358 LOGE("munmap failed while releasing mCodeDataAddr\n");
3359 }
3360
3361 mCodeDataAddr = 0;
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003362 }
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003363
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003364 if (mCacheMapAddr) {
3365 free(mCacheMapAddr);
Shih-wei Liao0ea73a82010-11-23 00:40:28 -08003366 mCacheMapAddr = 0;
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003367 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003368 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003369
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003370 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003371 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003372 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003373 return;
3374 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003375
3376 private:
3377 // Note: loader() and genCacheFile() go hand in hand
3378 void genCacheFile() {
3379 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3380 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3381 return;
3382 }
3383
3384 bool codeOffsetNeedPadding = false;
3385
3386 uint32_t offset = sizeof(oBCCHeader);
3387
3388 // BCC Cache File Header
3389 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3390
3391 if (!hdr) {
3392 LOGE("Unable to allocate oBCCHeader.\n");
3393 return;
3394 }
3395
3396 // Magic Words
3397 memcpy(hdr->magic, OBCC_MAGIC, 4);
3398 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3399
3400 // Timestamp
3401 hdr->sourceWhen = 0; // TODO(all)
3402 hdr->rslibWhen = 0; // TODO(all)
3403 hdr->libRSWhen = 0; // TODO(all)
3404 hdr->libbccWhen = 0; // TODO(all)
3405
3406 // Current Memory Address (Saved for Recalculation)
3407 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3408 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3409 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3410
3411 // Relocation Table Offset and Entry Count
3412 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003413 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003414
Logan824dd0a2010-11-20 01:45:54 +08003415 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003416
3417 // Export Variable Table Offset and Entry Count
3418 hdr->exportVarsOffset = offset;
3419 hdr->exportVarsCount = mExportVars.size();
3420
3421 offset += hdr->exportVarsCount * sizeof(uint32_t);
3422
3423 // Export Function Table Offset and Entry Count
3424 hdr->exportFuncsOffset = offset;
3425 hdr->exportFuncsCount = mExportFuncs.size();
3426
3427 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3428
3429 // Export Pragmas Table Offset and Entry Count
3430 hdr->exportPragmasOffset = offset;
3431 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3432
3433 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3434
3435 // Code Offset and Size
3436
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003437 //#ifdef BCC_CODE_ADDR
3438 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003439 long pagesize = sysconf(_SC_PAGESIZE);
3440
3441 if (offset % pagesize > 0) {
3442 codeOffsetNeedPadding = true;
3443 offset += pagesize - (offset % pagesize);
3444 }
3445 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003446 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003447 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3448 codeOffsetNeedPadding = true;
3449 offset += 0x08 - (offset & 0x07);
3450 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003451 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003452
3453 hdr->codeOffset = offset;
3454 hdr->codeSize = MaxCodeSize;
3455
3456 offset += hdr->codeSize;
3457
3458 // Data (Global Variable) Offset and Size
3459 hdr->dataOffset = offset;
3460 hdr->dataSize = MaxGlobalVarSize;
3461
3462 offset += hdr->dataSize;
3463
3464 // Checksum
3465 hdr->checksum = 0; // Set Field checksum. TODO(all)
3466
3467 // Write Header
3468 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3469 sizeof(oBCCHeader), "Write oBCC header");
3470
Logan824dd0a2010-11-20 01:45:54 +08003471 // Write Relocation Entry Table
3472 {
3473 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003474
Logan824dd0a2010-11-20 01:45:54 +08003475 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3476
3477 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3478 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003479 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003480
3481 // Write Export Variables Table
3482 {
3483 uint32_t *record, *ptr;
3484
3485 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3486 ptr = record;
3487
3488 if (!record) {
3489 goto bail;
3490 }
3491
3492 for (ExportVarList::const_iterator I = mExportVars.begin(),
3493 E = mExportVars.end(); I != E; I++) {
3494 *ptr++ = reinterpret_cast<uint32_t>(*I);
3495 }
3496
3497 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3498 hdr->exportVarsCount * sizeof(uint32_t),
3499 "Write ExportVars");
3500
3501 free(record);
3502 }
3503
3504 // Write Export Functions Table
3505 {
3506 uint32_t *record, *ptr;
3507
3508 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3509 ptr = record;
3510
3511 if (!record) {
3512 goto bail;
3513 }
3514
3515 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3516 E = mExportFuncs.end(); I != E; I++) {
3517 *ptr++ = reinterpret_cast<uint32_t>(*I);
3518 }
3519
3520 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3521 hdr->exportFuncsCount * sizeof(uint32_t),
3522 "Write ExportFuncs");
3523
3524 free(record);
3525 }
3526
3527
3528 // TODO(all): Write Export Pragmas Table
3529#if 0
3530#else
3531 // Note: As long as we have comment out export pragmas table code,
3532 // we have to seek the position to correct offset.
3533
3534 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3535#endif
3536
3537 if (codeOffsetNeedPadding) {
3538 // requires additional padding
3539 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3540 }
3541
3542 // Write Generated Code and Global Variable
3543 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3544 "Write code and global variable");
3545
3546 goto close_return;
3547
3548 bail:
3549 if (ftruncate(mCacheFd, 0) != 0) {
3550 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3551 }
3552
3553 close_return:
3554 free(hdr);
3555 close(mCacheFd);
3556 mCacheFd = -1;
3557 return;
3558 }
3559
3560 // OpenCacheFile() returns fd of the cache file.
3561 // Input:
3562 // BCCchar *resName: Used to genCacheFileName()
3563 // bool createIfMissing: If false, turn off caching
3564 // Output:
3565 // returns fd: If -1: Failed
3566 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3567 // cache file's file descriptor
3568 // Note: openCacheFile() will check the cache file's validity,
3569 // such as Magic number, sourceWhen... dependencies.
3570 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3571 int fd, cc;
3572 struct stat fdStat, fileStat;
3573 bool readOnly = false;
3574
3575 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3576
3577 mCacheNew = false;
3578
3579 retry:
3580 /*
3581 * Try to open the cache file. If we've been asked to,
3582 * create it if it doesn't exist.
3583 */
3584 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3585 if (fd < 0) {
3586 fd = open(cacheFileName, O_RDONLY, 0);
3587 if (fd < 0) {
3588 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08003589 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003590 cacheFileName, strerror(errno));
Shih-wei Liao30a51502010-11-22 03:23:30 -08003591 mNeverCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003592 }
3593 return fd;
3594 }
3595 readOnly = true;
3596 }
3597
3598 /*
3599 * Grab an exclusive lock on the cache file. If somebody else is
3600 * working on it, we'll block here until they complete.
3601 */
3602 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3603 cacheFileName, fd);
3604
3605 cc = flock(fd, LOCK_EX | LOCK_NB);
3606 if (cc != 0) {
3607 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3608 cc = flock(fd, LOCK_EX);
3609 }
3610
3611 if (cc != 0) {
3612 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3613 close(fd);
3614 return -1;
3615 }
3616 LOGV("bcc: locked cache file\n");
3617
3618 /*
3619 * Check to see if the fd we opened and locked matches the file in
3620 * the filesystem. If they don't, then somebody else unlinked ours
3621 * and created a new file, and we need to use that one instead. (If
3622 * we caught them between the unlink and the create, we'll get an
3623 * ENOENT from the file stat.)
3624 */
3625 cc = fstat(fd, &fdStat);
3626 if (cc != 0) {
3627 LOGE("Can't stat open file '%s'\n", cacheFileName);
3628 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3629 goto close_fail;
3630 }
3631 cc = stat(cacheFileName, &fileStat);
3632 if (cc != 0 ||
3633 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3634 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3635 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3636 flock(fd, LOCK_UN);
3637 close(fd);
3638 usleep(250 * 1000); // if something is hosed, don't peg machine
3639 goto retry;
3640 }
3641
3642 /*
3643 * We have the correct file open and locked. If the file size is zero,
3644 * then it was just created by us, and we want to fill in some fields
3645 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3646 * verify that the fields in the header match our expectations, and
3647 * reset the file if they don't.
3648 */
3649 if (fdStat.st_size == 0) {
3650 if (readOnly) { // The device is readOnly --> close_fail
3651 LOGW("bcc: file has zero length and isn't writable\n");
3652 goto close_fail;
3653 }
3654 /*cc = createEmptyHeader(fd);
3655 if (cc != 0)
3656 goto close_fail;
3657 */
3658 mCacheNew = true;
3659 LOGV("bcc: successfully initialized new cache file\n");
3660 } else {
3661 // Calculate sourceWhen
3662 // XXX
3663 uint32_t sourceWhen = 0;
3664 uint32_t rslibWhen = 0;
3665 uint32_t libRSWhen = 0;
3666 uint32_t libbccWhen = 0;
3667 if (!checkHeaderAndDependencies(fd,
3668 sourceWhen,
3669 rslibWhen,
3670 libRSWhen,
3671 libbccWhen)) {
3672 // If checkHeaderAndDependencies returns 0: FAILED
3673 // Will truncate the file and retry to createIfMissing the file
3674
3675 if (readOnly) { // Shouldn't be readonly.
3676 /*
3677 * We could unlink and rewrite the file if we own it or
3678 * the "sticky" bit isn't set on the directory. However,
3679 * we're not able to truncate it, which spoils things. So,
3680 * give up now.
3681 */
3682 if (createIfMissing) {
3683 LOGW("Cached file %s is stale and not writable\n",
3684 cacheFileName);
3685 }
3686 goto close_fail;
3687 }
3688
3689 /*
3690 * If we truncate the existing file before unlinking it, any
3691 * process that has it mapped will fail when it tries to touch
3692 * the pages? Probably OK because we use MAP_PRIVATE.
3693 */
3694 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3695 cacheFileName);
3696 if (ftruncate(fd, 0) != 0) {
3697 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3698 cacheFileName, strerror(errno));
3699 /* keep going */
3700 }
3701 if (unlink(cacheFileName) != 0) {
3702 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3703 cacheFileName, errno, strerror(errno));
3704 /* keep going; permission failure should probably be fatal */
3705 }
3706 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3707 flock(fd, LOCK_UN);
3708 close(fd);
3709 goto retry;
3710 } else {
3711 // Got cacheFile! Good to go.
3712 LOGV("Good cache file\n");
3713 }
3714 }
3715
3716 assert(fd >= 0);
3717 return fd;
3718
3719 close_fail:
3720 flock(fd, LOCK_UN);
3721 close(fd);
3722 return -1;
3723 } // End of openCacheFile()
3724
3725 char *genCacheFileName(const char *fileName, const char *subFileName) {
3726 char nameBuf[512];
3727 static const char kCachePath[] = "bcc-cache";
3728 char absoluteFile[sizeof(nameBuf)];
3729 const size_t kBufLen = sizeof(nameBuf) - 1;
3730 const char *dataRoot;
3731 char *cp;
3732
3733 // Get the absolute path of the raw/***.bc file.
3734 absoluteFile[0] = '\0';
3735 if (fileName[0] != '/') {
3736 /*
3737 * Generate the absolute path. This doesn't do everything it
3738 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3739 * the leading "./" out, but it'll do.
3740 */
3741 if (getcwd(absoluteFile, kBufLen) == NULL) {
3742 LOGE("Can't get CWD while opening raw/***.bc file\n");
3743 return NULL;
3744 }
3745 // TODO(srhines): strncat() is a bit dangerous
3746 strncat(absoluteFile, "/", kBufLen);
3747 }
3748 strncat(absoluteFile, fileName, kBufLen);
3749
3750 if (subFileName != NULL) {
3751 strncat(absoluteFile, "/", kBufLen);
3752 strncat(absoluteFile, subFileName, kBufLen);
3753 }
3754
3755 /* Turn the path into a flat filename by replacing
3756 * any slashes after the first one with '@' characters.
3757 */
3758 cp = absoluteFile + 1;
3759 while (*cp != '\0') {
3760 if (*cp == '/') {
3761 *cp = '@';
3762 }
3763 cp++;
3764 }
3765
3766 /* Build the name of the cache directory.
3767 */
3768 dataRoot = getenv("ANDROID_DATA");
3769 if (dataRoot == NULL)
3770 dataRoot = "/data";
3771 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3772
3773 /* Tack on the file name for the actual cache file path.
3774 */
3775 strncat(nameBuf, absoluteFile, kBufLen);
3776
3777 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3778 return strdup(nameBuf);
3779 }
3780
3781 /*
3782 * Read the oBCC header, verify it, then read the dependent section
3783 * and verify that data as well.
3784 *
3785 * On successful return, the file will be seeked immediately past the
3786 * oBCC header.
3787 */
3788 bool checkHeaderAndDependencies(int fd,
3789 uint32_t sourceWhen,
3790 uint32_t rslibWhen,
3791 uint32_t libRSWhen,
3792 uint32_t libbccWhen) {
3793 ssize_t actual;
3794 oBCCHeader optHdr;
3795 uint32_t val;
3796 uint8_t const *magic, *magicVer;
3797
3798 /*
3799 * Start at the start. The "bcc" header, when present, will always be
3800 * the first thing in the file.
3801 */
3802 if (lseek(fd, 0, SEEK_SET) != 0) {
3803 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3804 goto bail;
3805 }
3806
3807 /*
3808 * Read and do trivial verification on the bcc header. The header is
3809 * always in host byte order.
3810 */
3811 actual = read(fd, &optHdr, sizeof(optHdr));
3812 if (actual < 0) {
3813 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3814 goto bail;
3815 } else if (actual != sizeof(optHdr)) {
3816 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3817 (int) actual, sizeof(optHdr));
3818 goto bail;
3819 }
3820
3821 magic = optHdr.magic;
3822 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3823 /* not an oBCC file, or previous attempt was interrupted */
3824 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3825 magic[0], magic[1], magic[2], magic[3]);
3826 goto bail;
3827 }
3828
3829 magicVer = optHdr.magicVersion;
3830 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3831 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3832 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3833 goto bail;
3834 }
3835
3836 /*
3837 * Do the header flags match up with what we want?
3838 *
3839 * This is useful because it allows us to automatically regenerate
3840 * a file when settings change (e.g. verification is now mandatory),
3841 * but can cause difficulties if the thing we depend upon
3842 * were handled differently than the current options specify.
3843 *
3844 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3845 * by limiting the match mask.
3846 *
3847 * The only thing we really can't handle is incorrect byte-ordering.
3848 */
3849
3850 val = optHdr.sourceWhen;
3851 if (val && (val != sourceWhen)) {
3852 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3853 val, sourceWhen);
3854 goto bail;
3855 }
3856 val = optHdr.rslibWhen;
3857 if (val && (val != rslibWhen)) {
3858 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3859 val, rslibWhen);
3860 goto bail;
3861 }
3862 val = optHdr.libRSWhen;
3863 if (val && (val != libRSWhen)) {
3864 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3865 val, libRSWhen);
3866 goto bail;
3867 }
3868 val = optHdr.libbccWhen;
3869 if (val && (val != libbccWhen)) {
3870 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3871 val, libbccWhen);
3872 goto bail;
3873 }
3874
3875 return true;
3876
3877 bail:
3878 return false;
3879 }
3880
Zonr Chang932648d2010-10-13 22:23:56 +08003881};
3882// End of Class Compiler
3883////////////////////////////////////////////////////////////////////////////////
3884
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003885
3886bool Compiler::GlobalInitialized = false;
3887
Loganad7e8e12010-11-22 20:43:43 +08003888bool Compiler::BccCodeAddrTaken = false;
3889
Zonr Chang932648d2010-10-13 22:23:56 +08003890// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003891llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3892
3893std::string Compiler::Triple;
3894
3895std::string Compiler::CPU;
3896
3897std::vector<std::string> Compiler::Features;
3898
Zonr Chang932648d2010-10-13 22:23:56 +08003899// The named of metadata node that pragma resides (should be synced with
3900// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003901const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3902
Zonr Chang932648d2010-10-13 22:23:56 +08003903// The named of metadata node that export variable name resides (should be
3904// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003905const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3906
Zonr Chang932648d2010-10-13 22:23:56 +08003907// The named of metadata node that export function name resides (should be
3908// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003909const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3910
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003911struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003912 //////////////////////////////////////////////////////////////////////////////
3913 // Part I. Compiler
3914 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003915 Compiler compiler;
3916
Zonr Chang932648d2010-10-13 22:23:56 +08003917 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003918 compiler.registerSymbolCallback(pFn, pContext);
3919 }
3920
Zonr Chang932648d2010-10-13 22:23:56 +08003921 //////////////////////////////////////////////////////////////////////////////
3922 // Part II. Logistics & Error handling
3923 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003924 BCCscript() {
3925 bccError = BCC_NO_ERROR;
3926 }
3927
3928 ~BCCscript() {
3929 }
3930
3931 void setError(BCCenum error) {
3932 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3933 bccError = error;
3934 }
3935 }
3936
3937 BCCenum getError() {
3938 BCCenum result = bccError;
3939 bccError = BCC_NO_ERROR;
3940 return result;
3941 }
3942
3943 BCCenum bccError;
3944};
3945
3946
3947extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003948BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003949 return new BCCscript();
3950}
3951
3952extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003953BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003954 return script->getError();
3955}
3956
3957extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003958void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003959 delete script;
3960}
3961
3962extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003963void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003964 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08003965 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003966 script->registerSymbolCallback(pFn, pContext);
3967}
3968
3969extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003970int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08003971 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003972 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08003973}
3974
3975extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003976int bccReadBC(BCCscript *script,
3977 const BCCchar *bitcode,
3978 BCCint size,
3979 const BCCchar *resName) {
3980 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003981}
3982
3983extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003984void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08003985 const BCCchar *bitcode,
3986 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003987 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08003988}
3989
3990extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003991void bccLoadBinary(BCCscript *script) {
3992 int result = script->compiler.loader();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003993 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003994 script->setError(BCC_INVALID_OPERATION);
3995}
3996
3997extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003998void bccCompileBC(BCCscript *script) {
3999 {
4000#if defined(__arm__)
4001 android::StopWatch compileTimer("RenderScript compile time");
4002#endif
4003 int result = script->compiler.compile();
4004 if (result)
4005 script->setError(BCC_INVALID_OPERATION);
4006 }
4007}
4008
4009extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004010void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004011 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08004012 BCCsizei *length,
4013 BCCchar *infoLog) {
4014 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004015 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004016 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004017 *length = messageLength;
4018
4019 if (infoLog && maxLength > 0) {
4020 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4021 memcpy(infoLog, message, trimmedLength);
4022 infoLog[trimmedLength] = 0;
4023 }
4024}
4025
4026extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004027void bccGetScriptLabel(BCCscript *script,
4028 const BCCchar *name,
4029 BCCvoid **address) {
4030 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004031 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004032 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004033 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004034 script->setError(BCC_INVALID_VALUE);
4035}
4036
4037extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004038void bccGetExportVars(BCCscript *script,
4039 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004040 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004041 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004042 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4043}
4044
4045extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004046void bccGetExportFuncs(BCCscript *script,
4047 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004048 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004049 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004050 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4051}
4052
4053extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004054void bccGetPragmas(BCCscript *script,
4055 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004056 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004057 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004058 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4059}
4060
4061extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004062void bccGetFunctions(BCCscript *script,
4063 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004064 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004065 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004066 script->compiler.getFunctions(actualFunctionCount,
4067 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004068 functions);
4069}
4070
4071extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004072void bccGetFunctionBinary(BCCscript *script,
4073 BCCchar *function,
4074 BCCvoid **base,
4075 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004076 script->compiler.getFunctionBinary(function, base, length);
4077}
4078
4079struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004080 const Compiler *compiler;
4081 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004082};
4083
Zonr Chang932648d2010-10-13 22:23:56 +08004084} // namespace bcc