blob: 820c1847a94f2d35e7a2468e4aa87043e199a7a9 [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 Liao3d77c422010-11-21 19:51:59 -080020// Fixed BCC_CODE_ADDR here only works for 1 cached EXE.
Shih-wei Liao1f45b862010-11-21 23:22:38 -080021// At most 1 live Compiler object will have set mBccCodeAddrTaken
Shih-wei Liao3d77c422010-11-21 19:51:59 -080022#define BCC_CODE_ADDR 0x7e00000
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080023
Shih-wei Liao77ed6142010-04-07 12:21:42 -070024#define LOG_TAG "bcc"
25#include <cutils/log.h>
26
27#include <ctype.h>
28#include <errno.h>
29#include <limits.h>
30#include <stdarg.h>
31#include <stdint.h>
32#include <stdio.h>
33#include <stdlib.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080034#include <stddef.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070035#include <string.h>
36#include <unistd.h>
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -070037#include <sys/mman.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080038#include <sys/file.h>
39#include <sys/stat.h>
40#include <sys/types.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070041
42#include <cutils/hashmap.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080043#include <utils/StopWatch.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070044
Shih-wei Liao77ed6142010-04-07 12:21:42 -070045#if defined(__arm__)
Zonr Chang932648d2010-10-13 22:23:56 +080046# define DEFAULT_ARM_CODEGEN
47# define PROVIDE_ARM_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070048#elif defined(__i386__)
Zonr Chang932648d2010-10-13 22:23:56 +080049# define DEFAULT_X86_CODEGEN
50# define PROVIDE_X86_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070051#elif defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +080052# define DEFAULT_X64_CODEGEN
53# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070054#endif
55
56#if defined(FORCE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080057# define DEFAULT_ARM_CODEGEN
58# undef DEFAULT_X86_CODEGEN
59# undef DEFAULT_X64_CODEGEN
60# define PROVIDE_ARM_CODEGEN
61# undef PROVIDE_X86_CODEGEN
62# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070063#elif defined(FORCE_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080064# undef DEFAULT_ARM_CODEGEN
65# define DEFAULT_X86_CODEGEN
66# undef DEFAULT_X64_CODEGEN
67# undef PROVIDE_ARM_CODEGEN
68# define PROVIDE_X86_CODEGEN
69# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070070#elif defined(FORCE_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080071# undef DEFAULT_ARM_CODEGEN
72# undef DEFAULT_X86_CODEGEN
73# define DEFAULT_X64_CODEGEN
74# undef PROVIDE_ARM_CODEGEN
75# undef PROVIDE_X86_CODEGEN
76# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070077#endif
78
79#if defined(DEFAULT_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080080# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070081#elif defined(DEFAULT_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080082# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070083#elif defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080084# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070085#endif
86
87#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
Zonr Chang932648d2010-10-13 22:23:56 +080088# define ARM_USE_VFP
Shih-wei Liao77ed6142010-04-07 12:21:42 -070089#endif
90
91#include <bcc/bcc.h>
92#include "bcc_runtime.h"
93
Zonr Chang932648d2010-10-13 22:23:56 +080094#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070095// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
96
Zonr Chang932648d2010-10-13 22:23:56 +080097#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070098// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
99
100// #define PROVIDE_TRACE_CODEGEN
101
102#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +0800103# include "llvm/MC/MCInst.h"
104# include "llvm/MC/MCAsmInfo.h"
105# include "llvm/MC/MCInstPrinter.h"
106# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700107// If you want the disassemble results written to file, define this:
108# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700109#endif
110
111#include <set>
112#include <map>
113#include <list>
114#include <cmath>
115#include <string>
116#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800117#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700118
Zonr Chang932648d2010-10-13 22:23:56 +0800119// VMCore
120#include "llvm/Use.h"
121#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800122#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800123#include "llvm/Module.h"
124#include "llvm/Function.h"
125#include "llvm/Constant.h"
126#include "llvm/Constants.h"
127#include "llvm/Instruction.h"
128#include "llvm/PassManager.h"
129#include "llvm/LLVMContext.h"
130#include "llvm/GlobalValue.h"
131#include "llvm/Instructions.h"
132#include "llvm/OperandTraits.h"
133#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700134
135// System
Zonr Chang932648d2010-10-13 22:23:56 +0800136#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700137
138// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800139#include "llvm/ADT/APInt.h"
140#include "llvm/ADT/APFloat.h"
141#include "llvm/ADT/DenseMap.h"
142#include "llvm/ADT/ValueMap.h"
143#include "llvm/ADT/StringMap.h"
144#include "llvm/ADT/OwningPtr.h"
145#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700146
147// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800148#include "llvm/Target/TargetData.h"
149#include "llvm/Target/TargetSelect.h"
150#include "llvm/Target/TargetOptions.h"
151#include "llvm/Target/TargetMachine.h"
152#include "llvm/Target/TargetJITInfo.h"
153#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700154#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700155
156// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800157#include "llvm/Support/Casting.h"
158#include "llvm/Support/raw_ostream.h"
159#include "llvm/Support/ValueHandle.h"
160#include "llvm/Support/MemoryBuffer.h"
161#include "llvm/Support/MemoryObject.h"
162#include "llvm/Support/ManagedStatic.h"
163#include "llvm/Support/ErrorHandling.h"
164#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700165#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700166
167// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800168#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700169
170// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800171#include "llvm/CodeGen/Passes.h"
172#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700173#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700174#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700175#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700176#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700177#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700178#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700179#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700180#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700181
182// ExecutionEngine
183#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700184#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700185
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700186extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700187
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800188// For caching
189struct oBCCHeader {
190 uint8_t magic[4]; // includes version number
191 uint8_t magicVersion[4];
192
193 uint32_t sourceWhen;
194 uint32_t rslibWhen;
195 uint32_t libRSWhen;
196 uint32_t libbccWhen;
197
198 uint32_t cachedCodeDataAddr;
199 uint32_t rootAddr;
200 uint32_t initAddr;
201
202 uint32_t relocOffset; // offset of reloc table.
203 uint32_t relocCount;
204 uint32_t exportVarsOffset; // offset of export var table
205 uint32_t exportVarsCount;
206 uint32_t exportFuncsOffset; // offset of export func table
207 uint32_t exportFuncsCount;
208 uint32_t exportPragmasOffset; // offset of export pragma table
209 uint32_t exportPragmasCount;
210
211 uint32_t codeOffset; // offset of code: 64-bit alignment
212 uint32_t codeSize;
213 uint32_t dataOffset; // offset of data section
214 uint32_t dataSize;
215
216 // uint32_t flags; // some info flags
217 uint32_t checksum; // adler32 checksum covering deps/opt
218};
219
Logan824dd0a2010-11-20 01:45:54 +0800220struct oBCCRelocEntry {
221 uint32_t relocType; // target instruction relocation type
222 uint32_t relocOffset; // offset of hole (holeAddr - codeAddr)
223 uint32_t cachedResultAddr; // address resolved at compile time
224
Logan634bd832010-11-20 09:00:36 +0800225 oBCCRelocEntry(uint32_t ty, uintptr_t off, void *addr)
Logan824dd0a2010-11-20 01:45:54 +0800226 : relocType(ty),
227 relocOffset(static_cast<uint32_t>(off)),
228 cachedResultAddr(reinterpret_cast<uint32_t>(addr)) {
229 }
230};
231
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800232/* oBCCHeader Offset Table */
233#define k_magic offsetof(oBCCHeader, magic)
234#define k_magicVersion offsetof(oBCCHeader, magicVersion)
235#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
236#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
237#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
238#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
239#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
240#define k_rootAddr offsetof(oBCCHeader, rootAddr)
241#define k_initAddr offsetof(oBCCHeader, initAddr)
242#define k_relocOffset offsetof(oBCCHeader, relocOffset)
243#define k_relocCount offsetof(oBCCHeader, relocCount)
244#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
245#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
246#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
247#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
248#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
249#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
250#define k_codeOffset offsetof(oBCCHeader, codeOffset)
251#define k_codeSize offsetof(oBCCHeader, codeSize)
252#define k_dataOffset offsetof(oBCCHeader, dataOffset)
253#define k_dataSize offsetof(oBCCHeader, dataSize)
254#define k_checksum offsetof(oBCCHeader, checksum)
255
256/* oBCC file magic number */
257#define OBCC_MAGIC "bcc\n"
258/* version, encoded in 4 bytes of ASCII */
259#define OBCC_MAGIC_VERS "001\0"
260
261#define TEMP_FAILURE_RETRY1(exp) ({ \
262 typeof (exp) _rc; \
263 do { \
264 _rc = (exp); \
265 } while (_rc == -1 && errno == EINTR); \
266 _rc; })
267
268static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
269{
270 while (count != 0) {
271 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
272 if (actual < 0) {
273 int err = errno;
274 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
275 return err;
276 } else if (actual != (ssize_t) count) {
277 LOGD("%s: partial write (will retry): (%d of %zd)\n",
278 logMsg, (int) actual, count);
279 buf = (const void*) (((const uint8_t*) buf) + actual);
280 }
281 count -= actual;
282 }
283
284 return 0;
285}
286
Zonr Chang932648d2010-10-13 22:23:56 +0800287//
288// Compilation class that suits Android's needs.
289// (Support: no argument passed, ...)
290//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700291namespace bcc {
292
293class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800294 // This part is designed to be orthogonal to those exported bcc*() functions
295 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700296
Zonr Chang932648d2010-10-13 22:23:56 +0800297 //////////////////////////////////////////////////////////////////////////////
298 // The variable section below (e.g., Triple, CodeGenOptLevel)
299 // is initialized in GlobalInitialization()
300 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700301 static bool GlobalInitialized;
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800302 //sliao static bool BccCodeAddrTaken;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700303
Zonr Chang932648d2010-10-13 22:23:56 +0800304 // If given, this will be the name of the target triple to compile for.
305 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700306 static std::string Triple;
307
308 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700309
Zonr Chang932648d2010-10-13 22:23:56 +0800310 // End of section of GlobalInitializing variables
311 //////////////////////////////////////////////////////////////////////////////
312
313 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700314 static std::string CPU;
315
Zonr Chang932648d2010-10-13 22:23:56 +0800316 // The list of target specific features to enable or disable -- this should
317 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700318 static std::vector<std::string> Features;
319
320 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800321 const char *mName;
322 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700323 };
324 static struct Runtime Runtimes[];
325
326 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800327 if (GlobalInitialized)
328 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700329
Zonr Chang932648d2010-10-13 22:23:56 +0800330 // if (!llvm::llvm_is_multithreaded())
331 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700332
Zonr Chang932648d2010-10-13 22:23:56 +0800333 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700334 Triple = TARGET_TRIPLE_STRING;
335
Zonr Chang932648d2010-10-13 22:23:56 +0800336 // TODO(zonr): NEON for JIT
337 // Features.push_back("+neon");
338 // Features.push_back("+vmlx");
339 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700340 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700341 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700342
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700343#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
344 LLVMInitializeARMTargetInfo();
345 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700346#if defined(USE_DISASSEMBLER)
347 LLVMInitializeARMDisassembler();
348 LLVMInitializeARMAsmPrinter();
349#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700350#endif
351
352#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
353 LLVMInitializeX86TargetInfo();
354 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700355#if defined(USE_DISASSEMBLER)
356 LLVMInitializeX86Disassembler();
357 LLVMInitializeX86AsmPrinter();
358#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700359#endif
360
361#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
362 LLVMInitializeX86TargetInfo();
363 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700364#if defined(USE_DISASSEMBLER)
365 LLVMInitializeX86Disassembler();
366 LLVMInitializeX86AsmPrinter();
367#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700368#endif
369
Zonr Chang932648d2010-10-13 22:23:56 +0800370 // -O0: llvm::CodeGenOpt::None
371 // -O1: llvm::CodeGenOpt::Less
372 // -O2: llvm::CodeGenOpt::Default
373 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700374 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700375
Zonr Chang932648d2010-10-13 22:23:56 +0800376 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700377
Zonr Chang932648d2010-10-13 22:23:56 +0800378 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700379 llvm::NoFramePointerElim = false;
380
Zonr Chang932648d2010-10-13 22:23:56 +0800381 // Use hardfloat ABI
382 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800383 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800384 // softfp. To use softfp, change following 2 lines to
385 //
386 // llvm::FloatABIType = llvm::FloatABI::Soft;
387 // llvm::UseSoftFloat = true;
388 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700389 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700390 llvm::UseSoftFloat = false;
391
Zonr Chang932648d2010-10-13 22:23:56 +0800392 // BCC needs all unknown symbols resolved at JIT/compilation time.
393 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700394 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
395
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700396#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800397 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700398 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
399#else
Zonr Chang932648d2010-10-13 22:23:56 +0800400 // This is set for the linker (specify how large of the virtual addresses
401 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700402 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
403#endif
404
Zonr Chang932648d2010-10-13 22:23:56 +0800405 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700406 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
407
Zonr Chang932648d2010-10-13 22:23:56 +0800408 // Register allocation policy:
409 // createFastRegisterAllocator: fast but bad quality
410 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700411 llvm::RegisterRegAlloc::setDefault
412 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700413 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700414 llvm::createLinearScanRegisterAllocator);
415
416 GlobalInitialized = true;
417 return;
418 }
419
420 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800421 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700422 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700423 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800424 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700425 }
426
427 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700428 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700429 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700430
431 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700432 std::string mError;
433
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700434 inline bool hasError() const {
435 return !mError.empty();
436 }
Zonr Chang932648d2010-10-13 22:23:56 +0800437 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700438 mError.assign(Error); // Copying
439 return;
440 }
Zonr Chang932648d2010-10-13 22:23:56 +0800441 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700442 mError = Error;
443 return;
444 }
445
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800446 bool mNeverCache; // Set by readBC()
447 bool mCacheNew; // Set by readBC()
448 int mCacheFd; // Set by readBC()
449 char *mCacheMapAddr; // Set by loader() if mCacheNew is false
450 oBCCHeader *mCacheHdr; // Set by loader()
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800451 size_t mCacheSize; // Set by loader()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800452 ptrdiff_t mCacheDiff; // Set by loader()
453 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
454 // Used by genCacheFile() for dumping
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800455 bool mBccCodeAddrTaken;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800456
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700457 typedef std::list< std::pair<std::string, std::string> > PragmaList;
458 PragmaList mPragmas;
459
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700460 typedef std::list<void*> ExportVarList;
461 ExportVarList mExportVars;
462
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700463 typedef std::list<void*> ExportFuncList;
464 ExportFuncList mExportFuncs;
465
Zonr Chang932648d2010-10-13 22:23:56 +0800466 //////////////////////////////////////////////////////////////////////////////
467 // Memory manager for the code reside in memory
468 //
469 // The memory for our code emitter is very simple and is conforming to the
470 // design decisions of Android RenderScript's Exection Environment:
471 // The code, data, and symbol sizes are limited (currently 100KB.)
472 //
473 // It's very different from typical compiler, which has no limitation
474 // on the code size. How does code emitter know the size of the code
475 // it is about to emit? It does not know beforehand. We want to solve
476 // this without complicating the code emitter too much.
477 //
478 // We solve this by pre-allocating a certain amount of memory,
479 // and then start the code emission. Once the buffer overflows, the emitter
480 // simply discards all the subsequent emission but still has a counter
481 // on how many bytes have been emitted.
482 //
483 // So once the whole emission is done, if there's a buffer overflow,
484 // it re-allocates the buffer with enough size (based on the
485 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800486
487 // 128 KiB for code
488 static const unsigned int MaxCodeSize = 128 * 1024;
489 // 1 KiB for global offset table (GOT)
490 static const unsigned int MaxGOTSize = 1 * 1024;
491 // 128 KiB for global variable
492 static const unsigned int MaxGlobalVarSize = 128 * 1024;
493
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700494 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700495 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800496 //
497 // Our memory layout is as follows:
498 //
499 // The direction of arrows (-> and <-) shows memory's growth direction
500 // when more space is needed.
501 //
502 // @mpCodeMem:
503 // +--------------------------------------------------------------+
504 // | Function Memory ... -> <- ... Stub/GOT |
505 // +--------------------------------------------------------------+
506 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
507 //
508 // Where size of GOT is @MaxGOTSize KiB.
509 //
510 // @mpGVMem:
511 // +--------------------------------------------------------------+
512 // | Global variable ... -> |
513 // +--------------------------------------------------------------+
514 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
515 //
516 //
517 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
518 // of function code's memory usage
519 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
520 // of stub/GOT's memory usage
521 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
522 // of global variable's memory usage
523 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700524 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700525 uintptr_t mCurSGMemIdx;
526 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800527 void *mpCodeMem;
528 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700529
Zonr Chang932648d2010-10-13 22:23:56 +0800530 // GOT Base
531 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700532
533 typedef std::map<const llvm::Function*, pair<void* /* start address */,
534 void* /* end address */>
535 > FunctionMapTy;
536 FunctionMapTy mFunctionMap;
537
Zonr Chang932648d2010-10-13 22:23:56 +0800538 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700539 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700540 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700541
Zonr Chang932648d2010-10-13 22:23:56 +0800542 uint8_t *allocateSGMemory(uintptr_t Size,
543 unsigned Alignment = 1 /* no alignment */) {
544 intptr_t FreeMemSize = getFreeCodeMemSize();
545 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
546 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700547 return NULL;
548
Zonr Chang932648d2010-10-13 22:23:56 +0800549 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700550 Alignment = 1;
551
Zonr Chang932648d2010-10-13 22:23:56 +0800552 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700553 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
554
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700555 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700556
557 return result;
558 }
559
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700560 inline uintptr_t getFreeGVMemSize() const {
561 return MaxGlobalVarSize - mCurGVMemIdx;
562 }
Zonr Chang932648d2010-10-13 22:23:56 +0800563 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700564 return reinterpret_cast<uint8_t*>(mpGVMem);
565 }
566
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700567 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700568 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700569 reset();
570 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700571
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800572 // if (!Compiler::BccCodeAddrTaken) { // Use BCC_CODE_ADDR
Shih-wei Liao30a51502010-11-22 03:23:30 -0800573 /* TODO(sliao):
574 mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800575 MaxCodeSize + MaxGlobalVarSize,
576 PROT_READ | PROT_EXEC | PROT_WRITE,
577 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
578 -1,
579 0);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800580
Shih-wei Liao30a51502010-11-22 03:23:30 -0800581 if (mpCodeMem == MAP_FAILED) {*/
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800582 mpCodeMem = mmap(NULL,
583 MaxCodeSize + MaxGlobalVarSize,
584 PROT_READ | PROT_EXEC | PROT_WRITE,
585 MAP_PRIVATE | MAP_ANON,
586 -1,
587 0);
Shih-wei Liao30a51502010-11-22 03:23:30 -0800588 // } else {
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800589 // mBccCodeAddrTaken = true;
Shih-wei Liao30a51502010-11-22 03:23:30 -0800590 //}
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800591
592 if (mpCodeMem == MAP_FAILED) {
593 llvm::report_fatal_error("Failed to allocate memory for emitting "
594 "codes\n" + ErrMsg);
595 }
596 mpGVMem = (void *) ((int) mpCodeMem + MaxCodeSize);
597
598 /* mpCodeMem = mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700599 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700600 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800601 llvm::report_fatal_error("Failed to allocate memory for emitting "
602 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700603
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800604 mpGVMem = mmap(mpCodeMem, MaxGlobalVarSize,
605 PROT_READ | PROT_WRITE,
606 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700607 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800608 llvm::report_fatal_error("Failed to allocate memory for emitting "
609 "global variables\n" + ErrMsg);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800610 */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700611 return;
612 }
613
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800614 inline uint8_t *getCodeMemBase() const {
615 return reinterpret_cast<uint8_t*>(mpCodeMem);
616 }
617
Zonr Chang932648d2010-10-13 22:23:56 +0800618 // setMemoryWritable - When code generation is in progress, the code pages
619 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700620 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700621 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700622 return;
623 }
624
Zonr Chang932648d2010-10-13 22:23:56 +0800625 // When code generation is done and we're ready to start execution, the
626 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700627 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700628 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700629 return;
630 }
631
Zonr Chang932648d2010-10-13 22:23:56 +0800632 // Setting this flag to true makes the memory manager garbage values over
633 // freed memory. This is useful for testing and debugging, and is to be
634 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700635 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800636 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700637 return;
638 }
639
Zonr Chang932648d2010-10-13 22:23:56 +0800640 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700641
Zonr Chang932648d2010-10-13 22:23:56 +0800642 // If the current table requires a Global Offset Table, this method is
643 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700644 void AllocateGOT() {
645 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700646 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700647 HasGOT = true;
648 return;
649 }
650
Zonr Chang932648d2010-10-13 22:23:56 +0800651 // If this is managing a Global Offset Table, this method should return a
652 // pointer to its base.
653 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700654 return mpGOTBase;
655 }
656
Zonr Chang932648d2010-10-13 22:23:56 +0800657 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700658
Zonr Chang932648d2010-10-13 22:23:56 +0800659 // When we start JITing a function, the JIT calls this method to allocate a
660 // block of free RWX memory, which returns a pointer to it. If the JIT wants
661 // to request a block of memory of at least a certain size, it passes that
662 // value as ActualSize, and this method returns a block with at least that
663 // much space. If the JIT doesn't know ahead of time how much space it will
664 // need to emit the function, it passes 0 for the ActualSize. In either
665 // case, this method is required to pass back the size of the allocated
666 // block through ActualSize. The JIT will be careful to not write more than
667 // the returned ActualSize bytes of memory.
668 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
669 intptr_t FreeMemSize = getFreeCodeMemSize();
670 if ((FreeMemSize < 0) ||
671 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
672 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700673 return NULL;
674
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700675 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700676 return (getCodeMemBase() + mCurFuncMemIdx);
677 }
678
Zonr Chang932648d2010-10-13 22:23:56 +0800679 // This method is called by the JIT to allocate space for a function stub
680 // (used to handle limited branch displacements) while it is JIT compiling a
681 // function. For example, if foo calls bar, and if bar either needs to be
682 // lazily compiled or is a native function that exists too far away from the
683 // call site to work, this method will be used to make a thunk for it. The
684 // stub should be "close" to the current function body, but should not be
685 // included in the 'actualsize' returned by startFunctionBody.
686 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700687 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700688 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700689 }
690
Zonr Chang932648d2010-10-13 22:23:56 +0800691 // This method is called when the JIT is done codegen'ing the specified
692 // function. At this point we know the size of the JIT compiled function.
693 // This passes in FunctionStart (which was returned by the startFunctionBody
694 // method) and FunctionEnd which is a pointer to the actual end of the
695 // function. This method should mark the space allocated and remember where
696 // it is in case the client wants to deallocate it.
697 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
698 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700699 assert(FunctionEnd > FunctionStart);
700 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
701 "Mismatched function start/end!");
702
Zonr Chang932648d2010-10-13 22:23:56 +0800703 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700704 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700705 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700706 "Code size excess the limitation!");
707 mCurFuncMemIdx += FunctionCodeSize;
708
Zonr Chang932648d2010-10-13 22:23:56 +0800709 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700710 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
711 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800712 mFunctionMap.insert(
713 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
714 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700715
716 return;
717 }
718
Zonr Chang932648d2010-10-13 22:23:56 +0800719 // Allocate a (function code) memory block of the given size. This method
720 // cannot be called between calls to startFunctionBody and endFunctionBody.
721 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
722 if (getFreeCodeMemSize() < Size)
723 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700724 return NULL;
725
Zonr Chang932648d2010-10-13 22:23:56 +0800726 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700727 Alignment = 1;
728
Zonr Chang932648d2010-10-13 22:23:56 +0800729 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700730 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800731 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700732
733 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
734
735 return result;
736 }
737
Zonr Chang932648d2010-10-13 22:23:56 +0800738 // Allocate memory for a global variable.
739 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700740 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800741 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700742 LOGE("No Global Memory");
743 return NULL;
744 }
745
Zonr Chang932648d2010-10-13 22:23:56 +0800746 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700747 Alignment = 1;
748
Zonr Chang932648d2010-10-13 22:23:56 +0800749 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700750 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800751 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700752
753 mCurGVMemIdx = (result + Size) - getGVMemBase();
754
755 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700756 }
757
Zonr Chang932648d2010-10-13 22:23:56 +0800758 // Free the specified function body. The argument must be the return value
759 // from a call to startFunctionBody() that hasn't been deallocated yet. This
760 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700761 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800762 // linear search
763 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
764 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
765 E = mFunctionMap.end();
766 I != E;
767 I++)
768 if (I->second.first == Body) {
769 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
770 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700771 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800772 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700773
Zonr Chang932648d2010-10-13 22:23:56 +0800774 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700775
Zonr Chang932648d2010-10-13 22:23:56 +0800776 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700777 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
778
779 assert(SizeNeedMove >= 0 &&
780 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
781 " be correctly calculated!");
782
Zonr Chang932648d2010-10-13 22:23:56 +0800783 if (SizeNeedMove > 0)
784 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700785 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
786 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
787
788 return;
789 }
790
Zonr Chang932648d2010-10-13 22:23:56 +0800791 // When we finished JITing the function, if exception handling is set, we
792 // emit the exception table.
793 uint8_t *startExceptionTable(const llvm::Function *F,
794 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700795 assert(false && "Exception is not allowed in our language specification");
796 return NULL;
797 }
798
Zonr Chang932648d2010-10-13 22:23:56 +0800799 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700800 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800801 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700802 assert(false && "Exception is not allowed in our language specification");
803 return;
804 }
805
Zonr Chang932648d2010-10-13 22:23:56 +0800806 // Free the specified exception table's memory. The argument must be the
807 // return value from a call to startExceptionTable() that hasn't been
808 // deallocated yet. This is never called when the JIT is currently emitting
809 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700810 void deallocateExceptionTable(void *ET) {
811 assert(false && "Exception is not allowed in our language specification");
812 return;
813 }
814
Zonr Chang932648d2010-10-13 22:23:56 +0800815 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700816 void reset() {
817 mpGOTBase = NULL;
818 HasGOT = false;
819
820 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700821 mCurSGMemIdx = MaxCodeSize - 1;
822 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700823
824 mFunctionMap.clear();
825
826 return;
827 }
828
829 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800830 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700831 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800832 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700833 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700834 return;
835 }
Zonr Chang932648d2010-10-13 22:23:56 +0800836 };
837 // End of class CodeMemoryManager
838 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700839
Zonr Chang932648d2010-10-13 22:23:56 +0800840 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700841 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800842 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700843 mCodeMemMgr.reset(new CodeMemoryManager());
844 return mCodeMemMgr.get();
845 }
846
Zonr Chang932648d2010-10-13 22:23:56 +0800847 //////////////////////////////////////////////////////////////////////////////
848 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700849 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700850 public:
851 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
852 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
853
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800854 GlobalAddressMapTy mGlobalAddressMap;
855
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700856 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800857 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700858
Zonr Chang932648d2010-10-13 22:23:56 +0800859 // The JITInfo for the target we are compiling to
860 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700861
Zonr Chang932648d2010-10-13 22:23:56 +0800862 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700863
Zonr Chang932648d2010-10-13 22:23:56 +0800864 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700865
866 class EmittedFunctionCode {
867 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800868 // Beginning of the function's allocation.
869 void *FunctionBody;
870
871 // The address the function's code actually starts at.
872 void *Code;
873
874 // The size of the function code
875 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700876
877 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
878 };
Zonr Chang932648d2010-10-13 22:23:56 +0800879 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700880
Zonr Chang932648d2010-10-13 22:23:56 +0800881 typedef std::map<const std::string,
882 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700883 EmittedFunctionsMapTy mEmittedFunctions;
884
Zonr Chang932648d2010-10-13 22:23:56 +0800885 // This vector is a mapping from MBB ID's to their address. It is filled in
886 // by the StartMachineBasicBlock callback and queried by the
887 // getMachineBasicBlockAddress callback.
888 std::vector<uintptr_t> mMBBLocations;
889
890 // The constant pool for the current function.
891 llvm::MachineConstantPool *mpConstantPool;
892
893 // A pointer to the first entry in the constant pool.
894 void *mpConstantPoolBase;
895
896 // Addresses of individual constant pool entries.
897 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
898
899 // The jump tables for the current function.
900 llvm::MachineJumpTableInfo *mpJumpTable;
901
902 // A pointer to the first entry in the jump table.
903 void *mpJumpTableBase;
904
905 // When outputting a function stub in the context of some other function, we
906 // save BufferBegin/BufferEnd/CurBufferPtr here.
907 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
908
909 // These are the relocations that the function needs, as emitted.
910 std::vector<llvm::MachineRelocation> mRelocations;
911
Logan824dd0a2010-11-20 01:45:54 +0800912 std::vector<oBCCRelocEntry> mCachingRelocations;
913
Zonr Chang932648d2010-10-13 22:23:56 +0800914 // This vector is a mapping from Label ID's to their address.
915 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
916
917 // Machine module info for exception informations
918 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700919
Zonr Chang932648d2010-10-13 22:23:56 +0800920 // Replace an existing mapping for GV with a new address. This updates both
921 // maps as required. If Addr is null, the entry for the global is removed
922 // from the mappings.
923 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
924 if (Addr == NULL) {
925 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700926 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
927 void *OldVal;
928
Zonr Chang932648d2010-10-13 22:23:56 +0800929 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700930 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800931 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700932 OldVal = I->second;
933 mGlobalAddressMap.erase(I);
934 }
935
936 return OldVal;
937 }
938
Zonr Chang932648d2010-10-13 22:23:56 +0800939 void *&CurVal = mGlobalAddressMap[GV];
940 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700941
942 CurVal = Addr;
943
944 return OldVal;
945 }
946
Zonr Chang932648d2010-10-13 22:23:56 +0800947 // Tell the execution engine that the specified global is at the specified
948 // location. This is used internally as functions are JIT'd and as global
949 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700950 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800951 void *&CurVal = mGlobalAddressMap[GV];
952 assert((CurVal == 0 || Addr == 0) &&
953 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700954 CurVal = Addr;
955 return;
956 }
957
Zonr Chang932648d2010-10-13 22:23:56 +0800958 // This returns the address of the specified global value if it is has
959 // already been codegen'd, otherwise it returns null.
960 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700961 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700962 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
963 }
964
Zonr Chang932648d2010-10-13 22:23:56 +0800965 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
966 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700967 MCP->getConstants();
968
Zonr Chang932648d2010-10-13 22:23:56 +0800969 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700970 return 0;
971
972 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800973 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700974 llvm::MachineConstantPoolEntry CPE = Constants[i];
975 unsigned int AlignMask = CPE.getAlignment() - 1;
976 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800977 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700978 Size += mpTD->getTypeAllocSize(Ty);
979 }
980
981 return Size;
982 }
983
Zonr Chang932648d2010-10-13 22:23:56 +0800984 // This function converts a Constant* into a GenericValue. The interesting
985 // part is if C is a ConstantExpr.
986 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
987 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700988 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800989 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
990 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
991 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700992
Zonr Chang932648d2010-10-13 22:23:56 +0800993 switch (CE->getOpcode()) {
994 case llvm::Instruction::GetElementPtr: {
995 // Compute the index
996 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
997 CE->op_end());
998 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
999 &Indices[0],
1000 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001001
Zonr Chang932648d2010-10-13 22:23:56 +08001002 GetConstantValue(Op0, Result);
1003 Result.PointerVal =
1004 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001005
Zonr Chang932648d2010-10-13 22:23:56 +08001006 return;
1007 }
1008 case llvm::Instruction::Trunc: {
1009 uint32_t BitWidth =
1010 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1011
1012 GetConstantValue(Op0, Result);
1013 Result.IntVal = Result.IntVal.trunc(BitWidth);
1014
1015 return;
1016 }
1017 case llvm::Instruction::ZExt: {
1018 uint32_t BitWidth =
1019 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1020
1021 GetConstantValue(Op0, Result);
1022 Result.IntVal = Result.IntVal.zext(BitWidth);
1023
1024 return;
1025 }
1026 case llvm::Instruction::SExt: {
1027 uint32_t BitWidth =
1028 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1029
1030 GetConstantValue(Op0, Result);
1031 Result.IntVal = Result.IntVal.sext(BitWidth);
1032
1033 return;
1034 }
1035 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001036 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001037 GetConstantValue(Op0, Result);
1038 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1039 return;
1040 }
1041 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001042 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001043 GetConstantValue(Op0, Result);
1044 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1045 return;
1046 }
1047 case llvm::Instruction::UIToFP: {
1048 GetConstantValue(Op0, Result);
1049 if (CE->getType()->isFloatTy())
1050 Result.FloatVal =
1051 static_cast<float>(Result.IntVal.roundToDouble());
1052 else if (CE->getType()->isDoubleTy())
1053 Result.DoubleVal = Result.IntVal.roundToDouble();
1054 else if (CE->getType()->isX86_FP80Ty()) {
1055 const uint64_t zero[] = { 0, 0 };
1056 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1057 apf.convertFromAPInt(Result.IntVal,
1058 false,
1059 llvm::APFloat::rmNearestTiesToEven);
1060 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001061 }
Zonr Chang932648d2010-10-13 22:23:56 +08001062 return;
1063 }
1064 case llvm::Instruction::SIToFP: {
1065 GetConstantValue(Op0, Result);
1066 if (CE->getType()->isFloatTy())
1067 Result.FloatVal =
1068 static_cast<float>(Result.IntVal.signedRoundToDouble());
1069 else if (CE->getType()->isDoubleTy())
1070 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1071 else if (CE->getType()->isX86_FP80Ty()) {
1072 const uint64_t zero[] = { 0, 0 };
1073 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1074 apf.convertFromAPInt(Result.IntVal,
1075 true,
1076 llvm::APFloat::rmNearestTiesToEven);
1077 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001078 }
Zonr Chang932648d2010-10-13 22:23:56 +08001079 return;
1080 }
1081 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001082 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001083 case llvm::Instruction::FPToSI: {
1084 uint32_t BitWidth =
1085 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001086
Zonr Chang932648d2010-10-13 22:23:56 +08001087 GetConstantValue(Op0, Result);
1088 if (Op0->getType()->isFloatTy())
1089 Result.IntVal =
1090 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1091 else if (Op0->getType()->isDoubleTy())
1092 Result.IntVal =
1093 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1094 BitWidth);
1095 else if (Op0->getType()->isX86_FP80Ty()) {
1096 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1097 uint64_t V;
1098 bool Ignored;
1099 apf.convertToInteger(&V,
1100 BitWidth,
1101 CE->getOpcode() == llvm::Instruction::FPToSI,
1102 llvm::APFloat::rmTowardZero,
1103 &Ignored);
1104 Result.IntVal = V; // endian?
1105 }
1106 return;
1107 }
1108 case llvm::Instruction::PtrToInt: {
1109 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1110
1111 GetConstantValue(Op0, Result);
1112 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1113 (Result.PointerVal));
1114
1115 return;
1116 }
1117 case llvm::Instruction::IntToPtr: {
1118 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1119
1120 GetConstantValue(Op0, Result);
1121 if (PtrWidth != Result.IntVal.getBitWidth())
1122 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1123 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1124
1125 Result.PointerVal =
1126 llvm::PointerTy(
1127 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1128
1129 return;
1130 }
1131 case llvm::Instruction::BitCast: {
1132 GetConstantValue(Op0, Result);
1133 const llvm::Type *DestTy = CE->getType();
1134
1135 switch (Op0->getType()->getTypeID()) {
1136 case llvm::Type::IntegerTyID: {
1137 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1138 if (DestTy->isFloatTy())
1139 Result.FloatVal = Result.IntVal.bitsToFloat();
1140 else if (DestTy->isDoubleTy())
1141 Result.DoubleVal = Result.IntVal.bitsToDouble();
1142 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001143 }
Zonr Chang932648d2010-10-13 22:23:56 +08001144 case llvm::Type::FloatTyID: {
1145 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1146 Result.IntVal.floatToBits(Result.FloatVal);
1147 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001148 }
Zonr Chang932648d2010-10-13 22:23:56 +08001149 case llvm::Type::DoubleTyID: {
1150 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1151 Result.IntVal.doubleToBits(Result.DoubleVal);
1152 break;
1153 }
1154 case llvm::Type::PointerTyID: {
1155 assert(DestTy->isPointerTy() && "Invalid bitcast");
1156 break; // getConstantValue(Op0) above already converted it
1157 }
1158 default: {
1159 llvm_unreachable("Invalid bitcast operand");
1160 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001161 }
Zonr Chang932648d2010-10-13 22:23:56 +08001162 return;
1163 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001164 case llvm::Instruction::Add:
1165 case llvm::Instruction::FAdd:
1166 case llvm::Instruction::Sub:
1167 case llvm::Instruction::FSub:
1168 case llvm::Instruction::Mul:
1169 case llvm::Instruction::FMul:
1170 case llvm::Instruction::UDiv:
1171 case llvm::Instruction::SDiv:
1172 case llvm::Instruction::URem:
1173 case llvm::Instruction::SRem:
1174 case llvm::Instruction::And:
1175 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001176 case llvm::Instruction::Xor: {
1177 llvm::GenericValue LHS, RHS;
1178 GetConstantValue(Op0, LHS);
1179 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001180
Zonr Chang932648d2010-10-13 22:23:56 +08001181 switch (Op0->getType()->getTypeID()) {
1182 case llvm::Type::IntegerTyID: {
1183 switch (CE->getOpcode()) {
1184 case llvm::Instruction::Add: {
1185 Result.IntVal = LHS.IntVal + RHS.IntVal;
1186 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001187 }
Zonr Chang932648d2010-10-13 22:23:56 +08001188 case llvm::Instruction::Sub: {
1189 Result.IntVal = LHS.IntVal - RHS.IntVal;
1190 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001191 }
Zonr Chang932648d2010-10-13 22:23:56 +08001192 case llvm::Instruction::Mul: {
1193 Result.IntVal = LHS.IntVal * RHS.IntVal;
1194 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001195 }
Zonr Chang932648d2010-10-13 22:23:56 +08001196 case llvm::Instruction::UDiv: {
1197 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1198 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001199 }
Zonr Chang932648d2010-10-13 22:23:56 +08001200 case llvm::Instruction::SDiv: {
1201 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1202 break;
1203 }
1204 case llvm::Instruction::URem: {
1205 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1206 break;
1207 }
1208 case llvm::Instruction::SRem: {
1209 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1210 break;
1211 }
1212 case llvm::Instruction::And: {
1213 Result.IntVal = LHS.IntVal & RHS.IntVal;
1214 break;
1215 }
1216 case llvm::Instruction::Or: {
1217 Result.IntVal = LHS.IntVal | RHS.IntVal;
1218 break;
1219 }
1220 case llvm::Instruction::Xor: {
1221 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1222 break;
1223 }
1224 default: {
1225 llvm_unreachable("Invalid integer opcode");
1226 }
1227 }
1228 break;
1229 }
1230 case llvm::Type::FloatTyID: {
1231 switch (CE->getOpcode()) {
1232 case llvm::Instruction::FAdd: {
1233 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1234 break;
1235 }
1236 case llvm::Instruction::FSub: {
1237 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1238 break;
1239 }
1240 case llvm::Instruction::FMul: {
1241 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1242 break;
1243 }
1244 case llvm::Instruction::FDiv: {
1245 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1246 break;
1247 }
1248 case llvm::Instruction::FRem: {
1249 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1250 break;
1251 }
1252 default: {
1253 llvm_unreachable("Invalid float opcode");
1254 }
1255 }
1256 break;
1257 }
1258 case llvm::Type::DoubleTyID: {
1259 switch (CE->getOpcode()) {
1260 case llvm::Instruction::FAdd: {
1261 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1262 break;
1263 }
1264 case llvm::Instruction::FSub: {
1265 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1266 break;
1267 }
1268 case llvm::Instruction::FMul: {
1269 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1270 break;
1271 }
1272 case llvm::Instruction::FDiv: {
1273 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1274 break;
1275 }
1276 case llvm::Instruction::FRem: {
1277 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1278 break;
1279 }
1280 default: {
1281 llvm_unreachable("Invalid double opcode");
1282 }
1283 }
1284 break;
1285 }
1286 case llvm::Type::X86_FP80TyID:
1287 case llvm::Type::PPC_FP128TyID:
1288 case llvm::Type::FP128TyID: {
1289 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1290 switch (CE->getOpcode()) {
1291 case llvm::Instruction::FAdd: {
1292 apfLHS.add(llvm::APFloat(RHS.IntVal),
1293 llvm::APFloat::rmNearestTiesToEven);
1294 break;
1295 }
1296 case llvm::Instruction::FSub: {
1297 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1298 llvm::APFloat::rmNearestTiesToEven);
1299 break;
1300 }
1301 case llvm::Instruction::FMul: {
1302 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1303 llvm::APFloat::rmNearestTiesToEven);
1304 break;
1305 }
1306 case llvm::Instruction::FDiv: {
1307 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1308 llvm::APFloat::rmNearestTiesToEven);
1309 break;
1310 }
1311 case llvm::Instruction::FRem: {
1312 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1313 llvm::APFloat::rmNearestTiesToEven);
1314 break;
1315 }
1316 default: {
1317 llvm_unreachable("Invalid long double opcode");
1318 }
1319 }
1320 Result.IntVal = apfLHS.bitcastToAPInt();
1321 break;
1322 }
1323 default: {
1324 llvm_unreachable("Bad add type!");
1325 }
1326 } // End switch (Op0->getType()->getTypeID())
1327 return;
1328 }
1329 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001330 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001331 }
1332 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001333
1334 std::string msg;
1335 llvm::raw_string_ostream Msg(msg);
1336 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001337 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001338 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001339
1340 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001341 case llvm::Type::FloatTyID: {
1342 Result.FloatVal =
1343 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001344 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001345 }
1346 case llvm::Type::DoubleTyID: {
1347 Result.DoubleVal =
1348 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001349 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001350 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001351 case llvm::Type::X86_FP80TyID:
1352 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001353 case llvm::Type::PPC_FP128TyID: {
1354 Result.IntVal =
1355 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001356 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001357 }
1358 case llvm::Type::IntegerTyID: {
1359 Result.IntVal =
1360 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001361 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001362 }
1363 case llvm::Type::PointerTyID: {
1364 switch (C->getValueID()) {
1365 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001366 Result.PointerVal = NULL;
1367 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001368 }
1369 case llvm::Value::FunctionVal: {
1370 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1371 Result.PointerVal =
1372 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001373 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001374 }
1375 case llvm::Value::GlobalVariableVal: {
1376 const llvm::GlobalVariable *GV =
1377 static_cast<const llvm::GlobalVariable*>(C);
1378 Result.PointerVal =
1379 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001380 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001381 }
1382 case llvm::Value::BlockAddressVal: {
1383 assert(false && "JIT does not support address-of-label yet!");
1384 }
1385 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001386 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001387 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001388 }
1389 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001390 }
1391 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001392 std::string msg;
1393 llvm::raw_string_ostream Msg(msg);
1394 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001395 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001396 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001397 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001398 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001399 return;
1400 }
1401
Zonr Chang932648d2010-10-13 22:23:56 +08001402 // Stores the data in @Val of type @Ty at address @Addr.
1403 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001404 const llvm::Type *Ty) {
1405 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1406
Zonr Chang932648d2010-10-13 22:23:56 +08001407 switch (Ty->getTypeID()) {
1408 case llvm::Type::IntegerTyID: {
1409 const llvm::APInt &IntVal = Val.IntVal;
1410 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1411 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001412
Zonr Chang932648d2010-10-13 22:23:56 +08001413 const uint8_t *Src =
1414 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001415
Zonr Chang932648d2010-10-13 22:23:56 +08001416 if (llvm::sys::isLittleEndianHost()) {
1417 // Little-endian host - the source is ordered from LSB to MSB.
1418 // Order the destination from LSB to MSB: Do a straight copy.
1419 memcpy(Addr, Src, StoreBytes);
1420 } else {
1421 // Big-endian host - the source is an array of 64 bit words
1422 // ordered from LSW to MSW.
1423 //
1424 // Each word is ordered from MSB to LSB.
1425 //
1426 // Order the destination from MSB to LSB:
1427 // Reverse the word order, but not the bytes in a word.
1428 unsigned int i = StoreBytes;
1429 while (i > sizeof(uint64_t)) {
1430 i -= sizeof(uint64_t);
1431 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1432 Src,
1433 sizeof(uint64_t));
1434 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001435 }
Zonr Chang932648d2010-10-13 22:23:56 +08001436 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001437 }
1438 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001439 }
1440 case llvm::Type::FloatTyID: {
1441 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001442 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001443 }
1444 case llvm::Type::DoubleTyID: {
1445 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001446 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001447 }
1448 case llvm::Type::X86_FP80TyID: {
1449 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001450 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001451 }
1452 case llvm::Type::PointerTyID: {
1453 // Ensure 64 bit target pointers are fully initialized on 32 bit
1454 // hosts.
1455 if (StoreBytes != sizeof(llvm::PointerTy))
1456 memset(Addr, 0, StoreBytes);
1457 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001458 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001459 }
1460 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001461 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001462 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001463 }
1464
Zonr Chang932648d2010-10-13 22:23:56 +08001465 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1466 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1467 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001468
1469 return;
1470 }
1471
Zonr Chang932648d2010-10-13 22:23:56 +08001472 // Recursive function to apply a @Constant value into the specified memory
1473 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001474 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001475 switch (C->getValueID()) {
1476 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001477 // Nothing to do
1478 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001479 }
1480 case llvm::Value::ConstantVectorVal: {
1481 // dynamic cast may hurt performance
1482 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001483
Zonr Chang932648d2010-10-13 22:23:56 +08001484 unsigned int ElementSize = mpTD->getTypeAllocSize
1485 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001486
Zonr Chang932648d2010-10-13 22:23:56 +08001487 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1488 InitializeConstantToMemory(
1489 CP->getOperand(i),
1490 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001491 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001492 }
1493 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001494 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1495 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001496 }
1497 case llvm::Value::ConstantArrayVal: {
1498 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1499 unsigned int ElementSize = mpTD->getTypeAllocSize
1500 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001501
Zonr Chang932648d2010-10-13 22:23:56 +08001502 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1503 InitializeConstantToMemory(
1504 CPA->getOperand(i),
1505 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1506 break;
1507 }
1508 case llvm::Value::ConstantStructVal: {
1509 const llvm::ConstantStruct *CPS =
1510 static_cast<const llvm::ConstantStruct*>(C);
1511 const llvm::StructLayout *SL = mpTD->getStructLayout
1512 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001513
Zonr Chang932648d2010-10-13 22:23:56 +08001514 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1515 InitializeConstantToMemory(
1516 CPS->getOperand(i),
1517 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1518 break;
1519 }
1520 default: {
1521 if (C->getType()->isFirstClassType()) {
1522 llvm::GenericValue Val;
1523 GetConstantValue(C, Val);
1524 StoreValueToMemory(Val, Addr, C->getType());
1525 } else {
1526 llvm_unreachable("Unknown constant type to initialize memory "
1527 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001528 }
1529 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001530 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001531 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001532 return;
1533 }
1534
1535 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001536 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001537 return;
1538
Zonr Chang932648d2010-10-13 22:23:56 +08001539 // Constant pool address resolution is handled by the target itself in ARM
1540 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001541#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001542 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1543 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001544
Zonr Chang932648d2010-10-13 22:23:56 +08001545 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001546 return;
1547
1548 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1549 unsigned Align = MCP->getConstantPoolAlignment();
1550
1551 mpConstantPoolBase = allocateSpace(Size, Align);
1552 mpConstantPool = MCP;
1553
Zonr Chang932648d2010-10-13 22:23:56 +08001554 if (mpConstantPoolBase == NULL)
1555 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001556
1557 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001558 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001559 llvm::MachineConstantPoolEntry CPE = Constants[i];
1560 unsigned AlignMask = CPE.getAlignment() - 1;
1561 Offset = (Offset + AlignMask) & ~AlignMask;
1562
1563 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1564 mConstPoolAddresses.push_back(CAddr);
1565
Zonr Chang932648d2010-10-13 22:23:56 +08001566 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001567 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001568 ("Initialize memory with machine specific constant pool"
1569 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001570
1571 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1572
1573 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1574 Offset += mpTD->getTypeAllocSize(Ty);
1575 }
1576#endif
1577 return;
1578 }
1579
1580 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001581 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001582 return;
1583
Zonr Chang932648d2010-10-13 22:23:56 +08001584 const std::vector<llvm::MachineJumpTableEntry> &JT =
1585 MJTI->getJumpTables();
1586 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001587 return;
1588
1589 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001590 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001591 NumEntries += JT[i].MBBs.size();
1592
1593 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1594
Zonr Chang932648d2010-10-13 22:23:56 +08001595 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001596 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001597 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001598
1599 return;
1600 }
1601
1602 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001603 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001604 return;
1605
Zonr Chang932648d2010-10-13 22:23:56 +08001606 const std::vector<llvm::MachineJumpTableEntry> &JT =
1607 MJTI->getJumpTables();
1608 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001609 return;
1610
Zonr Chang932648d2010-10-13 22:23:56 +08001611 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1612 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1613 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001614
Zonr Chang932648d2010-10-13 22:23:56 +08001615 // For each jump table, map each target in the jump table to the
1616 // address of an emitted MachineBasicBlock.
1617 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1618 for (int i = 0, ie = JT.size(); i != ie; i++) {
1619 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1620 // Store the address of the basic block for this jump table slot in the
1621 // memory we allocated for the jump table in 'initJumpTableInfo'
1622 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001623 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1624 }
1625 }
1626
Zonr Chang932648d2010-10-13 22:23:56 +08001627 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1628 bool MayNeedFarStub) {
1629 switch (V->getValueID()) {
1630 case llvm::Value::FunctionVal: {
1631 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001632
Zonr Chang932648d2010-10-13 22:23:56 +08001633 // If we have code, go ahead and return that.
1634 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1635 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001636
Zonr Chang932648d2010-10-13 22:23:56 +08001637 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1638 // Return the function stub if it's already created.
1639 // We do this first so that:
1640 // we're returning the same address for the function as any
1641 // previous call.
1642 //
1643 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1644 // guaranteed to be close enough to call.
1645 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001646
Zonr Chang932648d2010-10-13 22:23:56 +08001647 // If we know the target can handle arbitrary-distance calls, try to
1648 // return a direct pointer.
1649 if (!MayNeedFarStub) {
1650 //
1651 // x86_64 architecture may encounter the bug:
1652 // http://llvm.org/bugs/show_bug.cgi?id=5201
1653 // which generate instruction "call" instead of "callq".
1654 //
1655 // And once the real address of stub is greater than 64-bit
1656 // long, the replacement will truncate to 32-bit resulting a
1657 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001658#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001659 // If this is an external function pointer, we can force the JIT
1660 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001661 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1662 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1663 // Changing to false because wanting to allow later calls to
1664 // mpTJI->relocate() without aborting. For caching purpose
1665 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001666#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001667 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001668
Zonr Chang932648d2010-10-13 22:23:56 +08001669 // Otherwise, we may need a to emit a stub, and, conservatively, we
1670 // always do so.
1671 return GetLazyFunctionStub(F);
1672 break;
1673 }
1674 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001675 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1676 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001677 }
1678 case llvm::Value::GlobalAliasVal: {
1679 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1680 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001681
Zonr Chang932648d2010-10-13 22:23:56 +08001682 switch (GV->getValueID()) {
1683 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001684 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001685 // code-gen'd?
1686 return GetPointerToFunction(
1687 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001688 /* AbortOnFailure = */false);
1689 // Changing to false because wanting to allow later calls to
1690 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001691 break;
1692 }
1693 case llvm::Value::GlobalVariableVal: {
1694 if (void *P = mGlobalAddressMap[GV])
1695 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001696
Zonr Chang932648d2010-10-13 22:23:56 +08001697 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1698 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001699
Zonr Chang932648d2010-10-13 22:23:56 +08001700 return mGlobalAddressMap[GV];
1701 break;
1702 }
1703 case llvm::Value::GlobalAliasVal: {
1704 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001705 }
1706 }
1707 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001708 }
1709 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001710 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001711 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001712 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001713 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001714 }
1715
Zonr Chang932648d2010-10-13 22:23:56 +08001716 // If the specified function has been code-gen'd, return a pointer to the
1717 // function. If not, compile it, or use a stub to implement lazy compilation
1718 // if available.
1719 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1720 // If we have already code generated the function, just return the
1721 // address.
1722 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001723 return Addr;
1724
Zonr Chang932648d2010-10-13 22:23:56 +08001725 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001726 return GetLazyFunctionStub(F);
1727 }
1728
Zonr Chang932648d2010-10-13 22:23:56 +08001729 typedef llvm::DenseMap<const llvm::Function*,
1730 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001731 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1732
Zonr Chang932648d2010-10-13 22:23:56 +08001733 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001734 return mFunctionToLazyStubMap.lookup(F);
1735 }
1736
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001737 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001738 void *GetLazyFunctionStub(llvm::Function *F) {
1739 // If we already have a lazy stub for this function, recycle it.
1740 void *&Stub = mFunctionToLazyStubMap[F];
1741 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001742 return Stub;
1743
Zonr Chang932648d2010-10-13 22:23:56 +08001744 // In any cases, we should NOT resolve function at runtime (though we are
1745 // able to). We resolve this right now.
1746 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001747 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1748 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1749 // Changing to false because wanting to allow later calls to
1750 // mpTJI->relocate() without aborting. For caching purpose
1751 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001752
Zonr Chang932648d2010-10-13 22:23:56 +08001753 // Codegen a new stub, calling the actual address of the external
1754 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001755 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1756 startGVStub(F, SL.Size, SL.Alignment);
1757 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1758 finishGVStub();
1759
Zonr Chang932648d2010-10-13 22:23:56 +08001760 // We really want the address of the stub in the GlobalAddressMap for the
1761 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001762 UpdateGlobalMapping(F, Stub);
1763
Zonr Chang932648d2010-10-13 22:23:56 +08001764 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001765 PendingFunctions.insert(F);
1766 else
Zonr Chang932648d2010-10-13 22:23:56 +08001767 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1768 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001769
1770 return Stub;
1771 }
1772
Zonr Chang932648d2010-10-13 22:23:56 +08001773 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1774 void *Addr = GetPointerToGlobalIfAvailable(F);
1775 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001776 return Addr;
1777
1778 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1779 "Internal error: only external defined function routes here!");
1780
Zonr Chang932648d2010-10-13 22:23:56 +08001781 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001782 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001783 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001784
Zonr Chang932648d2010-10-13 22:23:56 +08001785 // If we resolved the symbol to a null address (eg. a weak external)
1786 // return a null pointer let the application handle it.
1787 if (Addr == NULL) {
1788 if (AbortOnFailure)
1789 llvm::report_fatal_error("Could not resolve external function "
1790 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001791 else
1792 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001793 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001794
1795 AddGlobalMapping(F, Addr);
1796
1797 return Addr;
1798 }
1799
Zonr Chang932648d2010-10-13 22:23:56 +08001800 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001801 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001802 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001803 return Addr;
1804
Zonr Chang932648d2010-10-13 22:23:56 +08001805 if (mpSymbolLookupFn)
1806 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001807 return Addr;
1808
Zonr Chang932648d2010-10-13 22:23:56 +08001809 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001810 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001811 "' which could not be resolved!");
1812
1813 return NULL;
1814 }
1815
Zonr Chang932648d2010-10-13 22:23:56 +08001816 // Return the address of the specified global variable, possibly emitting it
1817 // to memory if needed. This is used by the Emitter.
1818 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1819 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1820 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001821 return Ptr;
1822
Zonr Chang932648d2010-10-13 22:23:56 +08001823 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1824 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001825 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1826 AddGlobalMapping(GV, Ptr);
1827 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001828 // If the global hasn't been emitted to memory yet, allocate space and
1829 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001830 Ptr = GetMemoryForGV(GV);
1831 AddGlobalMapping(GV, Ptr);
1832 EmitGlobalVariable(GV);
1833 }
1834
1835 return Ptr;
1836 }
1837
Zonr Chang932648d2010-10-13 22:23:56 +08001838 // This method abstracts memory allocation of global variable so that the
1839 // JIT can allocate thread local variables depending on the target.
1840 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1841 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001842
Zonr Chang932648d2010-10-13 22:23:56 +08001843 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001844 size_t S = mpTD->getTypeAllocSize(GlobalType);
1845 size_t A = mpTD->getPreferredAlignment(GV);
1846
Zonr Chang932648d2010-10-13 22:23:56 +08001847 if (GV->isThreadLocal()) {
1848 // We can support TLS by
1849 //
1850 // Ptr = TJI.allocateThreadLocalMemory(S);
1851 //
1852 // But I tend not to.
1853 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001854 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001855 ("Compilation of Thread Local Storage (TLS) is disabled!");
1856
Zonr Chang932648d2010-10-13 22:23:56 +08001857 } else if (mpTJI->allocateSeparateGVMemory()) {
1858 if (A <= 8) {
1859 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001860 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001861 // Allocate (S + A) bytes of memory, then use an aligned pointer
1862 // within that space.
1863 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001864 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001865 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1866 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001867 }
1868 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001869 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001870 }
1871
1872 return Ptr;
1873 }
1874
1875 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001876 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001877
Zonr Chang932648d2010-10-13 22:23:56 +08001878 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001879 llvm::report_fatal_error
1880 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001881
Zonr Chang932648d2010-10-13 22:23:56 +08001882 if (GA == NULL) {
1883 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001884 GA = GetMemoryForGV(GV);
1885 AddGlobalMapping(GV, GA);
1886 }
1887
1888 InitializeConstantToMemory(GV->getInitializer(), GA);
1889
Zonr Chang932648d2010-10-13 22:23:56 +08001890 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001891 return;
1892 }
1893
1894 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1895 > GlobalToIndirectSymMapTy;
1896 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1897
Zonr Chang932648d2010-10-13 22:23:56 +08001898 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1899 // Make sure GV is emitted first, and create a stub containing the fully
1900 // resolved address.
1901 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001902
Zonr Chang932648d2010-10-13 22:23:56 +08001903 // If we already have a stub for this global variable, recycle it.
1904 void *&IndirectSym = GlobalToIndirectSymMap[V];
1905 // Otherwise, codegen a new indirect symbol.
1906 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001907 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1908
1909 return IndirectSym;
1910 }
1911
Zonr Chang932648d2010-10-13 22:23:56 +08001912 // This is the equivalent of FunctionToLazyStubMap for external functions.
1913 //
1914 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1915 // It's actually here to make it more likely that far calls
1916 // succeed, but no single stub can guarantee that. I'll
1917 // remove this in a subsequent checkin when I actually fix
1918 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001919 std::map<void*, void*> ExternalFnToStubMap;
1920
Zonr Chang932648d2010-10-13 22:23:56 +08001921 // Return a stub for the function at the specified address.
1922 void *GetExternalFunctionStub(void *FnAddr) {
1923 void *&Stub = ExternalFnToStubMap[FnAddr];
1924 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001925 return Stub;
1926
1927 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1928 startGVStub(0, SL.Size, SL.Alignment);
1929 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1930 finishGVStub();
1931
1932 return Stub;
1933 }
1934
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001935#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001936 const llvm::MCAsmInfo *mpAsmInfo;
1937 const llvm::MCDisassembler *mpDisassmbler;
1938 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001939
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001940 class BufferMemoryObject : public llvm::MemoryObject {
1941 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001942 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001943 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001944
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001945 public:
1946 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1947 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001948
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001949 uint64_t getBase() const { return 0; }
1950 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001951
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001952 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001953 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001954 return -1;
1955 *Byte = mBytes[Addr];
1956 return 0;
1957 }
1958 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001959
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08001960 public:
Zonr Chang932648d2010-10-13 22:23:56 +08001961 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001962 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001963 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001964#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001965 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001966 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1967 ErrorInfo,
1968 llvm::raw_fd_ostream::F_Append);
1969 if (!ErrorInfo.empty()) { // some errors occurred
1970 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001971 delete OS;
1972 return;
1973 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001974#else
1975 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001976#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001977 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1978 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001979
Zonr Chang932648d2010-10-13 22:23:56 +08001980 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001981 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001982 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001983 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001984 if (mpIP == NULL)
1985 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1986 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001987
Zonr Chang932648d2010-10-13 22:23:56 +08001988 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1989 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001990 uint64_t Size;
1991 uint64_t Index;
1992
Zonr Chang932648d2010-10-13 22:23:56 +08001993 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001994 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001995
Zonr Chang932648d2010-10-13 22:23:56 +08001996 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1997 /* REMOVED */ llvm::nulls())) {
1998 (*OS).indent(4)
1999 .write("0x", 2)
2000 .write_hex((uint32_t) Start + Index)
2001 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002002 mpIP->printInst(&Inst, *OS);
2003 *OS << "\n";
2004 } else {
2005 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002006 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002007 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002008 }
2009
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002010 *OS << "\n";
2011 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002012
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002013#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002014 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002015 OS->close();
2016 delete OS;
2017#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002018 return;
2019 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002020#else
Zonr Chang932648d2010-10-13 22:23:56 +08002021 inline void Disassemble(const std::string &Name, uint8_t *Start,
2022 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002023 return;
2024 }
Zonr Chang932648d2010-10-13 22:23:56 +08002025#endif // defined(USE_DISASSEMBLER)
2026
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002027 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002028 // Resolver to undefined symbol in CodeEmitter
2029 BCCSymbolLookupFn mpSymbolLookupFn;
2030 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002031
2032 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002033 // Will take the ownership of @MemMgr
2034 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2035 : mpMemMgr(pMemMgr),
2036 mpTarget(NULL),
2037 mpTJI(NULL),
2038 mpTD(NULL),
2039 mpCurEmitFunction(NULL),
2040 mpConstantPool(NULL),
2041 mpJumpTable(NULL),
2042 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002043#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002044 mpAsmInfo(NULL),
2045 mpDisassmbler(NULL),
2046 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002047#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002048 mpSymbolLookupFn(NULL),
2049 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002050 return;
2051 }
2052
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002053 inline global_addresses_const_iterator global_address_begin() const {
2054 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002055 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002056 inline global_addresses_const_iterator global_address_end() const {
2057 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002058 }
2059
Logan824dd0a2010-11-20 01:45:54 +08002060 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2061 return mCachingRelocations;
2062 }
2063
Zonr Chang932648d2010-10-13 22:23:56 +08002064 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002065 mpSymbolLookupFn = pFn;
2066 mpSymbolLookupContext = pContext;
2067 return;
2068 }
2069
Zonr Chang932648d2010-10-13 22:23:56 +08002070 void setTargetMachine(llvm::TargetMachine &TM) {
2071 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002072 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002073 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002074 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002075 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002076 mpTD = TM.getTargetData();
2077
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002078 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2079
2080 return;
2081 }
2082
Zonr Chang932648d2010-10-13 22:23:56 +08002083 // This callback is invoked when the specified function is about to be code
2084 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002085 void startFunction(llvm::MachineFunction &F) {
2086 uintptr_t ActualSize = 0;
2087
2088 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002089
2090 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2091 // MachineCodeEmitter, which is the super class of the class
2092 // JITCodeEmitter.
2093 //
2094 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2095 // allocated for this code buffer.
2096 //
2097 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2098 // code. This is guranteed to be in the range
2099 // [BufferBegin, BufferEnd]. If this pointer is at
2100 // BufferEnd, it will never move due to code emission, and
2101 // all code emission requests will be ignored (this is the
2102 // buffer overflow condition).
2103 BufferBegin = CurBufferPtr =
2104 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002105 BufferEnd = BufferBegin + ActualSize;
2106
Zonr Chang932648d2010-10-13 22:23:56 +08002107 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002108 mpCurEmitFunction = new EmittedFunctionCode();
2109 mpCurEmitFunction->FunctionBody = BufferBegin;
2110
Zonr Chang932648d2010-10-13 22:23:56 +08002111 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002112 emitAlignment(16);
2113
2114 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002115 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002116 initJumpTableInfo(MJTI);
2117
Zonr Chang932648d2010-10-13 22:23:56 +08002118 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002119 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2120
2121 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2122
2123 mpCurEmitFunction->Code = CurBufferPtr;
2124
2125 mMBBLocations.clear();
2126
2127 return;
2128 }
2129
Zonr Chang932648d2010-10-13 22:23:56 +08002130 // This callback is invoked when the specified function has finished code
2131 // generation. If a buffer overflow has occurred, this method returns true
2132 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002133 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002134 if (CurBufferPtr == BufferEnd) {
2135 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002136 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2137 return false;
2138 }
2139
Zonr Chang932648d2010-10-13 22:23:56 +08002140 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002141 emitJumpTableInfo(MJTI);
2142
Zonr Chang932648d2010-10-13 22:23:56 +08002143 // FnStart is the start of the text, not the start of the constant pool
2144 // and other per-function data.
2145 uint8_t *FnStart =
2146 reinterpret_cast<uint8_t*>(
2147 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002148
Zonr Chang932648d2010-10-13 22:23:56 +08002149 // FnEnd is the end of the function's machine code.
2150 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002151
Zonr Chang932648d2010-10-13 22:23:56 +08002152 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002153 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2154
Zonr Chang932648d2010-10-13 22:23:56 +08002155 // Resolve the relocations to concrete pointers.
2156 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2157 llvm::MachineRelocation &MR = mRelocations[i];
2158 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002159
Zonr Chang932648d2010-10-13 22:23:56 +08002160 if (!MR.letTargetResolve()) {
2161 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002162 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002163
2164 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002165 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002166 }
2167
Zonr Chang932648d2010-10-13 22:23:56 +08002168 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002169 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2170 BufferBegin
2171 + MR.getMachineCodeOffset(),
2172 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002173 } else if (MR.isIndirectSymbol()) {
2174 ResultPtr =
2175 GetPointerToGVIndirectSym(
2176 MR.getGlobalValue(),
2177 BufferBegin + MR.getMachineCodeOffset());
2178 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002179 ResultPtr =
2180 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002181 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002182 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002183 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002184 } else {
2185 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2186 ResultPtr =
2187 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2188 }
2189
Logan824dd0a2010-11-20 01:45:54 +08002190 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2191 // TODO(logan): Cache external symbol relocation entry.
2192 // Currently, we are not caching them. But since Android
2193 // system is using prelink, it is not a problem.
2194
2195 // Cache the relocation result address
2196 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002197 oBCCRelocEntry(MR.getRelocationType(),
2198 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002199 ResultPtr));
2200 }
2201
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002202 MR.setResultPointer(ResultPtr);
2203 }
2204 }
2205
2206 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2207 mpMemMgr->getGOTBase());
2208 }
2209
2210 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002211 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2212 // global variables that were referenced in the relocations.
2213 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002214 return false;
2215
Zonr Chang932648d2010-10-13 22:23:56 +08002216 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002217 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2218 BufferBegin = CurBufferPtr = 0;
2219
Zonr Chang932648d2010-10-13 22:23:56 +08002220 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002221 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2222 mpCurEmitFunction = NULL;
2223
2224 mRelocations.clear();
2225 mConstPoolAddresses.clear();
2226
Zonr Chang932648d2010-10-13 22:23:56 +08002227 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002228 mpMMI->EndFunction();
2229
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002230 updateFunctionStub(F.getFunction());
2231
Zonr Chang932648d2010-10-13 22:23:56 +08002232 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002233 mpMemMgr->setMemoryExecutable();
2234
2235 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2236
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002237 return false;
2238 }
2239
Zonr Chang932648d2010-10-13 22:23:56 +08002240 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002241 unsigned Alignment) {
2242 mpSavedBufferBegin = BufferBegin;
2243 mpSavedBufferEnd = BufferEnd;
2244 mpSavedCurBufferPtr = CurBufferPtr;
2245
2246 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2247 Alignment);
2248 BufferEnd = BufferBegin + StubSize + 1;
2249
2250 return;
2251 }
2252
Zonr Chang932648d2010-10-13 22:23:56 +08002253 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002254 mpSavedBufferBegin = BufferBegin;
2255 mpSavedBufferEnd = BufferEnd;
2256 mpSavedCurBufferPtr = CurBufferPtr;
2257
Zonr Chang932648d2010-10-13 22:23:56 +08002258 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002259 BufferEnd = BufferBegin + StubSize + 1;
2260
2261 return;
2262 }
2263
2264 void finishGVStub() {
2265 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2266
Zonr Chang932648d2010-10-13 22:23:56 +08002267 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002268 BufferBegin = mpSavedBufferBegin;
2269 BufferEnd = mpSavedBufferEnd;
2270 CurBufferPtr = mpSavedCurBufferPtr;
2271
2272 return;
2273 }
2274
Zonr Chang932648d2010-10-13 22:23:56 +08002275 // Allocates and fills storage for an indirect GlobalValue, and returns the
2276 // address.
2277 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002278 const uint8_t *Buffer, size_t Size,
2279 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002280 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002281 memcpy(IndGV, Buffer, Size);
2282 return IndGV;
2283 }
2284
Zonr Chang932648d2010-10-13 22:23:56 +08002285 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002286 void emitLabel(llvm::MCSymbol *Label) {
2287 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002288 return;
2289 }
2290
Zonr Chang932648d2010-10-13 22:23:56 +08002291 // Allocate memory for a global. Unlike allocateSpace, this method does not
2292 // allocate memory in the current output buffer, because a global may live
2293 // longer than the current function.
2294 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2295 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002296 return mpMemMgr->allocateGlobal(Size, Alignment);
2297 }
2298
Zonr Chang932648d2010-10-13 22:23:56 +08002299 // This should be called by the target when a new basic block is about to be
2300 // emitted. This way the MCE knows where the start of the block is, and can
2301 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002302 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002303 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002304 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2305 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2306 return;
2307 }
2308
Zonr Chang932648d2010-10-13 22:23:56 +08002309 // Whenever a relocatable address is needed, it should be noted with this
2310 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002311 void addRelocation(const llvm::MachineRelocation &MR) {
2312 mRelocations.push_back(MR);
2313 return;
2314 }
2315
Zonr Chang932648d2010-10-13 22:23:56 +08002316 // Return the address of the @Index entry in the constant pool that was
2317 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002318 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2319 assert(Index < mpConstantPool->getConstants().size() &&
2320 "Invalid constant pool index!");
2321 return mConstPoolAddresses[Index];
2322 }
2323
Zonr Chang932648d2010-10-13 22:23:56 +08002324 // Return the address of the jump table with index @Index in the function
2325 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002326 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002327 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002328 mpJumpTable->getJumpTables();
2329
Zonr Chang932648d2010-10-13 22:23:56 +08002330 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002331
2332 unsigned int Offset = 0;
2333 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2334
Zonr Chang932648d2010-10-13 22:23:56 +08002335 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002336 Offset += JT[i].MBBs.size();
2337 Offset *= EntrySize;
2338
Zonr Chang932648d2010-10-13 22:23:56 +08002339 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002340 }
2341
Zonr Chang932648d2010-10-13 22:23:56 +08002342 // Return the address of the specified MachineBasicBlock, only usable after
2343 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002344 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2345 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002346 mMBBLocations[MBB->getNumber()] &&
2347 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002348 return mMBBLocations[MBB->getNumber()];
2349 }
2350
Zonr Chang932648d2010-10-13 22:23:56 +08002351 // Return the address of the specified LabelID, only usable after the
2352 // LabelID has been emitted.
2353 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002354 assert(mLabelLocations.count(Label) && "Label not emitted!");
2355 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002356 }
2357
Zonr Chang932648d2010-10-13 22:23:56 +08002358 // Specifies the MachineModuleInfo object. This is used for exception
2359 // handling purposes.
2360 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002361 mpMMI = Info;
2362 return;
2363 }
2364
Zonr Chang932648d2010-10-13 22:23:56 +08002365 void updateFunctionStub(const llvm::Function *F) {
2366 // Get the empty stub we generated earlier.
2367 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002368 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002369 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002370 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002371 else
2372 return;
2373
Zonr Chang932648d2010-10-13 22:23:56 +08002374 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002375
2376 assert(Addr != Stub &&
2377 "Function must have non-stub address to be updated.");
2378
Zonr Chang932648d2010-10-13 22:23:56 +08002379 // Tell the target jit info to rewrite the stub at the specified address,
2380 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002381 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2382 startGVStub(Stub, SL.Size);
2383 mpTJI->emitFunctionStub(F, Addr, *this);
2384 finishGVStub();
2385
Zonr Chang932648d2010-10-13 22:23:56 +08002386 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2387 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002388
2389 PendingFunctions.erase(I);
2390
2391 return;
2392 }
2393
Zonr Chang932648d2010-10-13 22:23:56 +08002394 // Once you finish the compilation on a translation unit, you can call this
2395 // function to recycle the memory (which is used at compilation time and not
2396 // needed for runtime).
2397 //
2398 // NOTE: You should not call this funtion until the code-gen passes for a
2399 // given module is done. Otherwise, the results is undefined and may
2400 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002401 void releaseUnnecessary() {
2402 mMBBLocations.clear();
2403 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002404 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002405 mFunctionToLazyStubMap.clear();
2406 GlobalToIndirectSymMap.clear();
2407 ExternalFnToStubMap.clear();
2408 PendingFunctions.clear();
2409
2410 return;
2411 }
2412
2413 void reset() {
2414 releaseUnnecessary();
2415
2416 mpSymbolLookupFn = NULL;
2417 mpSymbolLookupContext = NULL;
2418
2419 mpTJI = NULL;
2420 mpTD = NULL;
2421
Zonr Chang932648d2010-10-13 22:23:56 +08002422 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2423 E = mEmittedFunctions.end();
2424 I != E;
2425 I++)
2426 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002427 delete I->second;
2428 mEmittedFunctions.clear();
2429
2430 mpMemMgr->reset();
2431
2432 return;
2433 }
2434
Zonr Chang932648d2010-10-13 22:23:56 +08002435 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002436 return lookup( llvm::StringRef(Name) );
2437 }
2438
Zonr Chang932648d2010-10-13 22:23:56 +08002439 void *lookup(const llvm::StringRef &Name) {
2440 EmittedFunctionsMapTy::const_iterator I =
2441 mEmittedFunctions.find(Name.str());
2442 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002443 return NULL;
2444 else
2445 return I->second->Code;
2446 }
2447
Zonr Chang932648d2010-10-13 22:23:56 +08002448 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002449 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002450 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002451 int functionCount = mEmittedFunctions.size();
2452
Zonr Chang932648d2010-10-13 22:23:56 +08002453 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002454 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002455 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002456 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002457 if (functions)
2458 for (EmittedFunctionsMapTy::const_iterator
2459 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2460 (I != E) && (functionCount > 0);
2461 I++, functionCount--)
2462 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002463
2464 return;
2465 }
2466
Zonr Chang932648d2010-10-13 22:23:56 +08002467 void getFunctionBinary(BCCchar *label,
2468 BCCvoid **base,
2469 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002470 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002471 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002472 *base = NULL;
2473 *length = 0;
2474 } else {
2475 *base = I->second->Code;
2476 *length = I->second->Size;
2477 }
2478 return;
2479 }
2480
2481 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002482 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002483#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002484 delete mpAsmInfo;
2485 delete mpDisassmbler;
2486 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002487#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002488 return;
2489 }
Zonr Chang932648d2010-10-13 22:23:56 +08002490 };
2491 // End of Class CodeEmitter
2492 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002493
Zonr Chang932648d2010-10-13 22:23:56 +08002494 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002495 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002496 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002497 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2498 return mCodeEmitter.get();
2499 }
2500
2501 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002502 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002503
Zonr Chang932648d2010-10-13 22:23:56 +08002504 llvm::LLVMContext *mContext;
2505 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002506
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002507 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002508
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002509 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002510 Compiler()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002511 : mNeverCache(true),
2512 mCacheNew(false),
2513 mCacheFd(-1),
2514 mCacheMapAddr(NULL),
2515 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002516 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002517 mCacheDiff(0),
2518 mCodeDataAddr(NULL),
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002519 mBccCodeAddrTaken(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002520 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002521 mpSymbolLookupContext(NULL),
2522 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002523 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002524 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002525 llvm::remove_fatal_error_handler();
2526 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002527 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002528 return;
2529 }
2530
Zonr Chang932648d2010-10-13 22:23:56 +08002531 // interface for BCCscript::registerSymbolCallback()
2532 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002533 mpSymbolLookupFn = pFn;
2534 mpSymbolLookupContext = pContext;
2535 return;
2536 }
2537
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002538 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002539 GlobalInitialization();
2540 mModule = module;
2541 return hasError();
2542 }
2543
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002544 int readBC(const char *bitcode,
2545 size_t bitcodeSize,
2546 const BCCchar *resName) {
2547 GlobalInitialization();
2548
2549 if (resName) {
2550 // Turn off the default NeverCaching mode
2551 mNeverCache = false;
2552
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002553 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2554 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2555 return -mCacheFd;
2556 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002557 }
2558
2559 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002560
Zonr Chang932648d2010-10-13 22:23:56 +08002561 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002562 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002563
Zonr Chang932648d2010-10-13 22:23:56 +08002564 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002565 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002566 llvm::StringRef(bitcode, bitcodeSize)));
2567
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002568 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002569 setError("Error reading input program bitcode into memory");
2570 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002571 }
2572
Zonr Chang932648d2010-10-13 22:23:56 +08002573 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002574 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2575 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002576 return hasError();
2577 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002578
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002579 int linkBC(const char *bitcode, size_t bitcodeSize) {
2580 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002581
2582 if (bitcode == NULL || bitcodeSize <= 0)
2583 return 0;
2584
2585 if (mModule == NULL) {
2586 setError("No module presents for linking");
2587 return hasError();
2588 }
2589
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002590 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002591 llvm::StringRef(bitcode, bitcodeSize)));
2592
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002593 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002594 setError("Error reading input library bitcode into memory");
2595 return hasError();
2596 }
2597
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002598 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002599 *mContext,
2600 &mError));
2601 if (Lib.get() == NULL)
2602 return hasError();
2603
2604 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2605 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002606
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002607 // Everything for linking should be settled down here with no error occurs
2608 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002609 return hasError();
2610 }
2611
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002612
2613 // interface for bccLoadBinary()
2614 int loader() {
2615 // Check File Descriptor
2616 if (mCacheFd < 0) {
2617 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2618 goto giveup;
2619 }
2620
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002621 // Check File Size
2622 struct stat statCacheFd;
2623 if (fstat(mCacheFd, &statCacheFd) < 0) {
2624 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2625 goto giveup;
2626 }
2627
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002628 mCacheSize = statCacheFd.st_size;
2629
2630 if (mCacheSize < sizeof(oBCCHeader) ||
2631 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002632 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2633 goto giveup;
2634 }
2635
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002636 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2637 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2638 goto giveup;
2639 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002640
2641 // Read File Content
2642 {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002643 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002644 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002645 LOGE("sliao@Loader: mCacheSize=%x, heuristicCodeOffset=%x", mCacheSize, heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002646
2647 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002648 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002649 flock(mCacheFd, LOCK_UN);
2650 LOGE("allocation failed.\n");
2651 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002652 }
2653
2654 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2655 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002656 if (nread != (size_t)heuristicCodeOffset) {
2657 LOGE("read(mCacheFd) failed\n");
2658 free(mCacheMapAddr);
2659 goto bail;
2660 }
2661
2662 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002663 // Sanity check
2664 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2665 LOGE("assertion failed: heuristic code offset is not correct.\n");
2666 goto bail;
2667 }
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002668 LOGE("sliao: mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2669 LOGE("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2670 LOGE("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2671 LOGE("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2672 LOGE("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002673
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002674 // Verify the Cache File
2675 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2676 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002677 goto bail;
2678 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002679
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002680 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2681 LOGE("bad oBCC version 0x%08x\n",
2682 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2683 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002684 }
2685
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002686 if (mCacheSize < mCacheHdr->relocOffset +
2687 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2688 LOGE("relocate table overflow\n");
2689 goto bail;
2690 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002691
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002692 if (mCacheSize < mCacheHdr->exportVarsOffset +
2693 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2694 LOGE("export variables table overflow\n");
2695 goto bail;
2696 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002697
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002698 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2699 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2700 LOGE("export functions table overflow\n");
2701 goto bail;
2702 }
2703
2704 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2705 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2706 LOGE("export pragmas table overflow\n");
2707 goto bail;
2708 }
2709
2710 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2711 LOGE("code cache overflow\n");
2712 goto bail;
2713 }
2714
2715 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2716 LOGE("data (global variable) cache overflow\n");
2717 goto bail;
2718 }
2719
2720 // Part 2. Deal with the codedata section
2721 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2722 MaxCodeSize + MaxGlobalVarSize,
2723 PROT_READ | PROT_EXEC | PROT_WRITE,
2724 MAP_PRIVATE | MAP_FIXED,
2725 mCacheFd, heuristicCodeOffset);
2726 if (mCodeDataAddr != MAP_FAILED &&
2727 mCodeDataAddr ==
2728 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr)) {
2729 // relocate is avoidable
2730 mBccCodeAddrTaken = true;
2731
2732 flock(mCacheFd, LOCK_UN);
2733 } else {
2734 mCacheMapAddr = (char *) mmap(0,
2735 mCacheSize,
2736 PROT_READ | PROT_EXEC | PROT_WRITE,
2737 MAP_PRIVATE,
2738 mCacheFd,
2739 0);
2740 if (mCacheMapAddr == MAP_FAILED) {
2741 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2742 flock(mCacheFd, LOCK_UN);
2743 goto giveup;
2744 }
2745
2746 flock(mCacheFd, LOCK_UN);
2747 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2748 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002749 }
2750
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002751 // Relocate
2752 {
2753 mCacheDiff = mCodeDataAddr -
2754 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2755
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002756 if (!mBccCodeAddrTaken) { // To relocate
2757 if (mCacheHdr->rootAddr) {
2758 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002759 }
2760
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002761 if (mCacheHdr->initAddr) {
2762 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002763 }
2764
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002765 oBCCRelocEntry *cachedRelocTable =
2766 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2767 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002768
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002769 std::vector<llvm::MachineRelocation> relocations;
2770
2771 // Read in the relocs
2772 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2773 oBCCRelocEntry *entry = &cachedRelocTable[i];
2774
2775 llvm::MachineRelocation reloc =
2776 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2777 (unsigned)entry->relocType, 0, 0);
2778
2779 reloc.setResultPointer(
2780 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2781
2782 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002783 }
2784
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002785 // Rewrite machine code using llvm::TargetJITInfo relocate
2786 {
2787 llvm::TargetMachine *TM = NULL;
2788 const llvm::Target *Target;
2789 std::string FeaturesStr;
2790
2791 // Create TargetMachine
2792 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2793 if (hasError())
2794 goto bail;
2795
2796 if (!CPU.empty() || !Features.empty()) {
2797 llvm::SubtargetFeatures F;
2798 F.setCPU(CPU);
2799 for (std::vector<std::string>::const_iterator I = Features.begin(),
2800 E = Features.end(); I != E; I++)
2801 F.AddFeature(*I);
2802 FeaturesStr = F.getString();
2803 }
2804
2805 TM = Target->createTargetMachine(Triple, FeaturesStr);
2806 if (TM == NULL) {
2807 setError("Failed to create target machine implementation for the"
2808 " specified triple '" + Triple + "'");
2809 goto bail;
2810 }
2811
2812 TM->getJITInfo()->relocate(mCodeDataAddr,
2813 &relocations[0], relocations.size(),
2814 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2815
2816 if (mCodeEmitter.get()) {
2817 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2818 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2819 2 * 1024 /*MaxCodeSize*/,
2820 false);
2821 }
2822
2823 delete TM;
2824 }
2825 } // End of if (!mBccCodeAddrTaken)
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002826 }
2827
2828 return 0;
2829
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002830 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002831 if (mCacheMapAddr) {
2832 free(mCacheMapAddr);
2833 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002834 if (mBccCodeAddrTaken) {
2835 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2836 LOGE("munmap failed: %s\n", strerror(errno));
2837 }
2838 } else {
2839 if (munmap(mCacheMapAddr, mCacheSize) != 0) {
2840 LOGE("munmap failed: %s\n", strerror(errno));
2841 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002842 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002843
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002844 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002845 return 1;
2846 }
2847
2848 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002849 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002850 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002851
Zonr Chang932648d2010-10-13 22:23:56 +08002852 llvm::TargetMachine *TM = NULL;
2853 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002854 std::string FeaturesStr;
2855
Zonr Chang932648d2010-10-13 22:23:56 +08002856 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002857
Zonr Chang932648d2010-10-13 22:23:56 +08002858 const llvm::NamedMDNode *PragmaMetadata;
2859 const llvm::NamedMDNode *ExportVarMetadata;
2860 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002861
Zonr Chang932648d2010-10-13 22:23:56 +08002862 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002863 return 0;
2864
Zonr Chang932648d2010-10-13 22:23:56 +08002865 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002866 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002867 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002868 goto on_bcc_compile_error;
2869
Zonr Chang932648d2010-10-13 22:23:56 +08002870 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002871 llvm::SubtargetFeatures F;
2872 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002873 for (std::vector<std::string>::const_iterator I = Features.begin(),
2874 E = Features.end();
2875 I != E;
2876 I++)
2877 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002878 FeaturesStr = F.getString();
2879 }
2880
2881 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002882 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002883 setError("Failed to create target machine implementation for the"
2884 " specified triple '" + Triple + "'");
2885 goto on_bcc_compile_error;
2886 }
2887
Zonr Chang932648d2010-10-13 22:23:56 +08002888 // Create memory manager for creation of code emitter later.
2889 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002890 setError("Failed to startup memory management for further compilation");
2891 goto on_bcc_compile_error;
2892 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002893 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002894
Zonr Chang932648d2010-10-13 22:23:56 +08002895 // Create code emitter
2896 if (!mCodeEmitter.get()) {
2897 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002898 setError("Failed to create machine code emitter to complete"
2899 " the compilation");
2900 goto on_bcc_compile_error;
2901 }
2902 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002903 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002904 mCodeEmitter->reset();
2905 }
2906
2907 mCodeEmitter->setTargetMachine(*TM);
2908 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2909 mpSymbolLookupContext);
2910
Zonr Chang932648d2010-10-13 22:23:56 +08002911 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002912 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002913
Zonr Chang5d35b972010-10-23 14:36:47 +08002914 // Load named metadata
2915 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2916 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2917 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2918
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002919 // Create LTO passes and run them on the mModule
2920 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002921 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002922 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08002923 LTOPasses.add(new llvm::TargetData(*TD));
2924
2925 std::vector<const char*> ExportSymbols;
2926
2927 // A workaround for getting export variable and function name. Will refine
2928 // it soon.
2929 if (ExportVarMetadata) {
2930 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2931 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2932 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2933 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2934 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2935 llvm::StringRef ExportVarName =
2936 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2937 ExportSymbols.push_back(ExportVarName.data());
2938 }
2939 }
2940 }
2941 }
2942
2943 if (ExportFuncMetadata) {
2944 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2945 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2946 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2947 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2948 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2949 llvm::StringRef ExportFuncName =
2950 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2951 ExportSymbols.push_back(ExportFuncName.data());
2952 }
2953 }
2954 }
2955 }
2956 // root() and init() are born to be exported
2957 ExportSymbols.push_back("root");
2958 ExportSymbols.push_back("init");
2959
Zonr Change5c7a542010-10-24 01:07:27 +08002960 // We now create passes list performing LTO. These are copied from
2961 // (including comments) llvm::createStandardLTOPasses().
2962
2963 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08002964 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002965
Zonr Change5c7a542010-10-24 01:07:27 +08002966 // Propagate constants at call sites into the functions they call. This
2967 // opens opportunities for globalopt (and inlining) by substituting
2968 // function pointers passed as arguments to direct uses of functions.
2969 LTOPasses.add(llvm::createIPSCCPPass());
2970
2971 // Now that we internalized some globals, see if we can hack on them!
2972 LTOPasses.add(llvm::createGlobalOptimizerPass());
2973
2974 // Linking modules together can lead to duplicated global constants, only
2975 // keep one copy of each constant...
2976 LTOPasses.add(llvm::createConstantMergePass());
2977
2978 // Remove unused arguments from functions...
2979 LTOPasses.add(llvm::createDeadArgEliminationPass());
2980
2981 // Reduce the code after globalopt and ipsccp. Both can open up
2982 // significant simplification opportunities, and both can propagate
2983 // functions through function pointers. When this happens, we often have
2984 // to resolve varargs calls, etc, so let instcombine do this.
2985 LTOPasses.add(llvm::createInstructionCombiningPass());
2986
2987 // Inline small functions
2988 LTOPasses.add(llvm::createFunctionInliningPass());
2989
2990 // Remove dead EH info.
2991 LTOPasses.add(llvm::createPruneEHPass());
2992
2993 // Internalize the globals again after inlining
2994 LTOPasses.add(llvm::createGlobalOptimizerPass());
2995
2996 // Remove dead functions.
2997 LTOPasses.add(llvm::createGlobalDCEPass());
2998
2999 // If we didn't decide to inline a function, check to see if we can
3000 // transform it to pass arguments by value instead of by reference.
3001 LTOPasses.add(llvm::createArgumentPromotionPass());
3002
3003 // The IPO passes may leave cruft around. Clean up after them.
3004 LTOPasses.add(llvm::createInstructionCombiningPass());
3005 LTOPasses.add(llvm::createJumpThreadingPass());
3006
3007 // Break up allocas
3008 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3009
3010 // Run a few AA driven optimizations here and now, to cleanup the code.
3011 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3012 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3013
3014 // Hoist loop invariants.
3015 LTOPasses.add(llvm::createLICMPass());
3016
3017 // Remove redundancies.
3018 LTOPasses.add(llvm::createGVNPass());
3019
3020 // Remove dead memcpys.
3021 LTOPasses.add(llvm::createMemCpyOptPass());
3022
3023 // Nuke dead stores.
3024 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3025
3026 // Cleanup and simplify the code after the scalar optimizations.
3027 LTOPasses.add(llvm::createInstructionCombiningPass());
3028
3029 LTOPasses.add(llvm::createJumpThreadingPass());
3030
3031 // Delete basic blocks, which optimization passes may have killed.
3032 LTOPasses.add(llvm::createCFGSimplificationPass());
3033
3034 // Now that we have optimized the program, discard unreachable functions.
3035 LTOPasses.add(llvm::createGlobalDCEPass());
3036
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003037 LTOPasses.run(*mModule);
3038 }
3039
Zonr Chang932648d2010-10-13 22:23:56 +08003040 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003041 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003042 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003043
Zonr Chang932648d2010-10-13 22:23:56 +08003044 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3045 *mCodeEmitter,
3046 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003047 setError("The machine code emission is not supported by BCC on target '"
3048 + Triple + "'");
3049 goto on_bcc_compile_error;
3050 }
3051
Zonr Chang932648d2010-10-13 22:23:56 +08003052 // Run the pass (the code emitter) on every non-declaration function in the
3053 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003054 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003055 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3056 I != E;
3057 I++)
3058 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003059 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003060
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003061 CodeGenPasses->doFinalization();
3062
Zonr Chang932648d2010-10-13 22:23:56 +08003063 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003064 if (ExportVarMetadata) {
3065 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3066 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3067 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3068 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3069 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003070 llvm::StringRef ExportVarName =
3071 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003072 CodeEmitter::global_addresses_const_iterator I, E;
3073 for (I = mCodeEmitter->global_address_begin(),
3074 E = mCodeEmitter->global_address_end();
3075 I != E;
3076 I++) {
3077 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003078 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003079 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003080 mExportVars.push_back(I->second);
3081 break;
3082 }
3083 }
Zonr Chang932648d2010-10-13 22:23:56 +08003084 if (I != mCodeEmitter->global_address_end())
3085 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003086 }
3087 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003088 // if reaching here, we know the global variable record in metadata is
3089 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003090 mExportVars.push_back(NULL);
3091 }
3092 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3093 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003094 }
3095
Zonr Chang932648d2010-10-13 22:23:56 +08003096 if (ExportFuncMetadata) {
3097 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3098 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3099 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3100 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3101 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003102 llvm::StringRef ExportFuncName =
3103 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3104 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3105 }
3106 }
3107 }
3108 }
3109
Zonr Chang932648d2010-10-13 22:23:56 +08003110 // Tell code emitter now can release the memory using during the JIT since
3111 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003112 mCodeEmitter->releaseUnnecessary();
3113
Zonr Chang932648d2010-10-13 22:23:56 +08003114 // Finally, read pragma information from the metadata node of the @Module if
3115 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003116 if (PragmaMetadata)
3117 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3118 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3119 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003120 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003121 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3122 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003123
Zonr Chang932648d2010-10-13 22:23:56 +08003124 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003125 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3126 llvm::StringRef PragmaName =
3127 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3128 llvm::StringRef PragmaValue =
3129 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3130
Zonr Chang932648d2010-10-13 22:23:56 +08003131 mPragmas.push_back(
3132 std::make_pair(std::string(PragmaName.data(),
3133 PragmaName.size()),
3134 std::string(PragmaValue.data(),
3135 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003136 }
3137 }
3138 }
3139
3140 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003141 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003142 if (CodeGenPasses) {
3143 delete CodeGenPasses;
3144 } else if (TD) {
3145 delete TD;
3146 }
3147 if (TM)
3148 delete TM;
3149
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003150 if (mError.empty()) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003151 if (!mNeverCache && mCacheFd >= 0 && mCacheNew) {
3152 genCacheFile();
3153 flock(mCacheFd, LOCK_UN);
3154 }
3155
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003156 return false;
3157 }
3158
Zonr Chang932648d2010-10-13 22:23:56 +08003159 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003160 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003161 }
3162
Zonr Chang932648d2010-10-13 22:23:56 +08003163 // interface for bccGetScriptInfoLog()
3164 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003165 return const_cast<char*>(mError.c_str());
3166 }
3167
Zonr Chang932648d2010-10-13 22:23:56 +08003168 // interface for bccGetScriptLabel()
3169 void *lookup(const char *name) {
3170 void *addr = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003171 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3172 if (!strcmp(name, "root")) {
3173 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3174 } else if (!strcmp(name, "init")) {
3175 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3176 }
3177 return addr;
3178 }
3179
Zonr Chang932648d2010-10-13 22:23:56 +08003180 if (mCodeEmitter.get())
3181 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003182 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003183 return addr;
3184 }
3185
Zonr Chang932648d2010-10-13 22:23:56 +08003186 // Interface for bccGetExportVars()
3187 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003188 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003189 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003190 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003191
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003192 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3193 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3194 if (actualVarCount)
3195 *actualVarCount = varCount;
3196 if (varCount > maxVarCount)
3197 varCount = maxVarCount;
3198 if (vars) {
3199 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3200 mCacheHdr->exportVarsOffset);
3201
3202 for (int i = 0; i < varCount; i++) {
3203 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3204 mCacheDiff);
3205 cachedVars++;
3206 }
3207 }
3208 return;
3209 }
3210
3211 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003212 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003213 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003214 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003215 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003216 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003217 for (ExportVarList::const_iterator I = mExportVars.begin(),
3218 E = mExportVars.end();
3219 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003220 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003221 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003222 }
3223 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003224
3225 return;
3226 }
3227
Zonr Chang932648d2010-10-13 22:23:56 +08003228 // Interface for bccGetExportFuncs()
3229 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003230 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003231 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003232 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003233
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003234 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3235 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3236 if (actualFuncCount)
3237 *actualFuncCount = funcCount;
3238 if (funcCount > maxFuncCount)
3239 funcCount = maxFuncCount;
3240 if (funcs) {
3241 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3242 mCacheHdr->exportFuncsOffset);
3243
3244 for (int i = 0; i < funcCount; i++) {
3245 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3246 mCacheDiff);
3247 cachedFuncs++;
3248 }
3249 }
3250 return;
3251 }
3252
3253 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003254 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003255 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003256 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003257 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003258 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003259 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3260 E = mExportFuncs.end();
3261 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003262 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003263 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003264 }
3265 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003266
3267 return;
3268 }
3269
Zonr Chang932648d2010-10-13 22:23:56 +08003270 // Interface for bccGetPragmas()
3271 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003272 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003273 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003274 int stringCount;
3275 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3276 if (actualStringCount)
3277 *actualStringCount = 0; // XXX
3278 return;
3279 }
3280
3281 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003282
Zonr Chang932648d2010-10-13 22:23:56 +08003283 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003284 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003285 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003286 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003287 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003288 for (PragmaList::const_iterator it = mPragmas.begin();
3289 stringCount > 0;
3290 stringCount -= 2, it++) {
3291 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3292 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003293 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003294 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003295
3296 return;
3297 }
3298
Zonr Chang932648d2010-10-13 22:23:56 +08003299 // Interface for bccGetFunctions()
3300 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003301 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003302 BCCchar **functions) {
3303 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003304 mCodeEmitter->getFunctionNames(actualFunctionCount,
3305 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003306 functions);
3307 else
3308 *actualFunctionCount = 0;
3309
3310 return;
3311 }
3312
Zonr Chang932648d2010-10-13 22:23:56 +08003313 // Interface for bccGetFunctionBinary()
3314 void getFunctionBinary(BCCchar *function,
3315 BCCvoid **base,
3316 BCCsizei *length) {
3317 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003318 mCodeEmitter->getFunctionBinary(function, base, length);
3319 } else {
3320 *base = NULL;
3321 *length = 0;
3322 }
3323 return;
3324 }
3325
Zonr Chang932648d2010-10-13 22:23:56 +08003326 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003327 return mModule;
3328 }
3329
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003330 ~Compiler() {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003331 // #ifdef BCC_CODE_ADDR
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003332 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3333 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3334 LOGE("munmap failed while releasing mCodeDataAddr\n");
3335 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003336 if (mCacheMapAddr) {
3337 free(mCacheMapAddr);
3338 }
3339 } else {
3340 if (mCacheMapAddr != 0 && mCacheMapAddr != MAP_FAILED) {
3341 if (munmap(mCacheMapAddr, mCacheSize) < 0) {
3342 LOGE("munmap failed while releasing mCacheMapAddr\n");
3343 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003344 }
3345 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003346
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003347 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003348 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003349 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003350 return;
3351 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003352
3353 private:
3354 // Note: loader() and genCacheFile() go hand in hand
3355 void genCacheFile() {
3356 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3357 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3358 return;
3359 }
3360
3361 bool codeOffsetNeedPadding = false;
3362
3363 uint32_t offset = sizeof(oBCCHeader);
3364
3365 // BCC Cache File Header
3366 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3367
3368 if (!hdr) {
3369 LOGE("Unable to allocate oBCCHeader.\n");
3370 return;
3371 }
3372
3373 // Magic Words
3374 memcpy(hdr->magic, OBCC_MAGIC, 4);
3375 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3376
3377 // Timestamp
3378 hdr->sourceWhen = 0; // TODO(all)
3379 hdr->rslibWhen = 0; // TODO(all)
3380 hdr->libRSWhen = 0; // TODO(all)
3381 hdr->libbccWhen = 0; // TODO(all)
3382
3383 // Current Memory Address (Saved for Recalculation)
3384 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3385 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3386 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3387
3388 // Relocation Table Offset and Entry Count
3389 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003390 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003391
Logan824dd0a2010-11-20 01:45:54 +08003392 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003393
3394 // Export Variable Table Offset and Entry Count
3395 hdr->exportVarsOffset = offset;
3396 hdr->exportVarsCount = mExportVars.size();
3397
3398 offset += hdr->exportVarsCount * sizeof(uint32_t);
3399
3400 // Export Function Table Offset and Entry Count
3401 hdr->exportFuncsOffset = offset;
3402 hdr->exportFuncsCount = mExportFuncs.size();
3403
3404 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3405
3406 // Export Pragmas Table Offset and Entry Count
3407 hdr->exportPragmasOffset = offset;
3408 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3409
3410 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3411
3412 // Code Offset and Size
3413
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003414 //#ifdef BCC_CODE_ADDR
3415 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003416 long pagesize = sysconf(_SC_PAGESIZE);
3417
3418 if (offset % pagesize > 0) {
3419 codeOffsetNeedPadding = true;
3420 offset += pagesize - (offset % pagesize);
3421 }
3422 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003423 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003424 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3425 codeOffsetNeedPadding = true;
3426 offset += 0x08 - (offset & 0x07);
3427 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003428 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003429
3430 hdr->codeOffset = offset;
3431 hdr->codeSize = MaxCodeSize;
3432
3433 offset += hdr->codeSize;
3434
3435 // Data (Global Variable) Offset and Size
3436 hdr->dataOffset = offset;
3437 hdr->dataSize = MaxGlobalVarSize;
3438
3439 offset += hdr->dataSize;
3440
3441 // Checksum
3442 hdr->checksum = 0; // Set Field checksum. TODO(all)
3443
3444 // Write Header
3445 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3446 sizeof(oBCCHeader), "Write oBCC header");
3447
Logan824dd0a2010-11-20 01:45:54 +08003448 // Write Relocation Entry Table
3449 {
3450 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003451
Logan824dd0a2010-11-20 01:45:54 +08003452 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3453
3454 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3455 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003456 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003457
3458 // Write Export Variables Table
3459 {
3460 uint32_t *record, *ptr;
3461
3462 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3463 ptr = record;
3464
3465 if (!record) {
3466 goto bail;
3467 }
3468
3469 for (ExportVarList::const_iterator I = mExportVars.begin(),
3470 E = mExportVars.end(); I != E; I++) {
3471 *ptr++ = reinterpret_cast<uint32_t>(*I);
3472 }
3473
3474 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3475 hdr->exportVarsCount * sizeof(uint32_t),
3476 "Write ExportVars");
3477
3478 free(record);
3479 }
3480
3481 // Write Export Functions Table
3482 {
3483 uint32_t *record, *ptr;
3484
3485 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3486 ptr = record;
3487
3488 if (!record) {
3489 goto bail;
3490 }
3491
3492 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3493 E = mExportFuncs.end(); I != E; I++) {
3494 *ptr++ = reinterpret_cast<uint32_t>(*I);
3495 }
3496
3497 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3498 hdr->exportFuncsCount * sizeof(uint32_t),
3499 "Write ExportFuncs");
3500
3501 free(record);
3502 }
3503
3504
3505 // TODO(all): Write Export Pragmas Table
3506#if 0
3507#else
3508 // Note: As long as we have comment out export pragmas table code,
3509 // we have to seek the position to correct offset.
3510
3511 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3512#endif
3513
3514 if (codeOffsetNeedPadding) {
3515 // requires additional padding
3516 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3517 }
3518
3519 // Write Generated Code and Global Variable
3520 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3521 "Write code and global variable");
3522
3523 goto close_return;
3524
3525 bail:
3526 if (ftruncate(mCacheFd, 0) != 0) {
3527 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3528 }
3529
3530 close_return:
3531 free(hdr);
3532 close(mCacheFd);
3533 mCacheFd = -1;
3534 return;
3535 }
3536
3537 // OpenCacheFile() returns fd of the cache file.
3538 // Input:
3539 // BCCchar *resName: Used to genCacheFileName()
3540 // bool createIfMissing: If false, turn off caching
3541 // Output:
3542 // returns fd: If -1: Failed
3543 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3544 // cache file's file descriptor
3545 // Note: openCacheFile() will check the cache file's validity,
3546 // such as Magic number, sourceWhen... dependencies.
3547 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3548 int fd, cc;
3549 struct stat fdStat, fileStat;
3550 bool readOnly = false;
3551
3552 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3553
3554 mCacheNew = false;
3555
3556 retry:
3557 /*
3558 * Try to open the cache file. If we've been asked to,
3559 * create it if it doesn't exist.
3560 */
3561 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3562 if (fd < 0) {
3563 fd = open(cacheFileName, O_RDONLY, 0);
3564 if (fd < 0) {
3565 if (createIfMissing) {
Shih-wei Liao30a51502010-11-22 03:23:30 -08003566 LOGW("Can't open bcc-cache '%s': %s\n",
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003567 cacheFileName, strerror(errno));
Shih-wei Liao30a51502010-11-22 03:23:30 -08003568 mNeverCache = true;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003569 }
3570 return fd;
3571 }
3572 readOnly = true;
3573 }
3574
3575 /*
3576 * Grab an exclusive lock on the cache file. If somebody else is
3577 * working on it, we'll block here until they complete.
3578 */
3579 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3580 cacheFileName, fd);
3581
3582 cc = flock(fd, LOCK_EX | LOCK_NB);
3583 if (cc != 0) {
3584 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3585 cc = flock(fd, LOCK_EX);
3586 }
3587
3588 if (cc != 0) {
3589 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3590 close(fd);
3591 return -1;
3592 }
3593 LOGV("bcc: locked cache file\n");
3594
3595 /*
3596 * Check to see if the fd we opened and locked matches the file in
3597 * the filesystem. If they don't, then somebody else unlinked ours
3598 * and created a new file, and we need to use that one instead. (If
3599 * we caught them between the unlink and the create, we'll get an
3600 * ENOENT from the file stat.)
3601 */
3602 cc = fstat(fd, &fdStat);
3603 if (cc != 0) {
3604 LOGE("Can't stat open file '%s'\n", cacheFileName);
3605 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3606 goto close_fail;
3607 }
3608 cc = stat(cacheFileName, &fileStat);
3609 if (cc != 0 ||
3610 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3611 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3612 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3613 flock(fd, LOCK_UN);
3614 close(fd);
3615 usleep(250 * 1000); // if something is hosed, don't peg machine
3616 goto retry;
3617 }
3618
3619 /*
3620 * We have the correct file open and locked. If the file size is zero,
3621 * then it was just created by us, and we want to fill in some fields
3622 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3623 * verify that the fields in the header match our expectations, and
3624 * reset the file if they don't.
3625 */
3626 if (fdStat.st_size == 0) {
3627 if (readOnly) { // The device is readOnly --> close_fail
3628 LOGW("bcc: file has zero length and isn't writable\n");
3629 goto close_fail;
3630 }
3631 /*cc = createEmptyHeader(fd);
3632 if (cc != 0)
3633 goto close_fail;
3634 */
3635 mCacheNew = true;
3636 LOGV("bcc: successfully initialized new cache file\n");
3637 } else {
3638 // Calculate sourceWhen
3639 // XXX
3640 uint32_t sourceWhen = 0;
3641 uint32_t rslibWhen = 0;
3642 uint32_t libRSWhen = 0;
3643 uint32_t libbccWhen = 0;
3644 if (!checkHeaderAndDependencies(fd,
3645 sourceWhen,
3646 rslibWhen,
3647 libRSWhen,
3648 libbccWhen)) {
3649 // If checkHeaderAndDependencies returns 0: FAILED
3650 // Will truncate the file and retry to createIfMissing the file
3651
3652 if (readOnly) { // Shouldn't be readonly.
3653 /*
3654 * We could unlink and rewrite the file if we own it or
3655 * the "sticky" bit isn't set on the directory. However,
3656 * we're not able to truncate it, which spoils things. So,
3657 * give up now.
3658 */
3659 if (createIfMissing) {
3660 LOGW("Cached file %s is stale and not writable\n",
3661 cacheFileName);
3662 }
3663 goto close_fail;
3664 }
3665
3666 /*
3667 * If we truncate the existing file before unlinking it, any
3668 * process that has it mapped will fail when it tries to touch
3669 * the pages? Probably OK because we use MAP_PRIVATE.
3670 */
3671 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3672 cacheFileName);
3673 if (ftruncate(fd, 0) != 0) {
3674 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3675 cacheFileName, strerror(errno));
3676 /* keep going */
3677 }
3678 if (unlink(cacheFileName) != 0) {
3679 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3680 cacheFileName, errno, strerror(errno));
3681 /* keep going; permission failure should probably be fatal */
3682 }
3683 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3684 flock(fd, LOCK_UN);
3685 close(fd);
3686 goto retry;
3687 } else {
3688 // Got cacheFile! Good to go.
3689 LOGV("Good cache file\n");
3690 }
3691 }
3692
3693 assert(fd >= 0);
3694 return fd;
3695
3696 close_fail:
3697 flock(fd, LOCK_UN);
3698 close(fd);
3699 return -1;
3700 } // End of openCacheFile()
3701
3702 char *genCacheFileName(const char *fileName, const char *subFileName) {
3703 char nameBuf[512];
3704 static const char kCachePath[] = "bcc-cache";
3705 char absoluteFile[sizeof(nameBuf)];
3706 const size_t kBufLen = sizeof(nameBuf) - 1;
3707 const char *dataRoot;
3708 char *cp;
3709
3710 // Get the absolute path of the raw/***.bc file.
3711 absoluteFile[0] = '\0';
3712 if (fileName[0] != '/') {
3713 /*
3714 * Generate the absolute path. This doesn't do everything it
3715 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3716 * the leading "./" out, but it'll do.
3717 */
3718 if (getcwd(absoluteFile, kBufLen) == NULL) {
3719 LOGE("Can't get CWD while opening raw/***.bc file\n");
3720 return NULL;
3721 }
3722 // TODO(srhines): strncat() is a bit dangerous
3723 strncat(absoluteFile, "/", kBufLen);
3724 }
3725 strncat(absoluteFile, fileName, kBufLen);
3726
3727 if (subFileName != NULL) {
3728 strncat(absoluteFile, "/", kBufLen);
3729 strncat(absoluteFile, subFileName, kBufLen);
3730 }
3731
3732 /* Turn the path into a flat filename by replacing
3733 * any slashes after the first one with '@' characters.
3734 */
3735 cp = absoluteFile + 1;
3736 while (*cp != '\0') {
3737 if (*cp == '/') {
3738 *cp = '@';
3739 }
3740 cp++;
3741 }
3742
3743 /* Build the name of the cache directory.
3744 */
3745 dataRoot = getenv("ANDROID_DATA");
3746 if (dataRoot == NULL)
3747 dataRoot = "/data";
3748 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3749
3750 /* Tack on the file name for the actual cache file path.
3751 */
3752 strncat(nameBuf, absoluteFile, kBufLen);
3753
3754 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3755 return strdup(nameBuf);
3756 }
3757
3758 /*
3759 * Read the oBCC header, verify it, then read the dependent section
3760 * and verify that data as well.
3761 *
3762 * On successful return, the file will be seeked immediately past the
3763 * oBCC header.
3764 */
3765 bool checkHeaderAndDependencies(int fd,
3766 uint32_t sourceWhen,
3767 uint32_t rslibWhen,
3768 uint32_t libRSWhen,
3769 uint32_t libbccWhen) {
3770 ssize_t actual;
3771 oBCCHeader optHdr;
3772 uint32_t val;
3773 uint8_t const *magic, *magicVer;
3774
3775 /*
3776 * Start at the start. The "bcc" header, when present, will always be
3777 * the first thing in the file.
3778 */
3779 if (lseek(fd, 0, SEEK_SET) != 0) {
3780 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3781 goto bail;
3782 }
3783
3784 /*
3785 * Read and do trivial verification on the bcc header. The header is
3786 * always in host byte order.
3787 */
3788 actual = read(fd, &optHdr, sizeof(optHdr));
3789 if (actual < 0) {
3790 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3791 goto bail;
3792 } else if (actual != sizeof(optHdr)) {
3793 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3794 (int) actual, sizeof(optHdr));
3795 goto bail;
3796 }
3797
3798 magic = optHdr.magic;
3799 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3800 /* not an oBCC file, or previous attempt was interrupted */
3801 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3802 magic[0], magic[1], magic[2], magic[3]);
3803 goto bail;
3804 }
3805
3806 magicVer = optHdr.magicVersion;
3807 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3808 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3809 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3810 goto bail;
3811 }
3812
3813 /*
3814 * Do the header flags match up with what we want?
3815 *
3816 * This is useful because it allows us to automatically regenerate
3817 * a file when settings change (e.g. verification is now mandatory),
3818 * but can cause difficulties if the thing we depend upon
3819 * were handled differently than the current options specify.
3820 *
3821 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3822 * by limiting the match mask.
3823 *
3824 * The only thing we really can't handle is incorrect byte-ordering.
3825 */
3826
3827 val = optHdr.sourceWhen;
3828 if (val && (val != sourceWhen)) {
3829 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3830 val, sourceWhen);
3831 goto bail;
3832 }
3833 val = optHdr.rslibWhen;
3834 if (val && (val != rslibWhen)) {
3835 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3836 val, rslibWhen);
3837 goto bail;
3838 }
3839 val = optHdr.libRSWhen;
3840 if (val && (val != libRSWhen)) {
3841 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3842 val, libRSWhen);
3843 goto bail;
3844 }
3845 val = optHdr.libbccWhen;
3846 if (val && (val != libbccWhen)) {
3847 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3848 val, libbccWhen);
3849 goto bail;
3850 }
3851
3852 return true;
3853
3854 bail:
3855 return false;
3856 }
3857
Zonr Chang932648d2010-10-13 22:23:56 +08003858};
3859// End of Class Compiler
3860////////////////////////////////////////////////////////////////////////////////
3861
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003862
3863bool Compiler::GlobalInitialized = false;
3864
Zonr Chang932648d2010-10-13 22:23:56 +08003865// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003866llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3867
3868std::string Compiler::Triple;
3869
3870std::string Compiler::CPU;
3871
3872std::vector<std::string> Compiler::Features;
3873
Zonr Chang932648d2010-10-13 22:23:56 +08003874// The named of metadata node that pragma resides (should be synced with
3875// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003876const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3877
Zonr Chang932648d2010-10-13 22:23:56 +08003878// The named of metadata node that export variable name resides (should be
3879// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003880const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3881
Zonr Chang932648d2010-10-13 22:23:56 +08003882// The named of metadata node that export function name resides (should be
3883// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003884const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3885
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003886struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003887 //////////////////////////////////////////////////////////////////////////////
3888 // Part I. Compiler
3889 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003890 Compiler compiler;
3891
Zonr Chang932648d2010-10-13 22:23:56 +08003892 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003893 compiler.registerSymbolCallback(pFn, pContext);
3894 }
3895
Zonr Chang932648d2010-10-13 22:23:56 +08003896 //////////////////////////////////////////////////////////////////////////////
3897 // Part II. Logistics & Error handling
3898 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003899 BCCscript() {
3900 bccError = BCC_NO_ERROR;
3901 }
3902
3903 ~BCCscript() {
3904 }
3905
3906 void setError(BCCenum error) {
3907 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3908 bccError = error;
3909 }
3910 }
3911
3912 BCCenum getError() {
3913 BCCenum result = bccError;
3914 bccError = BCC_NO_ERROR;
3915 return result;
3916 }
3917
3918 BCCenum bccError;
3919};
3920
3921
3922extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003923BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003924 return new BCCscript();
3925}
3926
3927extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003928BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003929 return script->getError();
3930}
3931
3932extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003933void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003934 delete script;
3935}
3936
3937extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003938void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003939 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08003940 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003941 script->registerSymbolCallback(pFn, pContext);
3942}
3943
3944extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003945int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08003946 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003947 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08003948}
3949
3950extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003951int bccReadBC(BCCscript *script,
3952 const BCCchar *bitcode,
3953 BCCint size,
3954 const BCCchar *resName) {
3955 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003956}
3957
3958extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003959void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08003960 const BCCchar *bitcode,
3961 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003962 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08003963}
3964
3965extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003966void bccLoadBinary(BCCscript *script) {
3967 int result = script->compiler.loader();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003968 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003969 script->setError(BCC_INVALID_OPERATION);
3970}
3971
3972extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003973void bccCompileBC(BCCscript *script) {
3974 {
3975#if defined(__arm__)
3976 android::StopWatch compileTimer("RenderScript compile time");
3977#endif
3978 int result = script->compiler.compile();
3979 if (result)
3980 script->setError(BCC_INVALID_OPERATION);
3981 }
3982}
3983
3984extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003985void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003986 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08003987 BCCsizei *length,
3988 BCCchar *infoLog) {
3989 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003990 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003991 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003992 *length = messageLength;
3993
3994 if (infoLog && maxLength > 0) {
3995 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
3996 memcpy(infoLog, message, trimmedLength);
3997 infoLog[trimmedLength] = 0;
3998 }
3999}
4000
4001extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004002void bccGetScriptLabel(BCCscript *script,
4003 const BCCchar *name,
4004 BCCvoid **address) {
4005 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004006 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004007 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004008 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004009 script->setError(BCC_INVALID_VALUE);
4010}
4011
4012extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004013void bccGetExportVars(BCCscript *script,
4014 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004015 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004016 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004017 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4018}
4019
4020extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004021void bccGetExportFuncs(BCCscript *script,
4022 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004023 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004024 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004025 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4026}
4027
4028extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004029void bccGetPragmas(BCCscript *script,
4030 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004031 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004032 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004033 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4034}
4035
4036extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004037void bccGetFunctions(BCCscript *script,
4038 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004039 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004040 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004041 script->compiler.getFunctions(actualFunctionCount,
4042 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004043 functions);
4044}
4045
4046extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004047void bccGetFunctionBinary(BCCscript *script,
4048 BCCchar *function,
4049 BCCvoid **base,
4050 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004051 script->compiler.getFunctionBinary(function, base, length);
4052}
4053
4054struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004055 const Compiler *compiler;
4056 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004057};
4058
Zonr Chang932648d2010-10-13 22:23:56 +08004059} // namespace bcc