blob: 8e9371c29c0558b06edde51e58dd2ca8ab7b9dbe [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 Liao7c5a5f72010-11-08 01:59:13 -0800573 mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
574 MaxCodeSize + MaxGlobalVarSize,
575 PROT_READ | PROT_EXEC | PROT_WRITE,
576 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
577 -1,
578 0);
Shih-wei Liao1f45b862010-11-21 23:22:38 -0800579
580 if (mpCodeMem == MAP_FAILED) {
581 mpCodeMem = mmap(NULL,
582 MaxCodeSize + MaxGlobalVarSize,
583 PROT_READ | PROT_EXEC | PROT_WRITE,
584 MAP_PRIVATE | MAP_ANON,
585 -1,
586 0);
587 } else {
588 // mBccCodeAddrTaken = true;
589 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800590
591 if (mpCodeMem == MAP_FAILED) {
592 llvm::report_fatal_error("Failed to allocate memory for emitting "
593 "codes\n" + ErrMsg);
594 }
595 mpGVMem = (void *) ((int) mpCodeMem + MaxCodeSize);
596
597 /* mpCodeMem = mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700598 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700599 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800600 llvm::report_fatal_error("Failed to allocate memory for emitting "
601 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700602
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800603 mpGVMem = mmap(mpCodeMem, MaxGlobalVarSize,
604 PROT_READ | PROT_WRITE,
605 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700606 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800607 llvm::report_fatal_error("Failed to allocate memory for emitting "
608 "global variables\n" + ErrMsg);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800609 */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700610 return;
611 }
612
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800613 inline uint8_t *getCodeMemBase() const {
614 return reinterpret_cast<uint8_t*>(mpCodeMem);
615 }
616
Zonr Chang932648d2010-10-13 22:23:56 +0800617 // setMemoryWritable - When code generation is in progress, the code pages
618 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700619 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700620 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700621 return;
622 }
623
Zonr Chang932648d2010-10-13 22:23:56 +0800624 // When code generation is done and we're ready to start execution, the
625 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700626 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700627 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700628 return;
629 }
630
Zonr Chang932648d2010-10-13 22:23:56 +0800631 // Setting this flag to true makes the memory manager garbage values over
632 // freed memory. This is useful for testing and debugging, and is to be
633 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700634 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800635 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700636 return;
637 }
638
Zonr Chang932648d2010-10-13 22:23:56 +0800639 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700640
Zonr Chang932648d2010-10-13 22:23:56 +0800641 // If the current table requires a Global Offset Table, this method is
642 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700643 void AllocateGOT() {
644 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700645 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700646 HasGOT = true;
647 return;
648 }
649
Zonr Chang932648d2010-10-13 22:23:56 +0800650 // If this is managing a Global Offset Table, this method should return a
651 // pointer to its base.
652 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700653 return mpGOTBase;
654 }
655
Zonr Chang932648d2010-10-13 22:23:56 +0800656 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700657
Zonr Chang932648d2010-10-13 22:23:56 +0800658 // When we start JITing a function, the JIT calls this method to allocate a
659 // block of free RWX memory, which returns a pointer to it. If the JIT wants
660 // to request a block of memory of at least a certain size, it passes that
661 // value as ActualSize, and this method returns a block with at least that
662 // much space. If the JIT doesn't know ahead of time how much space it will
663 // need to emit the function, it passes 0 for the ActualSize. In either
664 // case, this method is required to pass back the size of the allocated
665 // block through ActualSize. The JIT will be careful to not write more than
666 // the returned ActualSize bytes of memory.
667 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
668 intptr_t FreeMemSize = getFreeCodeMemSize();
669 if ((FreeMemSize < 0) ||
670 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
671 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700672 return NULL;
673
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700674 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700675 return (getCodeMemBase() + mCurFuncMemIdx);
676 }
677
Zonr Chang932648d2010-10-13 22:23:56 +0800678 // This method is called by the JIT to allocate space for a function stub
679 // (used to handle limited branch displacements) while it is JIT compiling a
680 // function. For example, if foo calls bar, and if bar either needs to be
681 // lazily compiled or is a native function that exists too far away from the
682 // call site to work, this method will be used to make a thunk for it. The
683 // stub should be "close" to the current function body, but should not be
684 // included in the 'actualsize' returned by startFunctionBody.
685 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700686 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700687 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700688 }
689
Zonr Chang932648d2010-10-13 22:23:56 +0800690 // This method is called when the JIT is done codegen'ing the specified
691 // function. At this point we know the size of the JIT compiled function.
692 // This passes in FunctionStart (which was returned by the startFunctionBody
693 // method) and FunctionEnd which is a pointer to the actual end of the
694 // function. This method should mark the space allocated and remember where
695 // it is in case the client wants to deallocate it.
696 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
697 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700698 assert(FunctionEnd > FunctionStart);
699 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
700 "Mismatched function start/end!");
701
Zonr Chang932648d2010-10-13 22:23:56 +0800702 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700703 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700704 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700705 "Code size excess the limitation!");
706 mCurFuncMemIdx += FunctionCodeSize;
707
Zonr Chang932648d2010-10-13 22:23:56 +0800708 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700709 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
710 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800711 mFunctionMap.insert(
712 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
713 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700714
715 return;
716 }
717
Zonr Chang932648d2010-10-13 22:23:56 +0800718 // Allocate a (function code) memory block of the given size. This method
719 // cannot be called between calls to startFunctionBody and endFunctionBody.
720 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
721 if (getFreeCodeMemSize() < Size)
722 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700723 return NULL;
724
Zonr Chang932648d2010-10-13 22:23:56 +0800725 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700726 Alignment = 1;
727
Zonr Chang932648d2010-10-13 22:23:56 +0800728 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700729 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800730 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700731
732 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
733
734 return result;
735 }
736
Zonr Chang932648d2010-10-13 22:23:56 +0800737 // Allocate memory for a global variable.
738 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700739 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800740 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700741 LOGE("No Global Memory");
742 return NULL;
743 }
744
Zonr Chang932648d2010-10-13 22:23:56 +0800745 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700746 Alignment = 1;
747
Zonr Chang932648d2010-10-13 22:23:56 +0800748 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700749 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800750 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700751
752 mCurGVMemIdx = (result + Size) - getGVMemBase();
753
754 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700755 }
756
Zonr Chang932648d2010-10-13 22:23:56 +0800757 // Free the specified function body. The argument must be the return value
758 // from a call to startFunctionBody() that hasn't been deallocated yet. This
759 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700760 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800761 // linear search
762 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
763 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
764 E = mFunctionMap.end();
765 I != E;
766 I++)
767 if (I->second.first == Body) {
768 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
769 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700770 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800771 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700772
Zonr Chang932648d2010-10-13 22:23:56 +0800773 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700774
Zonr Chang932648d2010-10-13 22:23:56 +0800775 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700776 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
777
778 assert(SizeNeedMove >= 0 &&
779 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
780 " be correctly calculated!");
781
Zonr Chang932648d2010-10-13 22:23:56 +0800782 if (SizeNeedMove > 0)
783 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700784 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
785 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
786
787 return;
788 }
789
Zonr Chang932648d2010-10-13 22:23:56 +0800790 // When we finished JITing the function, if exception handling is set, we
791 // emit the exception table.
792 uint8_t *startExceptionTable(const llvm::Function *F,
793 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700794 assert(false && "Exception is not allowed in our language specification");
795 return NULL;
796 }
797
Zonr Chang932648d2010-10-13 22:23:56 +0800798 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700799 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800800 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700801 assert(false && "Exception is not allowed in our language specification");
802 return;
803 }
804
Zonr Chang932648d2010-10-13 22:23:56 +0800805 // Free the specified exception table's memory. The argument must be the
806 // return value from a call to startExceptionTable() that hasn't been
807 // deallocated yet. This is never called when the JIT is currently emitting
808 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700809 void deallocateExceptionTable(void *ET) {
810 assert(false && "Exception is not allowed in our language specification");
811 return;
812 }
813
Zonr Chang932648d2010-10-13 22:23:56 +0800814 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700815 void reset() {
816 mpGOTBase = NULL;
817 HasGOT = false;
818
819 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700820 mCurSGMemIdx = MaxCodeSize - 1;
821 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700822
823 mFunctionMap.clear();
824
825 return;
826 }
827
828 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800829 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700830 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800831 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700832 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700833 return;
834 }
Zonr Chang932648d2010-10-13 22:23:56 +0800835 };
836 // End of class CodeMemoryManager
837 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700838
Zonr Chang932648d2010-10-13 22:23:56 +0800839 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700840 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800841 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700842 mCodeMemMgr.reset(new CodeMemoryManager());
843 return mCodeMemMgr.get();
844 }
845
Zonr Chang932648d2010-10-13 22:23:56 +0800846 //////////////////////////////////////////////////////////////////////////////
847 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700848 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700849 public:
850 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
851 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
852
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800853 GlobalAddressMapTy mGlobalAddressMap;
854
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700855 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800856 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700857
Zonr Chang932648d2010-10-13 22:23:56 +0800858 // The JITInfo for the target we are compiling to
859 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700860
Zonr Chang932648d2010-10-13 22:23:56 +0800861 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700862
Zonr Chang932648d2010-10-13 22:23:56 +0800863 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700864
865 class EmittedFunctionCode {
866 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800867 // Beginning of the function's allocation.
868 void *FunctionBody;
869
870 // The address the function's code actually starts at.
871 void *Code;
872
873 // The size of the function code
874 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700875
876 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
877 };
Zonr Chang932648d2010-10-13 22:23:56 +0800878 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700879
Zonr Chang932648d2010-10-13 22:23:56 +0800880 typedef std::map<const std::string,
881 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700882 EmittedFunctionsMapTy mEmittedFunctions;
883
Zonr Chang932648d2010-10-13 22:23:56 +0800884 // This vector is a mapping from MBB ID's to their address. It is filled in
885 // by the StartMachineBasicBlock callback and queried by the
886 // getMachineBasicBlockAddress callback.
887 std::vector<uintptr_t> mMBBLocations;
888
889 // The constant pool for the current function.
890 llvm::MachineConstantPool *mpConstantPool;
891
892 // A pointer to the first entry in the constant pool.
893 void *mpConstantPoolBase;
894
895 // Addresses of individual constant pool entries.
896 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
897
898 // The jump tables for the current function.
899 llvm::MachineJumpTableInfo *mpJumpTable;
900
901 // A pointer to the first entry in the jump table.
902 void *mpJumpTableBase;
903
904 // When outputting a function stub in the context of some other function, we
905 // save BufferBegin/BufferEnd/CurBufferPtr here.
906 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
907
908 // These are the relocations that the function needs, as emitted.
909 std::vector<llvm::MachineRelocation> mRelocations;
910
Logan824dd0a2010-11-20 01:45:54 +0800911 std::vector<oBCCRelocEntry> mCachingRelocations;
912
Zonr Chang932648d2010-10-13 22:23:56 +0800913 // This vector is a mapping from Label ID's to their address.
914 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
915
916 // Machine module info for exception informations
917 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700918
Zonr Chang932648d2010-10-13 22:23:56 +0800919 // Replace an existing mapping for GV with a new address. This updates both
920 // maps as required. If Addr is null, the entry for the global is removed
921 // from the mappings.
922 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
923 if (Addr == NULL) {
924 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700925 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
926 void *OldVal;
927
Zonr Chang932648d2010-10-13 22:23:56 +0800928 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700929 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800930 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700931 OldVal = I->second;
932 mGlobalAddressMap.erase(I);
933 }
934
935 return OldVal;
936 }
937
Zonr Chang932648d2010-10-13 22:23:56 +0800938 void *&CurVal = mGlobalAddressMap[GV];
939 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700940
941 CurVal = Addr;
942
943 return OldVal;
944 }
945
Zonr Chang932648d2010-10-13 22:23:56 +0800946 // Tell the execution engine that the specified global is at the specified
947 // location. This is used internally as functions are JIT'd and as global
948 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700949 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800950 void *&CurVal = mGlobalAddressMap[GV];
951 assert((CurVal == 0 || Addr == 0) &&
952 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700953 CurVal = Addr;
954 return;
955 }
956
Zonr Chang932648d2010-10-13 22:23:56 +0800957 // This returns the address of the specified global value if it is has
958 // already been codegen'd, otherwise it returns null.
959 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700960 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700961 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
962 }
963
Zonr Chang932648d2010-10-13 22:23:56 +0800964 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
965 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700966 MCP->getConstants();
967
Zonr Chang932648d2010-10-13 22:23:56 +0800968 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700969 return 0;
970
971 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800972 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700973 llvm::MachineConstantPoolEntry CPE = Constants[i];
974 unsigned int AlignMask = CPE.getAlignment() - 1;
975 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800976 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700977 Size += mpTD->getTypeAllocSize(Ty);
978 }
979
980 return Size;
981 }
982
Zonr Chang932648d2010-10-13 22:23:56 +0800983 // This function converts a Constant* into a GenericValue. The interesting
984 // part is if C is a ConstantExpr.
985 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
986 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700987 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800988 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
989 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
990 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700991
Zonr Chang932648d2010-10-13 22:23:56 +0800992 switch (CE->getOpcode()) {
993 case llvm::Instruction::GetElementPtr: {
994 // Compute the index
995 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
996 CE->op_end());
997 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
998 &Indices[0],
999 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001000
Zonr Chang932648d2010-10-13 22:23:56 +08001001 GetConstantValue(Op0, Result);
1002 Result.PointerVal =
1003 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001004
Zonr Chang932648d2010-10-13 22:23:56 +08001005 return;
1006 }
1007 case llvm::Instruction::Trunc: {
1008 uint32_t BitWidth =
1009 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1010
1011 GetConstantValue(Op0, Result);
1012 Result.IntVal = Result.IntVal.trunc(BitWidth);
1013
1014 return;
1015 }
1016 case llvm::Instruction::ZExt: {
1017 uint32_t BitWidth =
1018 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1019
1020 GetConstantValue(Op0, Result);
1021 Result.IntVal = Result.IntVal.zext(BitWidth);
1022
1023 return;
1024 }
1025 case llvm::Instruction::SExt: {
1026 uint32_t BitWidth =
1027 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1028
1029 GetConstantValue(Op0, Result);
1030 Result.IntVal = Result.IntVal.sext(BitWidth);
1031
1032 return;
1033 }
1034 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001035 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001036 GetConstantValue(Op0, Result);
1037 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1038 return;
1039 }
1040 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001041 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001042 GetConstantValue(Op0, Result);
1043 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1044 return;
1045 }
1046 case llvm::Instruction::UIToFP: {
1047 GetConstantValue(Op0, Result);
1048 if (CE->getType()->isFloatTy())
1049 Result.FloatVal =
1050 static_cast<float>(Result.IntVal.roundToDouble());
1051 else if (CE->getType()->isDoubleTy())
1052 Result.DoubleVal = Result.IntVal.roundToDouble();
1053 else if (CE->getType()->isX86_FP80Ty()) {
1054 const uint64_t zero[] = { 0, 0 };
1055 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1056 apf.convertFromAPInt(Result.IntVal,
1057 false,
1058 llvm::APFloat::rmNearestTiesToEven);
1059 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001060 }
Zonr Chang932648d2010-10-13 22:23:56 +08001061 return;
1062 }
1063 case llvm::Instruction::SIToFP: {
1064 GetConstantValue(Op0, Result);
1065 if (CE->getType()->isFloatTy())
1066 Result.FloatVal =
1067 static_cast<float>(Result.IntVal.signedRoundToDouble());
1068 else if (CE->getType()->isDoubleTy())
1069 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1070 else if (CE->getType()->isX86_FP80Ty()) {
1071 const uint64_t zero[] = { 0, 0 };
1072 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1073 apf.convertFromAPInt(Result.IntVal,
1074 true,
1075 llvm::APFloat::rmNearestTiesToEven);
1076 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001077 }
Zonr Chang932648d2010-10-13 22:23:56 +08001078 return;
1079 }
1080 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001081 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001082 case llvm::Instruction::FPToSI: {
1083 uint32_t BitWidth =
1084 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001085
Zonr Chang932648d2010-10-13 22:23:56 +08001086 GetConstantValue(Op0, Result);
1087 if (Op0->getType()->isFloatTy())
1088 Result.IntVal =
1089 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1090 else if (Op0->getType()->isDoubleTy())
1091 Result.IntVal =
1092 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1093 BitWidth);
1094 else if (Op0->getType()->isX86_FP80Ty()) {
1095 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1096 uint64_t V;
1097 bool Ignored;
1098 apf.convertToInteger(&V,
1099 BitWidth,
1100 CE->getOpcode() == llvm::Instruction::FPToSI,
1101 llvm::APFloat::rmTowardZero,
1102 &Ignored);
1103 Result.IntVal = V; // endian?
1104 }
1105 return;
1106 }
1107 case llvm::Instruction::PtrToInt: {
1108 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1109
1110 GetConstantValue(Op0, Result);
1111 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1112 (Result.PointerVal));
1113
1114 return;
1115 }
1116 case llvm::Instruction::IntToPtr: {
1117 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1118
1119 GetConstantValue(Op0, Result);
1120 if (PtrWidth != Result.IntVal.getBitWidth())
1121 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1122 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1123
1124 Result.PointerVal =
1125 llvm::PointerTy(
1126 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1127
1128 return;
1129 }
1130 case llvm::Instruction::BitCast: {
1131 GetConstantValue(Op0, Result);
1132 const llvm::Type *DestTy = CE->getType();
1133
1134 switch (Op0->getType()->getTypeID()) {
1135 case llvm::Type::IntegerTyID: {
1136 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1137 if (DestTy->isFloatTy())
1138 Result.FloatVal = Result.IntVal.bitsToFloat();
1139 else if (DestTy->isDoubleTy())
1140 Result.DoubleVal = Result.IntVal.bitsToDouble();
1141 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001142 }
Zonr Chang932648d2010-10-13 22:23:56 +08001143 case llvm::Type::FloatTyID: {
1144 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1145 Result.IntVal.floatToBits(Result.FloatVal);
1146 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001147 }
Zonr Chang932648d2010-10-13 22:23:56 +08001148 case llvm::Type::DoubleTyID: {
1149 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1150 Result.IntVal.doubleToBits(Result.DoubleVal);
1151 break;
1152 }
1153 case llvm::Type::PointerTyID: {
1154 assert(DestTy->isPointerTy() && "Invalid bitcast");
1155 break; // getConstantValue(Op0) above already converted it
1156 }
1157 default: {
1158 llvm_unreachable("Invalid bitcast operand");
1159 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001160 }
Zonr Chang932648d2010-10-13 22:23:56 +08001161 return;
1162 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001163 case llvm::Instruction::Add:
1164 case llvm::Instruction::FAdd:
1165 case llvm::Instruction::Sub:
1166 case llvm::Instruction::FSub:
1167 case llvm::Instruction::Mul:
1168 case llvm::Instruction::FMul:
1169 case llvm::Instruction::UDiv:
1170 case llvm::Instruction::SDiv:
1171 case llvm::Instruction::URem:
1172 case llvm::Instruction::SRem:
1173 case llvm::Instruction::And:
1174 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001175 case llvm::Instruction::Xor: {
1176 llvm::GenericValue LHS, RHS;
1177 GetConstantValue(Op0, LHS);
1178 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001179
Zonr Chang932648d2010-10-13 22:23:56 +08001180 switch (Op0->getType()->getTypeID()) {
1181 case llvm::Type::IntegerTyID: {
1182 switch (CE->getOpcode()) {
1183 case llvm::Instruction::Add: {
1184 Result.IntVal = LHS.IntVal + RHS.IntVal;
1185 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001186 }
Zonr Chang932648d2010-10-13 22:23:56 +08001187 case llvm::Instruction::Sub: {
1188 Result.IntVal = LHS.IntVal - RHS.IntVal;
1189 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001190 }
Zonr Chang932648d2010-10-13 22:23:56 +08001191 case llvm::Instruction::Mul: {
1192 Result.IntVal = LHS.IntVal * RHS.IntVal;
1193 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001194 }
Zonr Chang932648d2010-10-13 22:23:56 +08001195 case llvm::Instruction::UDiv: {
1196 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1197 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001198 }
Zonr Chang932648d2010-10-13 22:23:56 +08001199 case llvm::Instruction::SDiv: {
1200 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1201 break;
1202 }
1203 case llvm::Instruction::URem: {
1204 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1205 break;
1206 }
1207 case llvm::Instruction::SRem: {
1208 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1209 break;
1210 }
1211 case llvm::Instruction::And: {
1212 Result.IntVal = LHS.IntVal & RHS.IntVal;
1213 break;
1214 }
1215 case llvm::Instruction::Or: {
1216 Result.IntVal = LHS.IntVal | RHS.IntVal;
1217 break;
1218 }
1219 case llvm::Instruction::Xor: {
1220 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1221 break;
1222 }
1223 default: {
1224 llvm_unreachable("Invalid integer opcode");
1225 }
1226 }
1227 break;
1228 }
1229 case llvm::Type::FloatTyID: {
1230 switch (CE->getOpcode()) {
1231 case llvm::Instruction::FAdd: {
1232 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1233 break;
1234 }
1235 case llvm::Instruction::FSub: {
1236 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1237 break;
1238 }
1239 case llvm::Instruction::FMul: {
1240 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1241 break;
1242 }
1243 case llvm::Instruction::FDiv: {
1244 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1245 break;
1246 }
1247 case llvm::Instruction::FRem: {
1248 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1249 break;
1250 }
1251 default: {
1252 llvm_unreachable("Invalid float opcode");
1253 }
1254 }
1255 break;
1256 }
1257 case llvm::Type::DoubleTyID: {
1258 switch (CE->getOpcode()) {
1259 case llvm::Instruction::FAdd: {
1260 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1261 break;
1262 }
1263 case llvm::Instruction::FSub: {
1264 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1265 break;
1266 }
1267 case llvm::Instruction::FMul: {
1268 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1269 break;
1270 }
1271 case llvm::Instruction::FDiv: {
1272 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1273 break;
1274 }
1275 case llvm::Instruction::FRem: {
1276 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1277 break;
1278 }
1279 default: {
1280 llvm_unreachable("Invalid double opcode");
1281 }
1282 }
1283 break;
1284 }
1285 case llvm::Type::X86_FP80TyID:
1286 case llvm::Type::PPC_FP128TyID:
1287 case llvm::Type::FP128TyID: {
1288 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1289 switch (CE->getOpcode()) {
1290 case llvm::Instruction::FAdd: {
1291 apfLHS.add(llvm::APFloat(RHS.IntVal),
1292 llvm::APFloat::rmNearestTiesToEven);
1293 break;
1294 }
1295 case llvm::Instruction::FSub: {
1296 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1297 llvm::APFloat::rmNearestTiesToEven);
1298 break;
1299 }
1300 case llvm::Instruction::FMul: {
1301 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1302 llvm::APFloat::rmNearestTiesToEven);
1303 break;
1304 }
1305 case llvm::Instruction::FDiv: {
1306 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1307 llvm::APFloat::rmNearestTiesToEven);
1308 break;
1309 }
1310 case llvm::Instruction::FRem: {
1311 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1312 llvm::APFloat::rmNearestTiesToEven);
1313 break;
1314 }
1315 default: {
1316 llvm_unreachable("Invalid long double opcode");
1317 }
1318 }
1319 Result.IntVal = apfLHS.bitcastToAPInt();
1320 break;
1321 }
1322 default: {
1323 llvm_unreachable("Bad add type!");
1324 }
1325 } // End switch (Op0->getType()->getTypeID())
1326 return;
1327 }
1328 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001329 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001330 }
1331 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001332
1333 std::string msg;
1334 llvm::raw_string_ostream Msg(msg);
1335 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001336 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001337 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001338
1339 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001340 case llvm::Type::FloatTyID: {
1341 Result.FloatVal =
1342 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001343 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001344 }
1345 case llvm::Type::DoubleTyID: {
1346 Result.DoubleVal =
1347 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001348 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001349 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001350 case llvm::Type::X86_FP80TyID:
1351 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001352 case llvm::Type::PPC_FP128TyID: {
1353 Result.IntVal =
1354 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001355 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001356 }
1357 case llvm::Type::IntegerTyID: {
1358 Result.IntVal =
1359 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001360 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001361 }
1362 case llvm::Type::PointerTyID: {
1363 switch (C->getValueID()) {
1364 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001365 Result.PointerVal = NULL;
1366 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001367 }
1368 case llvm::Value::FunctionVal: {
1369 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1370 Result.PointerVal =
1371 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001372 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001373 }
1374 case llvm::Value::GlobalVariableVal: {
1375 const llvm::GlobalVariable *GV =
1376 static_cast<const llvm::GlobalVariable*>(C);
1377 Result.PointerVal =
1378 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001379 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001380 }
1381 case llvm::Value::BlockAddressVal: {
1382 assert(false && "JIT does not support address-of-label yet!");
1383 }
1384 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001385 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001386 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001387 }
1388 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001389 }
1390 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001391 std::string msg;
1392 llvm::raw_string_ostream Msg(msg);
1393 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001394 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001395 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001396 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001397 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001398 return;
1399 }
1400
Zonr Chang932648d2010-10-13 22:23:56 +08001401 // Stores the data in @Val of type @Ty at address @Addr.
1402 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001403 const llvm::Type *Ty) {
1404 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1405
Zonr Chang932648d2010-10-13 22:23:56 +08001406 switch (Ty->getTypeID()) {
1407 case llvm::Type::IntegerTyID: {
1408 const llvm::APInt &IntVal = Val.IntVal;
1409 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1410 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001411
Zonr Chang932648d2010-10-13 22:23:56 +08001412 const uint8_t *Src =
1413 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001414
Zonr Chang932648d2010-10-13 22:23:56 +08001415 if (llvm::sys::isLittleEndianHost()) {
1416 // Little-endian host - the source is ordered from LSB to MSB.
1417 // Order the destination from LSB to MSB: Do a straight copy.
1418 memcpy(Addr, Src, StoreBytes);
1419 } else {
1420 // Big-endian host - the source is an array of 64 bit words
1421 // ordered from LSW to MSW.
1422 //
1423 // Each word is ordered from MSB to LSB.
1424 //
1425 // Order the destination from MSB to LSB:
1426 // Reverse the word order, but not the bytes in a word.
1427 unsigned int i = StoreBytes;
1428 while (i > sizeof(uint64_t)) {
1429 i -= sizeof(uint64_t);
1430 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1431 Src,
1432 sizeof(uint64_t));
1433 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001434 }
Zonr Chang932648d2010-10-13 22:23:56 +08001435 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001436 }
1437 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001438 }
1439 case llvm::Type::FloatTyID: {
1440 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001441 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001442 }
1443 case llvm::Type::DoubleTyID: {
1444 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001445 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001446 }
1447 case llvm::Type::X86_FP80TyID: {
1448 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001449 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001450 }
1451 case llvm::Type::PointerTyID: {
1452 // Ensure 64 bit target pointers are fully initialized on 32 bit
1453 // hosts.
1454 if (StoreBytes != sizeof(llvm::PointerTy))
1455 memset(Addr, 0, StoreBytes);
1456 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001457 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001458 }
1459 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001460 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001461 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001462 }
1463
Zonr Chang932648d2010-10-13 22:23:56 +08001464 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1465 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1466 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001467
1468 return;
1469 }
1470
Zonr Chang932648d2010-10-13 22:23:56 +08001471 // Recursive function to apply a @Constant value into the specified memory
1472 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001473 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001474 switch (C->getValueID()) {
1475 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001476 // Nothing to do
1477 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001478 }
1479 case llvm::Value::ConstantVectorVal: {
1480 // dynamic cast may hurt performance
1481 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001482
Zonr Chang932648d2010-10-13 22:23:56 +08001483 unsigned int ElementSize = mpTD->getTypeAllocSize
1484 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001485
Zonr Chang932648d2010-10-13 22:23:56 +08001486 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1487 InitializeConstantToMemory(
1488 CP->getOperand(i),
1489 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001490 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001491 }
1492 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001493 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1494 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001495 }
1496 case llvm::Value::ConstantArrayVal: {
1497 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1498 unsigned int ElementSize = mpTD->getTypeAllocSize
1499 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001500
Zonr Chang932648d2010-10-13 22:23:56 +08001501 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1502 InitializeConstantToMemory(
1503 CPA->getOperand(i),
1504 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1505 break;
1506 }
1507 case llvm::Value::ConstantStructVal: {
1508 const llvm::ConstantStruct *CPS =
1509 static_cast<const llvm::ConstantStruct*>(C);
1510 const llvm::StructLayout *SL = mpTD->getStructLayout
1511 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001512
Zonr Chang932648d2010-10-13 22:23:56 +08001513 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1514 InitializeConstantToMemory(
1515 CPS->getOperand(i),
1516 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1517 break;
1518 }
1519 default: {
1520 if (C->getType()->isFirstClassType()) {
1521 llvm::GenericValue Val;
1522 GetConstantValue(C, Val);
1523 StoreValueToMemory(Val, Addr, C->getType());
1524 } else {
1525 llvm_unreachable("Unknown constant type to initialize memory "
1526 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001527 }
1528 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001529 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001530 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001531 return;
1532 }
1533
1534 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001535 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001536 return;
1537
Zonr Chang932648d2010-10-13 22:23:56 +08001538 // Constant pool address resolution is handled by the target itself in ARM
1539 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001540#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001541 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1542 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001543
Zonr Chang932648d2010-10-13 22:23:56 +08001544 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001545 return;
1546
1547 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1548 unsigned Align = MCP->getConstantPoolAlignment();
1549
1550 mpConstantPoolBase = allocateSpace(Size, Align);
1551 mpConstantPool = MCP;
1552
Zonr Chang932648d2010-10-13 22:23:56 +08001553 if (mpConstantPoolBase == NULL)
1554 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001555
1556 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001557 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001558 llvm::MachineConstantPoolEntry CPE = Constants[i];
1559 unsigned AlignMask = CPE.getAlignment() - 1;
1560 Offset = (Offset + AlignMask) & ~AlignMask;
1561
1562 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1563 mConstPoolAddresses.push_back(CAddr);
1564
Zonr Chang932648d2010-10-13 22:23:56 +08001565 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001566 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001567 ("Initialize memory with machine specific constant pool"
1568 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001569
1570 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1571
1572 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1573 Offset += mpTD->getTypeAllocSize(Ty);
1574 }
1575#endif
1576 return;
1577 }
1578
1579 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001580 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001581 return;
1582
Zonr Chang932648d2010-10-13 22:23:56 +08001583 const std::vector<llvm::MachineJumpTableEntry> &JT =
1584 MJTI->getJumpTables();
1585 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001586 return;
1587
1588 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001589 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001590 NumEntries += JT[i].MBBs.size();
1591
1592 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1593
Zonr Chang932648d2010-10-13 22:23:56 +08001594 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001595 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001596 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001597
1598 return;
1599 }
1600
1601 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001602 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001603 return;
1604
Zonr Chang932648d2010-10-13 22:23:56 +08001605 const std::vector<llvm::MachineJumpTableEntry> &JT =
1606 MJTI->getJumpTables();
1607 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001608 return;
1609
Zonr Chang932648d2010-10-13 22:23:56 +08001610 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1611 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1612 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001613
Zonr Chang932648d2010-10-13 22:23:56 +08001614 // For each jump table, map each target in the jump table to the
1615 // address of an emitted MachineBasicBlock.
1616 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1617 for (int i = 0, ie = JT.size(); i != ie; i++) {
1618 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1619 // Store the address of the basic block for this jump table slot in the
1620 // memory we allocated for the jump table in 'initJumpTableInfo'
1621 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001622 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1623 }
1624 }
1625
Zonr Chang932648d2010-10-13 22:23:56 +08001626 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1627 bool MayNeedFarStub) {
1628 switch (V->getValueID()) {
1629 case llvm::Value::FunctionVal: {
1630 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001631
Zonr Chang932648d2010-10-13 22:23:56 +08001632 // If we have code, go ahead and return that.
1633 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1634 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001635
Zonr Chang932648d2010-10-13 22:23:56 +08001636 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1637 // Return the function stub if it's already created.
1638 // We do this first so that:
1639 // we're returning the same address for the function as any
1640 // previous call.
1641 //
1642 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1643 // guaranteed to be close enough to call.
1644 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001645
Zonr Chang932648d2010-10-13 22:23:56 +08001646 // If we know the target can handle arbitrary-distance calls, try to
1647 // return a direct pointer.
1648 if (!MayNeedFarStub) {
1649 //
1650 // x86_64 architecture may encounter the bug:
1651 // http://llvm.org/bugs/show_bug.cgi?id=5201
1652 // which generate instruction "call" instead of "callq".
1653 //
1654 // And once the real address of stub is greater than 64-bit
1655 // long, the replacement will truncate to 32-bit resulting a
1656 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001657#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001658 // If this is an external function pointer, we can force the JIT
1659 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001660 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1661 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1662 // Changing to false because wanting to allow later calls to
1663 // mpTJI->relocate() without aborting. For caching purpose
1664 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001665#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001666 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001667
Zonr Chang932648d2010-10-13 22:23:56 +08001668 // Otherwise, we may need a to emit a stub, and, conservatively, we
1669 // always do so.
1670 return GetLazyFunctionStub(F);
1671 break;
1672 }
1673 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001674 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1675 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001676 }
1677 case llvm::Value::GlobalAliasVal: {
1678 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1679 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001680
Zonr Chang932648d2010-10-13 22:23:56 +08001681 switch (GV->getValueID()) {
1682 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001683 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001684 // code-gen'd?
1685 return GetPointerToFunction(
1686 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001687 /* AbortOnFailure = */false);
1688 // Changing to false because wanting to allow later calls to
1689 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001690 break;
1691 }
1692 case llvm::Value::GlobalVariableVal: {
1693 if (void *P = mGlobalAddressMap[GV])
1694 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001695
Zonr Chang932648d2010-10-13 22:23:56 +08001696 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1697 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001698
Zonr Chang932648d2010-10-13 22:23:56 +08001699 return mGlobalAddressMap[GV];
1700 break;
1701 }
1702 case llvm::Value::GlobalAliasVal: {
1703 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001704 }
1705 }
1706 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001707 }
1708 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001709 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001710 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001711 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001712 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001713 }
1714
Zonr Chang932648d2010-10-13 22:23:56 +08001715 // If the specified function has been code-gen'd, return a pointer to the
1716 // function. If not, compile it, or use a stub to implement lazy compilation
1717 // if available.
1718 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1719 // If we have already code generated the function, just return the
1720 // address.
1721 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001722 return Addr;
1723
Zonr Chang932648d2010-10-13 22:23:56 +08001724 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001725 return GetLazyFunctionStub(F);
1726 }
1727
Zonr Chang932648d2010-10-13 22:23:56 +08001728 typedef llvm::DenseMap<const llvm::Function*,
1729 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001730 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1731
Zonr Chang932648d2010-10-13 22:23:56 +08001732 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001733 return mFunctionToLazyStubMap.lookup(F);
1734 }
1735
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001736 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001737 void *GetLazyFunctionStub(llvm::Function *F) {
1738 // If we already have a lazy stub for this function, recycle it.
1739 void *&Stub = mFunctionToLazyStubMap[F];
1740 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001741 return Stub;
1742
Zonr Chang932648d2010-10-13 22:23:56 +08001743 // In any cases, we should NOT resolve function at runtime (though we are
1744 // able to). We resolve this right now.
1745 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001746 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1747 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1748 // Changing to false because wanting to allow later calls to
1749 // mpTJI->relocate() without aborting. For caching purpose
1750 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001751
Zonr Chang932648d2010-10-13 22:23:56 +08001752 // Codegen a new stub, calling the actual address of the external
1753 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001754 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1755 startGVStub(F, SL.Size, SL.Alignment);
1756 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1757 finishGVStub();
1758
Zonr Chang932648d2010-10-13 22:23:56 +08001759 // We really want the address of the stub in the GlobalAddressMap for the
1760 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001761 UpdateGlobalMapping(F, Stub);
1762
Zonr Chang932648d2010-10-13 22:23:56 +08001763 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001764 PendingFunctions.insert(F);
1765 else
Zonr Chang932648d2010-10-13 22:23:56 +08001766 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1767 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001768
1769 return Stub;
1770 }
1771
Zonr Chang932648d2010-10-13 22:23:56 +08001772 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1773 void *Addr = GetPointerToGlobalIfAvailable(F);
1774 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001775 return Addr;
1776
1777 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1778 "Internal error: only external defined function routes here!");
1779
Zonr Chang932648d2010-10-13 22:23:56 +08001780 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001781 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001782 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001783
Zonr Chang932648d2010-10-13 22:23:56 +08001784 // If we resolved the symbol to a null address (eg. a weak external)
1785 // return a null pointer let the application handle it.
1786 if (Addr == NULL) {
1787 if (AbortOnFailure)
1788 llvm::report_fatal_error("Could not resolve external function "
1789 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001790 else
1791 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001792 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001793
1794 AddGlobalMapping(F, Addr);
1795
1796 return Addr;
1797 }
1798
Zonr Chang932648d2010-10-13 22:23:56 +08001799 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001800 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001801 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001802 return Addr;
1803
Zonr Chang932648d2010-10-13 22:23:56 +08001804 if (mpSymbolLookupFn)
1805 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001806 return Addr;
1807
Zonr Chang932648d2010-10-13 22:23:56 +08001808 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001809 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001810 "' which could not be resolved!");
1811
1812 return NULL;
1813 }
1814
Zonr Chang932648d2010-10-13 22:23:56 +08001815 // Return the address of the specified global variable, possibly emitting it
1816 // to memory if needed. This is used by the Emitter.
1817 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1818 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1819 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001820 return Ptr;
1821
Zonr Chang932648d2010-10-13 22:23:56 +08001822 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1823 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001824 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1825 AddGlobalMapping(GV, Ptr);
1826 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001827 // If the global hasn't been emitted to memory yet, allocate space and
1828 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001829 Ptr = GetMemoryForGV(GV);
1830 AddGlobalMapping(GV, Ptr);
1831 EmitGlobalVariable(GV);
1832 }
1833
1834 return Ptr;
1835 }
1836
Zonr Chang932648d2010-10-13 22:23:56 +08001837 // This method abstracts memory allocation of global variable so that the
1838 // JIT can allocate thread local variables depending on the target.
1839 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1840 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001841
Zonr Chang932648d2010-10-13 22:23:56 +08001842 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001843 size_t S = mpTD->getTypeAllocSize(GlobalType);
1844 size_t A = mpTD->getPreferredAlignment(GV);
1845
Zonr Chang932648d2010-10-13 22:23:56 +08001846 if (GV->isThreadLocal()) {
1847 // We can support TLS by
1848 //
1849 // Ptr = TJI.allocateThreadLocalMemory(S);
1850 //
1851 // But I tend not to.
1852 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001853 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001854 ("Compilation of Thread Local Storage (TLS) is disabled!");
1855
Zonr Chang932648d2010-10-13 22:23:56 +08001856 } else if (mpTJI->allocateSeparateGVMemory()) {
1857 if (A <= 8) {
1858 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001859 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001860 // Allocate (S + A) bytes of memory, then use an aligned pointer
1861 // within that space.
1862 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001863 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001864 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1865 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001866 }
1867 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001868 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001869 }
1870
1871 return Ptr;
1872 }
1873
1874 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001875 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001876
Zonr Chang932648d2010-10-13 22:23:56 +08001877 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001878 llvm::report_fatal_error
1879 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001880
Zonr Chang932648d2010-10-13 22:23:56 +08001881 if (GA == NULL) {
1882 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001883 GA = GetMemoryForGV(GV);
1884 AddGlobalMapping(GV, GA);
1885 }
1886
1887 InitializeConstantToMemory(GV->getInitializer(), GA);
1888
Zonr Chang932648d2010-10-13 22:23:56 +08001889 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001890 return;
1891 }
1892
1893 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1894 > GlobalToIndirectSymMapTy;
1895 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1896
Zonr Chang932648d2010-10-13 22:23:56 +08001897 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1898 // Make sure GV is emitted first, and create a stub containing the fully
1899 // resolved address.
1900 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001901
Zonr Chang932648d2010-10-13 22:23:56 +08001902 // If we already have a stub for this global variable, recycle it.
1903 void *&IndirectSym = GlobalToIndirectSymMap[V];
1904 // Otherwise, codegen a new indirect symbol.
1905 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001906 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1907
1908 return IndirectSym;
1909 }
1910
Zonr Chang932648d2010-10-13 22:23:56 +08001911 // This is the equivalent of FunctionToLazyStubMap for external functions.
1912 //
1913 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1914 // It's actually here to make it more likely that far calls
1915 // succeed, but no single stub can guarantee that. I'll
1916 // remove this in a subsequent checkin when I actually fix
1917 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001918 std::map<void*, void*> ExternalFnToStubMap;
1919
Zonr Chang932648d2010-10-13 22:23:56 +08001920 // Return a stub for the function at the specified address.
1921 void *GetExternalFunctionStub(void *FnAddr) {
1922 void *&Stub = ExternalFnToStubMap[FnAddr];
1923 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001924 return Stub;
1925
1926 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1927 startGVStub(0, SL.Size, SL.Alignment);
1928 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1929 finishGVStub();
1930
1931 return Stub;
1932 }
1933
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001934#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001935 const llvm::MCAsmInfo *mpAsmInfo;
1936 const llvm::MCDisassembler *mpDisassmbler;
1937 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001938
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001939 class BufferMemoryObject : public llvm::MemoryObject {
1940 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001941 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001942 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001943
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001944 public:
1945 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1946 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001947
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001948 uint64_t getBase() const { return 0; }
1949 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001950
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001951 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001952 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001953 return -1;
1954 *Byte = mBytes[Addr];
1955 return 0;
1956 }
1957 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001958
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08001959 public:
Zonr Chang932648d2010-10-13 22:23:56 +08001960 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001961 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001962 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001963#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001964 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001965 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1966 ErrorInfo,
1967 llvm::raw_fd_ostream::F_Append);
1968 if (!ErrorInfo.empty()) { // some errors occurred
1969 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001970 delete OS;
1971 return;
1972 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001973#else
1974 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001975#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001976 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1977 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001978
Zonr Chang932648d2010-10-13 22:23:56 +08001979 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001980 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001981 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001982 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001983 if (mpIP == NULL)
1984 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1985 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001986
Zonr Chang932648d2010-10-13 22:23:56 +08001987 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1988 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001989 uint64_t Size;
1990 uint64_t Index;
1991
Zonr Chang932648d2010-10-13 22:23:56 +08001992 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001993 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001994
Zonr Chang932648d2010-10-13 22:23:56 +08001995 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1996 /* REMOVED */ llvm::nulls())) {
1997 (*OS).indent(4)
1998 .write("0x", 2)
1999 .write_hex((uint32_t) Start + Index)
2000 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002001 mpIP->printInst(&Inst, *OS);
2002 *OS << "\n";
2003 } else {
2004 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002005 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002006 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002007 }
2008
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002009 *OS << "\n";
2010 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002011
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002012#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002013 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002014 OS->close();
2015 delete OS;
2016#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002017 return;
2018 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002019#else
Zonr Chang932648d2010-10-13 22:23:56 +08002020 inline void Disassemble(const std::string &Name, uint8_t *Start,
2021 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002022 return;
2023 }
Zonr Chang932648d2010-10-13 22:23:56 +08002024#endif // defined(USE_DISASSEMBLER)
2025
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002026 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002027 // Resolver to undefined symbol in CodeEmitter
2028 BCCSymbolLookupFn mpSymbolLookupFn;
2029 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002030
2031 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002032 // Will take the ownership of @MemMgr
2033 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2034 : mpMemMgr(pMemMgr),
2035 mpTarget(NULL),
2036 mpTJI(NULL),
2037 mpTD(NULL),
2038 mpCurEmitFunction(NULL),
2039 mpConstantPool(NULL),
2040 mpJumpTable(NULL),
2041 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002042#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002043 mpAsmInfo(NULL),
2044 mpDisassmbler(NULL),
2045 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002046#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002047 mpSymbolLookupFn(NULL),
2048 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002049 return;
2050 }
2051
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002052 inline global_addresses_const_iterator global_address_begin() const {
2053 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002054 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002055 inline global_addresses_const_iterator global_address_end() const {
2056 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002057 }
2058
Logan824dd0a2010-11-20 01:45:54 +08002059 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2060 return mCachingRelocations;
2061 }
2062
Zonr Chang932648d2010-10-13 22:23:56 +08002063 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002064 mpSymbolLookupFn = pFn;
2065 mpSymbolLookupContext = pContext;
2066 return;
2067 }
2068
Zonr Chang932648d2010-10-13 22:23:56 +08002069 void setTargetMachine(llvm::TargetMachine &TM) {
2070 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002071 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002072 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002073 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002074 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002075 mpTD = TM.getTargetData();
2076
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002077 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2078
2079 return;
2080 }
2081
Zonr Chang932648d2010-10-13 22:23:56 +08002082 // This callback is invoked when the specified function is about to be code
2083 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002084 void startFunction(llvm::MachineFunction &F) {
2085 uintptr_t ActualSize = 0;
2086
2087 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002088
2089 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2090 // MachineCodeEmitter, which is the super class of the class
2091 // JITCodeEmitter.
2092 //
2093 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2094 // allocated for this code buffer.
2095 //
2096 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2097 // code. This is guranteed to be in the range
2098 // [BufferBegin, BufferEnd]. If this pointer is at
2099 // BufferEnd, it will never move due to code emission, and
2100 // all code emission requests will be ignored (this is the
2101 // buffer overflow condition).
2102 BufferBegin = CurBufferPtr =
2103 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002104 BufferEnd = BufferBegin + ActualSize;
2105
Zonr Chang932648d2010-10-13 22:23:56 +08002106 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002107 mpCurEmitFunction = new EmittedFunctionCode();
2108 mpCurEmitFunction->FunctionBody = BufferBegin;
2109
Zonr Chang932648d2010-10-13 22:23:56 +08002110 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002111 emitAlignment(16);
2112
2113 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002114 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002115 initJumpTableInfo(MJTI);
2116
Zonr Chang932648d2010-10-13 22:23:56 +08002117 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002118 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2119
2120 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2121
2122 mpCurEmitFunction->Code = CurBufferPtr;
2123
2124 mMBBLocations.clear();
2125
2126 return;
2127 }
2128
Zonr Chang932648d2010-10-13 22:23:56 +08002129 // This callback is invoked when the specified function has finished code
2130 // generation. If a buffer overflow has occurred, this method returns true
2131 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002132 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002133 if (CurBufferPtr == BufferEnd) {
2134 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002135 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2136 return false;
2137 }
2138
Zonr Chang932648d2010-10-13 22:23:56 +08002139 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002140 emitJumpTableInfo(MJTI);
2141
Zonr Chang932648d2010-10-13 22:23:56 +08002142 // FnStart is the start of the text, not the start of the constant pool
2143 // and other per-function data.
2144 uint8_t *FnStart =
2145 reinterpret_cast<uint8_t*>(
2146 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002147
Zonr Chang932648d2010-10-13 22:23:56 +08002148 // FnEnd is the end of the function's machine code.
2149 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002150
Zonr Chang932648d2010-10-13 22:23:56 +08002151 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002152 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2153
Zonr Chang932648d2010-10-13 22:23:56 +08002154 // Resolve the relocations to concrete pointers.
2155 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2156 llvm::MachineRelocation &MR = mRelocations[i];
2157 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002158
Zonr Chang932648d2010-10-13 22:23:56 +08002159 if (!MR.letTargetResolve()) {
2160 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002161 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002162
2163 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002164 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002165 }
2166
Zonr Chang932648d2010-10-13 22:23:56 +08002167 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002168 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2169 BufferBegin
2170 + MR.getMachineCodeOffset(),
2171 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002172 } else if (MR.isIndirectSymbol()) {
2173 ResultPtr =
2174 GetPointerToGVIndirectSym(
2175 MR.getGlobalValue(),
2176 BufferBegin + MR.getMachineCodeOffset());
2177 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002178 ResultPtr =
2179 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002180 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002181 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002182 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002183 } else {
2184 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2185 ResultPtr =
2186 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2187 }
2188
Logan824dd0a2010-11-20 01:45:54 +08002189 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2190 // TODO(logan): Cache external symbol relocation entry.
2191 // Currently, we are not caching them. But since Android
2192 // system is using prelink, it is not a problem.
2193
2194 // Cache the relocation result address
2195 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002196 oBCCRelocEntry(MR.getRelocationType(),
2197 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002198 ResultPtr));
2199 }
2200
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002201 MR.setResultPointer(ResultPtr);
2202 }
2203 }
2204
2205 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2206 mpMemMgr->getGOTBase());
2207 }
2208
2209 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002210 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2211 // global variables that were referenced in the relocations.
2212 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002213 return false;
2214
Zonr Chang932648d2010-10-13 22:23:56 +08002215 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002216 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2217 BufferBegin = CurBufferPtr = 0;
2218
Zonr Chang932648d2010-10-13 22:23:56 +08002219 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002220 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2221 mpCurEmitFunction = NULL;
2222
2223 mRelocations.clear();
2224 mConstPoolAddresses.clear();
2225
Zonr Chang932648d2010-10-13 22:23:56 +08002226 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002227 mpMMI->EndFunction();
2228
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002229 updateFunctionStub(F.getFunction());
2230
Zonr Chang932648d2010-10-13 22:23:56 +08002231 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002232 mpMemMgr->setMemoryExecutable();
2233
2234 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2235
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002236 return false;
2237 }
2238
Zonr Chang932648d2010-10-13 22:23:56 +08002239 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002240 unsigned Alignment) {
2241 mpSavedBufferBegin = BufferBegin;
2242 mpSavedBufferEnd = BufferEnd;
2243 mpSavedCurBufferPtr = CurBufferPtr;
2244
2245 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2246 Alignment);
2247 BufferEnd = BufferBegin + StubSize + 1;
2248
2249 return;
2250 }
2251
Zonr Chang932648d2010-10-13 22:23:56 +08002252 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002253 mpSavedBufferBegin = BufferBegin;
2254 mpSavedBufferEnd = BufferEnd;
2255 mpSavedCurBufferPtr = CurBufferPtr;
2256
Zonr Chang932648d2010-10-13 22:23:56 +08002257 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002258 BufferEnd = BufferBegin + StubSize + 1;
2259
2260 return;
2261 }
2262
2263 void finishGVStub() {
2264 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2265
Zonr Chang932648d2010-10-13 22:23:56 +08002266 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002267 BufferBegin = mpSavedBufferBegin;
2268 BufferEnd = mpSavedBufferEnd;
2269 CurBufferPtr = mpSavedCurBufferPtr;
2270
2271 return;
2272 }
2273
Zonr Chang932648d2010-10-13 22:23:56 +08002274 // Allocates and fills storage for an indirect GlobalValue, and returns the
2275 // address.
2276 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002277 const uint8_t *Buffer, size_t Size,
2278 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002279 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002280 memcpy(IndGV, Buffer, Size);
2281 return IndGV;
2282 }
2283
Zonr Chang932648d2010-10-13 22:23:56 +08002284 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002285 void emitLabel(llvm::MCSymbol *Label) {
2286 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002287 return;
2288 }
2289
Zonr Chang932648d2010-10-13 22:23:56 +08002290 // Allocate memory for a global. Unlike allocateSpace, this method does not
2291 // allocate memory in the current output buffer, because a global may live
2292 // longer than the current function.
2293 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2294 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002295 return mpMemMgr->allocateGlobal(Size, Alignment);
2296 }
2297
Zonr Chang932648d2010-10-13 22:23:56 +08002298 // This should be called by the target when a new basic block is about to be
2299 // emitted. This way the MCE knows where the start of the block is, and can
2300 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002301 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002302 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002303 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2304 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2305 return;
2306 }
2307
Zonr Chang932648d2010-10-13 22:23:56 +08002308 // Whenever a relocatable address is needed, it should be noted with this
2309 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002310 void addRelocation(const llvm::MachineRelocation &MR) {
2311 mRelocations.push_back(MR);
2312 return;
2313 }
2314
Zonr Chang932648d2010-10-13 22:23:56 +08002315 // Return the address of the @Index entry in the constant pool that was
2316 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002317 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2318 assert(Index < mpConstantPool->getConstants().size() &&
2319 "Invalid constant pool index!");
2320 return mConstPoolAddresses[Index];
2321 }
2322
Zonr Chang932648d2010-10-13 22:23:56 +08002323 // Return the address of the jump table with index @Index in the function
2324 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002325 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002326 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002327 mpJumpTable->getJumpTables();
2328
Zonr Chang932648d2010-10-13 22:23:56 +08002329 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002330
2331 unsigned int Offset = 0;
2332 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2333
Zonr Chang932648d2010-10-13 22:23:56 +08002334 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002335 Offset += JT[i].MBBs.size();
2336 Offset *= EntrySize;
2337
Zonr Chang932648d2010-10-13 22:23:56 +08002338 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002339 }
2340
Zonr Chang932648d2010-10-13 22:23:56 +08002341 // Return the address of the specified MachineBasicBlock, only usable after
2342 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002343 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2344 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002345 mMBBLocations[MBB->getNumber()] &&
2346 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002347 return mMBBLocations[MBB->getNumber()];
2348 }
2349
Zonr Chang932648d2010-10-13 22:23:56 +08002350 // Return the address of the specified LabelID, only usable after the
2351 // LabelID has been emitted.
2352 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002353 assert(mLabelLocations.count(Label) && "Label not emitted!");
2354 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002355 }
2356
Zonr Chang932648d2010-10-13 22:23:56 +08002357 // Specifies the MachineModuleInfo object. This is used for exception
2358 // handling purposes.
2359 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002360 mpMMI = Info;
2361 return;
2362 }
2363
Zonr Chang932648d2010-10-13 22:23:56 +08002364 void updateFunctionStub(const llvm::Function *F) {
2365 // Get the empty stub we generated earlier.
2366 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002367 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002368 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002369 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002370 else
2371 return;
2372
Zonr Chang932648d2010-10-13 22:23:56 +08002373 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002374
2375 assert(Addr != Stub &&
2376 "Function must have non-stub address to be updated.");
2377
Zonr Chang932648d2010-10-13 22:23:56 +08002378 // Tell the target jit info to rewrite the stub at the specified address,
2379 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002380 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2381 startGVStub(Stub, SL.Size);
2382 mpTJI->emitFunctionStub(F, Addr, *this);
2383 finishGVStub();
2384
Zonr Chang932648d2010-10-13 22:23:56 +08002385 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2386 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002387
2388 PendingFunctions.erase(I);
2389
2390 return;
2391 }
2392
Zonr Chang932648d2010-10-13 22:23:56 +08002393 // Once you finish the compilation on a translation unit, you can call this
2394 // function to recycle the memory (which is used at compilation time and not
2395 // needed for runtime).
2396 //
2397 // NOTE: You should not call this funtion until the code-gen passes for a
2398 // given module is done. Otherwise, the results is undefined and may
2399 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002400 void releaseUnnecessary() {
2401 mMBBLocations.clear();
2402 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002403 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002404 mFunctionToLazyStubMap.clear();
2405 GlobalToIndirectSymMap.clear();
2406 ExternalFnToStubMap.clear();
2407 PendingFunctions.clear();
2408
2409 return;
2410 }
2411
2412 void reset() {
2413 releaseUnnecessary();
2414
2415 mpSymbolLookupFn = NULL;
2416 mpSymbolLookupContext = NULL;
2417
2418 mpTJI = NULL;
2419 mpTD = NULL;
2420
Zonr Chang932648d2010-10-13 22:23:56 +08002421 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2422 E = mEmittedFunctions.end();
2423 I != E;
2424 I++)
2425 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002426 delete I->second;
2427 mEmittedFunctions.clear();
2428
2429 mpMemMgr->reset();
2430
2431 return;
2432 }
2433
Zonr Chang932648d2010-10-13 22:23:56 +08002434 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002435 return lookup( llvm::StringRef(Name) );
2436 }
2437
Zonr Chang932648d2010-10-13 22:23:56 +08002438 void *lookup(const llvm::StringRef &Name) {
2439 EmittedFunctionsMapTy::const_iterator I =
2440 mEmittedFunctions.find(Name.str());
2441 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002442 return NULL;
2443 else
2444 return I->second->Code;
2445 }
2446
Zonr Chang932648d2010-10-13 22:23:56 +08002447 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002448 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002449 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002450 int functionCount = mEmittedFunctions.size();
2451
Zonr Chang932648d2010-10-13 22:23:56 +08002452 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002453 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002454 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002455 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002456 if (functions)
2457 for (EmittedFunctionsMapTy::const_iterator
2458 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2459 (I != E) && (functionCount > 0);
2460 I++, functionCount--)
2461 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002462
2463 return;
2464 }
2465
Zonr Chang932648d2010-10-13 22:23:56 +08002466 void getFunctionBinary(BCCchar *label,
2467 BCCvoid **base,
2468 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002469 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002470 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002471 *base = NULL;
2472 *length = 0;
2473 } else {
2474 *base = I->second->Code;
2475 *length = I->second->Size;
2476 }
2477 return;
2478 }
2479
2480 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002481 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002482#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002483 delete mpAsmInfo;
2484 delete mpDisassmbler;
2485 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002486#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002487 return;
2488 }
Zonr Chang932648d2010-10-13 22:23:56 +08002489 };
2490 // End of Class CodeEmitter
2491 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002492
Zonr Chang932648d2010-10-13 22:23:56 +08002493 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002494 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002495 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002496 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2497 return mCodeEmitter.get();
2498 }
2499
2500 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002501 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002502
Zonr Chang932648d2010-10-13 22:23:56 +08002503 llvm::LLVMContext *mContext;
2504 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002505
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002506 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002507
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002508 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002509 Compiler()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002510 : mNeverCache(true),
2511 mCacheNew(false),
2512 mCacheFd(-1),
2513 mCacheMapAddr(NULL),
2514 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002515 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002516 mCacheDiff(0),
2517 mCodeDataAddr(NULL),
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002518 mBccCodeAddrTaken(false),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002519 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002520 mpSymbolLookupContext(NULL),
2521 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002522 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002523 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002524 llvm::remove_fatal_error_handler();
2525 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002526 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002527 return;
2528 }
2529
Zonr Chang932648d2010-10-13 22:23:56 +08002530 // interface for BCCscript::registerSymbolCallback()
2531 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002532 mpSymbolLookupFn = pFn;
2533 mpSymbolLookupContext = pContext;
2534 return;
2535 }
2536
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002537 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002538 GlobalInitialization();
2539 mModule = module;
2540 return hasError();
2541 }
2542
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002543 int readBC(const char *bitcode,
2544 size_t bitcodeSize,
2545 const BCCchar *resName) {
2546 GlobalInitialization();
2547
2548 if (resName) {
2549 // Turn off the default NeverCaching mode
2550 mNeverCache = false;
2551
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002552 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2553 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2554 return -mCacheFd;
2555 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002556 }
2557
2558 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002559
Zonr Chang932648d2010-10-13 22:23:56 +08002560 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002561 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002562
Zonr Chang932648d2010-10-13 22:23:56 +08002563 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002564 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002565 llvm::StringRef(bitcode, bitcodeSize)));
2566
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002567 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002568 setError("Error reading input program bitcode into memory");
2569 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002570 }
2571
Zonr Chang932648d2010-10-13 22:23:56 +08002572 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002573 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2574 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002575 return hasError();
2576 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002577
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002578 int linkBC(const char *bitcode, size_t bitcodeSize) {
2579 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002580
2581 if (bitcode == NULL || bitcodeSize <= 0)
2582 return 0;
2583
2584 if (mModule == NULL) {
2585 setError("No module presents for linking");
2586 return hasError();
2587 }
2588
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002589 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002590 llvm::StringRef(bitcode, bitcodeSize)));
2591
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002592 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002593 setError("Error reading input library bitcode into memory");
2594 return hasError();
2595 }
2596
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002597 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002598 *mContext,
2599 &mError));
2600 if (Lib.get() == NULL)
2601 return hasError();
2602
2603 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2604 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002605
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002606 // Everything for linking should be settled down here with no error occurs
2607 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002608 return hasError();
2609 }
2610
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002611
2612 // interface for bccLoadBinary()
2613 int loader() {
2614 // Check File Descriptor
2615 if (mCacheFd < 0) {
2616 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2617 goto giveup;
2618 }
2619
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002620 // Check File Size
2621 struct stat statCacheFd;
2622 if (fstat(mCacheFd, &statCacheFd) < 0) {
2623 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2624 goto giveup;
2625 }
2626
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002627 mCacheSize = statCacheFd.st_size;
2628
2629 if (mCacheSize < sizeof(oBCCHeader) ||
2630 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002631 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2632 goto giveup;
2633 }
2634
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002635 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2636 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2637 goto giveup;
2638 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002639
2640 // Read File Content
2641 {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002642 // Part 1. Deal with the non-codedata section first
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002643 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002644 LOGE("sliao@Loader: mCacheSize=%x, heuristicCodeOffset=%x", mCacheSize, heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002645
2646 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002647 if (!mCacheMapAddr) {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002648 flock(mCacheFd, LOCK_UN);
2649 LOGE("allocation failed.\n");
2650 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002651 }
2652
2653 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2654 heuristicCodeOffset));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002655 if (nread != (size_t)heuristicCodeOffset) {
2656 LOGE("read(mCacheFd) failed\n");
2657 free(mCacheMapAddr);
2658 goto bail;
2659 }
2660
2661 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002662 // Sanity check
2663 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2664 LOGE("assertion failed: heuristic code offset is not correct.\n");
2665 goto bail;
2666 }
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002667 LOGE("sliao: mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2668 LOGE("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2669 LOGE("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2670 LOGE("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2671 LOGE("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002672
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002673 // Verify the Cache File
2674 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2675 LOGE("bad magic word\n");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002676 goto bail;
2677 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002678
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002679 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2680 LOGE("bad oBCC version 0x%08x\n",
2681 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2682 goto bail;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002683 }
2684
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002685 if (mCacheSize < mCacheHdr->relocOffset +
2686 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
2687 LOGE("relocate table overflow\n");
2688 goto bail;
2689 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002690
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002691 if (mCacheSize < mCacheHdr->exportVarsOffset +
2692 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2693 LOGE("export variables table overflow\n");
2694 goto bail;
2695 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002696
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002697 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2698 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2699 LOGE("export functions table overflow\n");
2700 goto bail;
2701 }
2702
2703 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2704 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2705 LOGE("export pragmas table overflow\n");
2706 goto bail;
2707 }
2708
2709 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2710 LOGE("code cache overflow\n");
2711 goto bail;
2712 }
2713
2714 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2715 LOGE("data (global variable) cache overflow\n");
2716 goto bail;
2717 }
2718
2719 // Part 2. Deal with the codedata section
2720 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2721 MaxCodeSize + MaxGlobalVarSize,
2722 PROT_READ | PROT_EXEC | PROT_WRITE,
2723 MAP_PRIVATE | MAP_FIXED,
2724 mCacheFd, heuristicCodeOffset);
2725 if (mCodeDataAddr != MAP_FAILED &&
2726 mCodeDataAddr ==
2727 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr)) {
2728 // relocate is avoidable
2729 mBccCodeAddrTaken = true;
2730
2731 flock(mCacheFd, LOCK_UN);
2732 } else {
2733 mCacheMapAddr = (char *) mmap(0,
2734 mCacheSize,
2735 PROT_READ | PROT_EXEC | PROT_WRITE,
2736 MAP_PRIVATE,
2737 mCacheFd,
2738 0);
2739 if (mCacheMapAddr == MAP_FAILED) {
2740 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2741 flock(mCacheFd, LOCK_UN);
2742 goto giveup;
2743 }
2744
2745 flock(mCacheFd, LOCK_UN);
2746 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2747 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002748 }
2749
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002750 // Relocate
2751 {
2752 mCacheDiff = mCodeDataAddr -
2753 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2754
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002755 if (!mBccCodeAddrTaken) { // To relocate
2756 if (mCacheHdr->rootAddr) {
2757 mCacheHdr->rootAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002758 }
2759
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002760 if (mCacheHdr->initAddr) {
2761 mCacheHdr->initAddr += mCacheDiff;
Logan824dd0a2010-11-20 01:45:54 +08002762 }
2763
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002764 oBCCRelocEntry *cachedRelocTable =
2765 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2766 mCacheHdr->relocOffset);
Logan824dd0a2010-11-20 01:45:54 +08002767
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002768 std::vector<llvm::MachineRelocation> relocations;
2769
2770 // Read in the relocs
2771 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2772 oBCCRelocEntry *entry = &cachedRelocTable[i];
2773
2774 llvm::MachineRelocation reloc =
2775 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2776 (unsigned)entry->relocType, 0, 0);
2777
2778 reloc.setResultPointer(
2779 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2780
2781 relocations.push_back(reloc);
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002782 }
2783
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002784 // Rewrite machine code using llvm::TargetJITInfo relocate
2785 {
2786 llvm::TargetMachine *TM = NULL;
2787 const llvm::Target *Target;
2788 std::string FeaturesStr;
2789
2790 // Create TargetMachine
2791 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2792 if (hasError())
2793 goto bail;
2794
2795 if (!CPU.empty() || !Features.empty()) {
2796 llvm::SubtargetFeatures F;
2797 F.setCPU(CPU);
2798 for (std::vector<std::string>::const_iterator I = Features.begin(),
2799 E = Features.end(); I != E; I++)
2800 F.AddFeature(*I);
2801 FeaturesStr = F.getString();
2802 }
2803
2804 TM = Target->createTargetMachine(Triple, FeaturesStr);
2805 if (TM == NULL) {
2806 setError("Failed to create target machine implementation for the"
2807 " specified triple '" + Triple + "'");
2808 goto bail;
2809 }
2810
2811 TM->getJITInfo()->relocate(mCodeDataAddr,
2812 &relocations[0], relocations.size(),
2813 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2814
2815 if (mCodeEmitter.get()) {
2816 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2817 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2818 2 * 1024 /*MaxCodeSize*/,
2819 false);
2820 }
2821
2822 delete TM;
2823 }
2824 } // End of if (!mBccCodeAddrTaken)
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002825 }
2826
2827 return 0;
2828
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002829 bail:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002830 if (mCacheMapAddr) {
2831 free(mCacheMapAddr);
2832 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002833 if (mBccCodeAddrTaken) {
2834 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2835 LOGE("munmap failed: %s\n", strerror(errno));
2836 }
2837 } else {
2838 if (munmap(mCacheMapAddr, mCacheSize) != 0) {
2839 LOGE("munmap failed: %s\n", strerror(errno));
2840 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002841 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002842
Shih-wei Liao1f45b862010-11-21 23:22:38 -08002843 giveup:
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002844 return 1;
2845 }
2846
2847 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002848 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002849 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002850
Zonr Chang932648d2010-10-13 22:23:56 +08002851 llvm::TargetMachine *TM = NULL;
2852 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002853 std::string FeaturesStr;
2854
Zonr Chang932648d2010-10-13 22:23:56 +08002855 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002856
Zonr Chang932648d2010-10-13 22:23:56 +08002857 const llvm::NamedMDNode *PragmaMetadata;
2858 const llvm::NamedMDNode *ExportVarMetadata;
2859 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002860
Zonr Chang932648d2010-10-13 22:23:56 +08002861 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002862 return 0;
2863
Zonr Chang932648d2010-10-13 22:23:56 +08002864 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002865 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002866 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002867 goto on_bcc_compile_error;
2868
Zonr Chang932648d2010-10-13 22:23:56 +08002869 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002870 llvm::SubtargetFeatures F;
2871 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002872 for (std::vector<std::string>::const_iterator I = Features.begin(),
2873 E = Features.end();
2874 I != E;
2875 I++)
2876 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002877 FeaturesStr = F.getString();
2878 }
2879
2880 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002881 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002882 setError("Failed to create target machine implementation for the"
2883 " specified triple '" + Triple + "'");
2884 goto on_bcc_compile_error;
2885 }
2886
Zonr Chang932648d2010-10-13 22:23:56 +08002887 // Create memory manager for creation of code emitter later.
2888 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002889 setError("Failed to startup memory management for further compilation");
2890 goto on_bcc_compile_error;
2891 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002892 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002893
Zonr Chang932648d2010-10-13 22:23:56 +08002894 // Create code emitter
2895 if (!mCodeEmitter.get()) {
2896 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002897 setError("Failed to create machine code emitter to complete"
2898 " the compilation");
2899 goto on_bcc_compile_error;
2900 }
2901 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002902 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002903 mCodeEmitter->reset();
2904 }
2905
2906 mCodeEmitter->setTargetMachine(*TM);
2907 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2908 mpSymbolLookupContext);
2909
Zonr Chang932648d2010-10-13 22:23:56 +08002910 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002911 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002912
Zonr Chang5d35b972010-10-23 14:36:47 +08002913 // Load named metadata
2914 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2915 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2916 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2917
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002918 // Create LTO passes and run them on the mModule
2919 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002920 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002921 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08002922 LTOPasses.add(new llvm::TargetData(*TD));
2923
2924 std::vector<const char*> ExportSymbols;
2925
2926 // A workaround for getting export variable and function name. Will refine
2927 // it soon.
2928 if (ExportVarMetadata) {
2929 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2930 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2931 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2932 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2933 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2934 llvm::StringRef ExportVarName =
2935 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2936 ExportSymbols.push_back(ExportVarName.data());
2937 }
2938 }
2939 }
2940 }
2941
2942 if (ExportFuncMetadata) {
2943 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2944 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2945 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2946 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2947 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2948 llvm::StringRef ExportFuncName =
2949 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2950 ExportSymbols.push_back(ExportFuncName.data());
2951 }
2952 }
2953 }
2954 }
2955 // root() and init() are born to be exported
2956 ExportSymbols.push_back("root");
2957 ExportSymbols.push_back("init");
2958
Zonr Change5c7a542010-10-24 01:07:27 +08002959 // We now create passes list performing LTO. These are copied from
2960 // (including comments) llvm::createStandardLTOPasses().
2961
2962 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08002963 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002964
Zonr Change5c7a542010-10-24 01:07:27 +08002965 // Propagate constants at call sites into the functions they call. This
2966 // opens opportunities for globalopt (and inlining) by substituting
2967 // function pointers passed as arguments to direct uses of functions.
2968 LTOPasses.add(llvm::createIPSCCPPass());
2969
2970 // Now that we internalized some globals, see if we can hack on them!
2971 LTOPasses.add(llvm::createGlobalOptimizerPass());
2972
2973 // Linking modules together can lead to duplicated global constants, only
2974 // keep one copy of each constant...
2975 LTOPasses.add(llvm::createConstantMergePass());
2976
2977 // Remove unused arguments from functions...
2978 LTOPasses.add(llvm::createDeadArgEliminationPass());
2979
2980 // Reduce the code after globalopt and ipsccp. Both can open up
2981 // significant simplification opportunities, and both can propagate
2982 // functions through function pointers. When this happens, we often have
2983 // to resolve varargs calls, etc, so let instcombine do this.
2984 LTOPasses.add(llvm::createInstructionCombiningPass());
2985
2986 // Inline small functions
2987 LTOPasses.add(llvm::createFunctionInliningPass());
2988
2989 // Remove dead EH info.
2990 LTOPasses.add(llvm::createPruneEHPass());
2991
2992 // Internalize the globals again after inlining
2993 LTOPasses.add(llvm::createGlobalOptimizerPass());
2994
2995 // Remove dead functions.
2996 LTOPasses.add(llvm::createGlobalDCEPass());
2997
2998 // If we didn't decide to inline a function, check to see if we can
2999 // transform it to pass arguments by value instead of by reference.
3000 LTOPasses.add(llvm::createArgumentPromotionPass());
3001
3002 // The IPO passes may leave cruft around. Clean up after them.
3003 LTOPasses.add(llvm::createInstructionCombiningPass());
3004 LTOPasses.add(llvm::createJumpThreadingPass());
3005
3006 // Break up allocas
3007 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3008
3009 // Run a few AA driven optimizations here and now, to cleanup the code.
3010 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3011 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3012
3013 // Hoist loop invariants.
3014 LTOPasses.add(llvm::createLICMPass());
3015
3016 // Remove redundancies.
3017 LTOPasses.add(llvm::createGVNPass());
3018
3019 // Remove dead memcpys.
3020 LTOPasses.add(llvm::createMemCpyOptPass());
3021
3022 // Nuke dead stores.
3023 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3024
3025 // Cleanup and simplify the code after the scalar optimizations.
3026 LTOPasses.add(llvm::createInstructionCombiningPass());
3027
3028 LTOPasses.add(llvm::createJumpThreadingPass());
3029
3030 // Delete basic blocks, which optimization passes may have killed.
3031 LTOPasses.add(llvm::createCFGSimplificationPass());
3032
3033 // Now that we have optimized the program, discard unreachable functions.
3034 LTOPasses.add(llvm::createGlobalDCEPass());
3035
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003036 LTOPasses.run(*mModule);
3037 }
3038
Zonr Chang932648d2010-10-13 22:23:56 +08003039 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003040 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003041 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003042
Zonr Chang932648d2010-10-13 22:23:56 +08003043 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3044 *mCodeEmitter,
3045 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003046 setError("The machine code emission is not supported by BCC on target '"
3047 + Triple + "'");
3048 goto on_bcc_compile_error;
3049 }
3050
Zonr Chang932648d2010-10-13 22:23:56 +08003051 // Run the pass (the code emitter) on every non-declaration function in the
3052 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003053 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003054 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3055 I != E;
3056 I++)
3057 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003058 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003059
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003060 CodeGenPasses->doFinalization();
3061
Zonr Chang932648d2010-10-13 22:23:56 +08003062 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003063 if (ExportVarMetadata) {
3064 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3065 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3066 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3067 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3068 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003069 llvm::StringRef ExportVarName =
3070 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003071 CodeEmitter::global_addresses_const_iterator I, E;
3072 for (I = mCodeEmitter->global_address_begin(),
3073 E = mCodeEmitter->global_address_end();
3074 I != E;
3075 I++) {
3076 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003077 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003078 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003079 mExportVars.push_back(I->second);
3080 break;
3081 }
3082 }
Zonr Chang932648d2010-10-13 22:23:56 +08003083 if (I != mCodeEmitter->global_address_end())
3084 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003085 }
3086 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003087 // if reaching here, we know the global variable record in metadata is
3088 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003089 mExportVars.push_back(NULL);
3090 }
3091 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3092 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003093 }
3094
Zonr Chang932648d2010-10-13 22:23:56 +08003095 if (ExportFuncMetadata) {
3096 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3097 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3098 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3099 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3100 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003101 llvm::StringRef ExportFuncName =
3102 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3103 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3104 }
3105 }
3106 }
3107 }
3108
Zonr Chang932648d2010-10-13 22:23:56 +08003109 // Tell code emitter now can release the memory using during the JIT since
3110 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003111 mCodeEmitter->releaseUnnecessary();
3112
Zonr Chang932648d2010-10-13 22:23:56 +08003113 // Finally, read pragma information from the metadata node of the @Module if
3114 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003115 if (PragmaMetadata)
3116 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3117 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3118 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003119 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003120 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3121 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003122
Zonr Chang932648d2010-10-13 22:23:56 +08003123 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003124 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3125 llvm::StringRef PragmaName =
3126 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3127 llvm::StringRef PragmaValue =
3128 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3129
Zonr Chang932648d2010-10-13 22:23:56 +08003130 mPragmas.push_back(
3131 std::make_pair(std::string(PragmaName.data(),
3132 PragmaName.size()),
3133 std::string(PragmaValue.data(),
3134 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003135 }
3136 }
3137 }
3138
3139 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003140 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003141 if (CodeGenPasses) {
3142 delete CodeGenPasses;
3143 } else if (TD) {
3144 delete TD;
3145 }
3146 if (TM)
3147 delete TM;
3148
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003149 if (mError.empty()) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003150 if (!mNeverCache && mCacheFd >= 0 && mCacheNew) {
3151 genCacheFile();
3152 flock(mCacheFd, LOCK_UN);
3153 }
3154
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003155 return false;
3156 }
3157
Zonr Chang932648d2010-10-13 22:23:56 +08003158 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003159 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003160 }
3161
Zonr Chang932648d2010-10-13 22:23:56 +08003162 // interface for bccGetScriptInfoLog()
3163 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003164 return const_cast<char*>(mError.c_str());
3165 }
3166
Zonr Chang932648d2010-10-13 22:23:56 +08003167 // interface for bccGetScriptLabel()
3168 void *lookup(const char *name) {
3169 void *addr = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003170 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3171 if (!strcmp(name, "root")) {
3172 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3173 } else if (!strcmp(name, "init")) {
3174 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3175 }
3176 return addr;
3177 }
3178
Zonr Chang932648d2010-10-13 22:23:56 +08003179 if (mCodeEmitter.get())
3180 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003181 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003182 return addr;
3183 }
3184
Zonr Chang932648d2010-10-13 22:23:56 +08003185 // Interface for bccGetExportVars()
3186 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003187 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003188 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003189 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003190
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003191 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3192 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3193 if (actualVarCount)
3194 *actualVarCount = varCount;
3195 if (varCount > maxVarCount)
3196 varCount = maxVarCount;
3197 if (vars) {
3198 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3199 mCacheHdr->exportVarsOffset);
3200
3201 for (int i = 0; i < varCount; i++) {
3202 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3203 mCacheDiff);
3204 cachedVars++;
3205 }
3206 }
3207 return;
3208 }
3209
3210 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003211 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003212 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003213 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003214 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003215 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003216 for (ExportVarList::const_iterator I = mExportVars.begin(),
3217 E = mExportVars.end();
3218 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003219 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003220 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003221 }
3222 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003223
3224 return;
3225 }
3226
Zonr Chang932648d2010-10-13 22:23:56 +08003227 // Interface for bccGetExportFuncs()
3228 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003229 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003230 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003231 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003232
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003233 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3234 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3235 if (actualFuncCount)
3236 *actualFuncCount = funcCount;
3237 if (funcCount > maxFuncCount)
3238 funcCount = maxFuncCount;
3239 if (funcs) {
3240 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3241 mCacheHdr->exportFuncsOffset);
3242
3243 for (int i = 0; i < funcCount; i++) {
3244 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3245 mCacheDiff);
3246 cachedFuncs++;
3247 }
3248 }
3249 return;
3250 }
3251
3252 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003253 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003254 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003255 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003256 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003257 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003258 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3259 E = mExportFuncs.end();
3260 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003261 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003262 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003263 }
3264 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003265
3266 return;
3267 }
3268
Zonr Chang932648d2010-10-13 22:23:56 +08003269 // Interface for bccGetPragmas()
3270 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003271 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003272 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003273 int stringCount;
3274 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3275 if (actualStringCount)
3276 *actualStringCount = 0; // XXX
3277 return;
3278 }
3279
3280 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003281
Zonr Chang932648d2010-10-13 22:23:56 +08003282 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003283 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003284 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003285 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003286 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003287 for (PragmaList::const_iterator it = mPragmas.begin();
3288 stringCount > 0;
3289 stringCount -= 2, it++) {
3290 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3291 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003292 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003293 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003294
3295 return;
3296 }
3297
Zonr Chang932648d2010-10-13 22:23:56 +08003298 // Interface for bccGetFunctions()
3299 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003300 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003301 BCCchar **functions) {
3302 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003303 mCodeEmitter->getFunctionNames(actualFunctionCount,
3304 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003305 functions);
3306 else
3307 *actualFunctionCount = 0;
3308
3309 return;
3310 }
3311
Zonr Chang932648d2010-10-13 22:23:56 +08003312 // Interface for bccGetFunctionBinary()
3313 void getFunctionBinary(BCCchar *function,
3314 BCCvoid **base,
3315 BCCsizei *length) {
3316 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003317 mCodeEmitter->getFunctionBinary(function, base, length);
3318 } else {
3319 *base = NULL;
3320 *length = 0;
3321 }
3322 return;
3323 }
3324
Zonr Chang932648d2010-10-13 22:23:56 +08003325 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003326 return mModule;
3327 }
3328
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003329 ~Compiler() {
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003330 // #ifdef BCC_CODE_ADDR
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003331 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3332 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3333 LOGE("munmap failed while releasing mCodeDataAddr\n");
3334 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003335 if (mCacheMapAddr) {
3336 free(mCacheMapAddr);
3337 }
3338 } else {
3339 if (mCacheMapAddr != 0 && mCacheMapAddr != MAP_FAILED) {
3340 if (munmap(mCacheMapAddr, mCacheSize) < 0) {
3341 LOGE("munmap failed while releasing mCacheMapAddr\n");
3342 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003343 }
3344 }
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003345
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003346 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003347 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003348 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003349 return;
3350 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003351
3352 private:
3353 // Note: loader() and genCacheFile() go hand in hand
3354 void genCacheFile() {
3355 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3356 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3357 return;
3358 }
3359
3360 bool codeOffsetNeedPadding = false;
3361
3362 uint32_t offset = sizeof(oBCCHeader);
3363
3364 // BCC Cache File Header
3365 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3366
3367 if (!hdr) {
3368 LOGE("Unable to allocate oBCCHeader.\n");
3369 return;
3370 }
3371
3372 // Magic Words
3373 memcpy(hdr->magic, OBCC_MAGIC, 4);
3374 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3375
3376 // Timestamp
3377 hdr->sourceWhen = 0; // TODO(all)
3378 hdr->rslibWhen = 0; // TODO(all)
3379 hdr->libRSWhen = 0; // TODO(all)
3380 hdr->libbccWhen = 0; // TODO(all)
3381
3382 // Current Memory Address (Saved for Recalculation)
3383 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3384 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3385 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3386
3387 // Relocation Table Offset and Entry Count
3388 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003389 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003390
Logan824dd0a2010-11-20 01:45:54 +08003391 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003392
3393 // Export Variable Table Offset and Entry Count
3394 hdr->exportVarsOffset = offset;
3395 hdr->exportVarsCount = mExportVars.size();
3396
3397 offset += hdr->exportVarsCount * sizeof(uint32_t);
3398
3399 // Export Function Table Offset and Entry Count
3400 hdr->exportFuncsOffset = offset;
3401 hdr->exportFuncsCount = mExportFuncs.size();
3402
3403 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3404
3405 // Export Pragmas Table Offset and Entry Count
3406 hdr->exportPragmasOffset = offset;
3407 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3408
3409 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3410
3411 // Code Offset and Size
3412
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003413 //#ifdef BCC_CODE_ADDR
3414 { // Always pad to the page boundary for now
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003415 long pagesize = sysconf(_SC_PAGESIZE);
3416
3417 if (offset % pagesize > 0) {
3418 codeOffsetNeedPadding = true;
3419 offset += pagesize - (offset % pagesize);
3420 }
3421 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003422 /*#else
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003423 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3424 codeOffsetNeedPadding = true;
3425 offset += 0x08 - (offset & 0x07);
3426 }
Shih-wei Liao1f45b862010-11-21 23:22:38 -08003427 #endif*/
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003428
3429 hdr->codeOffset = offset;
3430 hdr->codeSize = MaxCodeSize;
3431
3432 offset += hdr->codeSize;
3433
3434 // Data (Global Variable) Offset and Size
3435 hdr->dataOffset = offset;
3436 hdr->dataSize = MaxGlobalVarSize;
3437
3438 offset += hdr->dataSize;
3439
3440 // Checksum
3441 hdr->checksum = 0; // Set Field checksum. TODO(all)
3442
3443 // Write Header
3444 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3445 sizeof(oBCCHeader), "Write oBCC header");
3446
Logan824dd0a2010-11-20 01:45:54 +08003447 // Write Relocation Entry Table
3448 {
3449 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003450
Logan824dd0a2010-11-20 01:45:54 +08003451 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3452
3453 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3454 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003455 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003456
3457 // Write Export Variables Table
3458 {
3459 uint32_t *record, *ptr;
3460
3461 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3462 ptr = record;
3463
3464 if (!record) {
3465 goto bail;
3466 }
3467
3468 for (ExportVarList::const_iterator I = mExportVars.begin(),
3469 E = mExportVars.end(); I != E; I++) {
3470 *ptr++ = reinterpret_cast<uint32_t>(*I);
3471 }
3472
3473 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3474 hdr->exportVarsCount * sizeof(uint32_t),
3475 "Write ExportVars");
3476
3477 free(record);
3478 }
3479
3480 // Write Export Functions Table
3481 {
3482 uint32_t *record, *ptr;
3483
3484 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3485 ptr = record;
3486
3487 if (!record) {
3488 goto bail;
3489 }
3490
3491 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3492 E = mExportFuncs.end(); I != E; I++) {
3493 *ptr++ = reinterpret_cast<uint32_t>(*I);
3494 }
3495
3496 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3497 hdr->exportFuncsCount * sizeof(uint32_t),
3498 "Write ExportFuncs");
3499
3500 free(record);
3501 }
3502
3503
3504 // TODO(all): Write Export Pragmas Table
3505#if 0
3506#else
3507 // Note: As long as we have comment out export pragmas table code,
3508 // we have to seek the position to correct offset.
3509
3510 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3511#endif
3512
3513 if (codeOffsetNeedPadding) {
3514 // requires additional padding
3515 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3516 }
3517
3518 // Write Generated Code and Global Variable
3519 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3520 "Write code and global variable");
3521
3522 goto close_return;
3523
3524 bail:
3525 if (ftruncate(mCacheFd, 0) != 0) {
3526 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3527 }
3528
3529 close_return:
3530 free(hdr);
3531 close(mCacheFd);
3532 mCacheFd = -1;
3533 return;
3534 }
3535
3536 // OpenCacheFile() returns fd of the cache file.
3537 // Input:
3538 // BCCchar *resName: Used to genCacheFileName()
3539 // bool createIfMissing: If false, turn off caching
3540 // Output:
3541 // returns fd: If -1: Failed
3542 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3543 // cache file's file descriptor
3544 // Note: openCacheFile() will check the cache file's validity,
3545 // such as Magic number, sourceWhen... dependencies.
3546 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3547 int fd, cc;
3548 struct stat fdStat, fileStat;
3549 bool readOnly = false;
3550
3551 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3552
3553 mCacheNew = false;
3554
3555 retry:
3556 /*
3557 * Try to open the cache file. If we've been asked to,
3558 * create it if it doesn't exist.
3559 */
3560 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3561 if (fd < 0) {
3562 fd = open(cacheFileName, O_RDONLY, 0);
3563 if (fd < 0) {
3564 if (createIfMissing) {
3565 LOGE("Can't open bcc-cache '%s': %s\n",
3566 cacheFileName, strerror(errno));
3567 mCacheNew = true;
3568 }
3569 return fd;
3570 }
3571 readOnly = true;
3572 }
3573
3574 /*
3575 * Grab an exclusive lock on the cache file. If somebody else is
3576 * working on it, we'll block here until they complete.
3577 */
3578 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3579 cacheFileName, fd);
3580
3581 cc = flock(fd, LOCK_EX | LOCK_NB);
3582 if (cc != 0) {
3583 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3584 cc = flock(fd, LOCK_EX);
3585 }
3586
3587 if (cc != 0) {
3588 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3589 close(fd);
3590 return -1;
3591 }
3592 LOGV("bcc: locked cache file\n");
3593
3594 /*
3595 * Check to see if the fd we opened and locked matches the file in
3596 * the filesystem. If they don't, then somebody else unlinked ours
3597 * and created a new file, and we need to use that one instead. (If
3598 * we caught them between the unlink and the create, we'll get an
3599 * ENOENT from the file stat.)
3600 */
3601 cc = fstat(fd, &fdStat);
3602 if (cc != 0) {
3603 LOGE("Can't stat open file '%s'\n", cacheFileName);
3604 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3605 goto close_fail;
3606 }
3607 cc = stat(cacheFileName, &fileStat);
3608 if (cc != 0 ||
3609 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3610 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3611 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3612 flock(fd, LOCK_UN);
3613 close(fd);
3614 usleep(250 * 1000); // if something is hosed, don't peg machine
3615 goto retry;
3616 }
3617
3618 /*
3619 * We have the correct file open and locked. If the file size is zero,
3620 * then it was just created by us, and we want to fill in some fields
3621 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3622 * verify that the fields in the header match our expectations, and
3623 * reset the file if they don't.
3624 */
3625 if (fdStat.st_size == 0) {
3626 if (readOnly) { // The device is readOnly --> close_fail
3627 LOGW("bcc: file has zero length and isn't writable\n");
3628 goto close_fail;
3629 }
3630 /*cc = createEmptyHeader(fd);
3631 if (cc != 0)
3632 goto close_fail;
3633 */
3634 mCacheNew = true;
3635 LOGV("bcc: successfully initialized new cache file\n");
3636 } else {
3637 // Calculate sourceWhen
3638 // XXX
3639 uint32_t sourceWhen = 0;
3640 uint32_t rslibWhen = 0;
3641 uint32_t libRSWhen = 0;
3642 uint32_t libbccWhen = 0;
3643 if (!checkHeaderAndDependencies(fd,
3644 sourceWhen,
3645 rslibWhen,
3646 libRSWhen,
3647 libbccWhen)) {
3648 // If checkHeaderAndDependencies returns 0: FAILED
3649 // Will truncate the file and retry to createIfMissing the file
3650
3651 if (readOnly) { // Shouldn't be readonly.
3652 /*
3653 * We could unlink and rewrite the file if we own it or
3654 * the "sticky" bit isn't set on the directory. However,
3655 * we're not able to truncate it, which spoils things. So,
3656 * give up now.
3657 */
3658 if (createIfMissing) {
3659 LOGW("Cached file %s is stale and not writable\n",
3660 cacheFileName);
3661 }
3662 goto close_fail;
3663 }
3664
3665 /*
3666 * If we truncate the existing file before unlinking it, any
3667 * process that has it mapped will fail when it tries to touch
3668 * the pages? Probably OK because we use MAP_PRIVATE.
3669 */
3670 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3671 cacheFileName);
3672 if (ftruncate(fd, 0) != 0) {
3673 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3674 cacheFileName, strerror(errno));
3675 /* keep going */
3676 }
3677 if (unlink(cacheFileName) != 0) {
3678 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3679 cacheFileName, errno, strerror(errno));
3680 /* keep going; permission failure should probably be fatal */
3681 }
3682 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3683 flock(fd, LOCK_UN);
3684 close(fd);
3685 goto retry;
3686 } else {
3687 // Got cacheFile! Good to go.
3688 LOGV("Good cache file\n");
3689 }
3690 }
3691
3692 assert(fd >= 0);
3693 return fd;
3694
3695 close_fail:
3696 flock(fd, LOCK_UN);
3697 close(fd);
3698 return -1;
3699 } // End of openCacheFile()
3700
3701 char *genCacheFileName(const char *fileName, const char *subFileName) {
3702 char nameBuf[512];
3703 static const char kCachePath[] = "bcc-cache";
3704 char absoluteFile[sizeof(nameBuf)];
3705 const size_t kBufLen = sizeof(nameBuf) - 1;
3706 const char *dataRoot;
3707 char *cp;
3708
3709 // Get the absolute path of the raw/***.bc file.
3710 absoluteFile[0] = '\0';
3711 if (fileName[0] != '/') {
3712 /*
3713 * Generate the absolute path. This doesn't do everything it
3714 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3715 * the leading "./" out, but it'll do.
3716 */
3717 if (getcwd(absoluteFile, kBufLen) == NULL) {
3718 LOGE("Can't get CWD while opening raw/***.bc file\n");
3719 return NULL;
3720 }
3721 // TODO(srhines): strncat() is a bit dangerous
3722 strncat(absoluteFile, "/", kBufLen);
3723 }
3724 strncat(absoluteFile, fileName, kBufLen);
3725
3726 if (subFileName != NULL) {
3727 strncat(absoluteFile, "/", kBufLen);
3728 strncat(absoluteFile, subFileName, kBufLen);
3729 }
3730
3731 /* Turn the path into a flat filename by replacing
3732 * any slashes after the first one with '@' characters.
3733 */
3734 cp = absoluteFile + 1;
3735 while (*cp != '\0') {
3736 if (*cp == '/') {
3737 *cp = '@';
3738 }
3739 cp++;
3740 }
3741
3742 /* Build the name of the cache directory.
3743 */
3744 dataRoot = getenv("ANDROID_DATA");
3745 if (dataRoot == NULL)
3746 dataRoot = "/data";
3747 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3748
3749 /* Tack on the file name for the actual cache file path.
3750 */
3751 strncat(nameBuf, absoluteFile, kBufLen);
3752
3753 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3754 return strdup(nameBuf);
3755 }
3756
3757 /*
3758 * Read the oBCC header, verify it, then read the dependent section
3759 * and verify that data as well.
3760 *
3761 * On successful return, the file will be seeked immediately past the
3762 * oBCC header.
3763 */
3764 bool checkHeaderAndDependencies(int fd,
3765 uint32_t sourceWhen,
3766 uint32_t rslibWhen,
3767 uint32_t libRSWhen,
3768 uint32_t libbccWhen) {
3769 ssize_t actual;
3770 oBCCHeader optHdr;
3771 uint32_t val;
3772 uint8_t const *magic, *magicVer;
3773
3774 /*
3775 * Start at the start. The "bcc" header, when present, will always be
3776 * the first thing in the file.
3777 */
3778 if (lseek(fd, 0, SEEK_SET) != 0) {
3779 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3780 goto bail;
3781 }
3782
3783 /*
3784 * Read and do trivial verification on the bcc header. The header is
3785 * always in host byte order.
3786 */
3787 actual = read(fd, &optHdr, sizeof(optHdr));
3788 if (actual < 0) {
3789 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3790 goto bail;
3791 } else if (actual != sizeof(optHdr)) {
3792 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3793 (int) actual, sizeof(optHdr));
3794 goto bail;
3795 }
3796
3797 magic = optHdr.magic;
3798 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3799 /* not an oBCC file, or previous attempt was interrupted */
3800 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3801 magic[0], magic[1], magic[2], magic[3]);
3802 goto bail;
3803 }
3804
3805 magicVer = optHdr.magicVersion;
3806 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3807 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3808 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3809 goto bail;
3810 }
3811
3812 /*
3813 * Do the header flags match up with what we want?
3814 *
3815 * This is useful because it allows us to automatically regenerate
3816 * a file when settings change (e.g. verification is now mandatory),
3817 * but can cause difficulties if the thing we depend upon
3818 * were handled differently than the current options specify.
3819 *
3820 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3821 * by limiting the match mask.
3822 *
3823 * The only thing we really can't handle is incorrect byte-ordering.
3824 */
3825
3826 val = optHdr.sourceWhen;
3827 if (val && (val != sourceWhen)) {
3828 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3829 val, sourceWhen);
3830 goto bail;
3831 }
3832 val = optHdr.rslibWhen;
3833 if (val && (val != rslibWhen)) {
3834 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3835 val, rslibWhen);
3836 goto bail;
3837 }
3838 val = optHdr.libRSWhen;
3839 if (val && (val != libRSWhen)) {
3840 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3841 val, libRSWhen);
3842 goto bail;
3843 }
3844 val = optHdr.libbccWhen;
3845 if (val && (val != libbccWhen)) {
3846 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3847 val, libbccWhen);
3848 goto bail;
3849 }
3850
3851 return true;
3852
3853 bail:
3854 return false;
3855 }
3856
Zonr Chang932648d2010-10-13 22:23:56 +08003857};
3858// End of Class Compiler
3859////////////////////////////////////////////////////////////////////////////////
3860
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003861
3862bool Compiler::GlobalInitialized = false;
3863
Zonr Chang932648d2010-10-13 22:23:56 +08003864// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003865llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3866
3867std::string Compiler::Triple;
3868
3869std::string Compiler::CPU;
3870
3871std::vector<std::string> Compiler::Features;
3872
Zonr Chang932648d2010-10-13 22:23:56 +08003873// The named of metadata node that pragma resides (should be synced with
3874// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003875const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3876
Zonr Chang932648d2010-10-13 22:23:56 +08003877// The named of metadata node that export variable name resides (should be
3878// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003879const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3880
Zonr Chang932648d2010-10-13 22:23:56 +08003881// The named of metadata node that export function name resides (should be
3882// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003883const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3884
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003885struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003886 //////////////////////////////////////////////////////////////////////////////
3887 // Part I. Compiler
3888 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003889 Compiler compiler;
3890
Zonr Chang932648d2010-10-13 22:23:56 +08003891 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003892 compiler.registerSymbolCallback(pFn, pContext);
3893 }
3894
Zonr Chang932648d2010-10-13 22:23:56 +08003895 //////////////////////////////////////////////////////////////////////////////
3896 // Part II. Logistics & Error handling
3897 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003898 BCCscript() {
3899 bccError = BCC_NO_ERROR;
3900 }
3901
3902 ~BCCscript() {
3903 }
3904
3905 void setError(BCCenum error) {
3906 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3907 bccError = error;
3908 }
3909 }
3910
3911 BCCenum getError() {
3912 BCCenum result = bccError;
3913 bccError = BCC_NO_ERROR;
3914 return result;
3915 }
3916
3917 BCCenum bccError;
3918};
3919
3920
3921extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003922BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003923 return new BCCscript();
3924}
3925
3926extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003927BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003928 return script->getError();
3929}
3930
3931extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003932void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003933 delete script;
3934}
3935
3936extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003937void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003938 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08003939 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003940 script->registerSymbolCallback(pFn, pContext);
3941}
3942
3943extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003944int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08003945 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003946 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08003947}
3948
3949extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003950int bccReadBC(BCCscript *script,
3951 const BCCchar *bitcode,
3952 BCCint size,
3953 const BCCchar *resName) {
3954 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003955}
3956
3957extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003958void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08003959 const BCCchar *bitcode,
3960 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003961 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08003962}
3963
3964extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003965void bccLoadBinary(BCCscript *script) {
3966 int result = script->compiler.loader();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003967 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003968 script->setError(BCC_INVALID_OPERATION);
3969}
3970
3971extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003972void bccCompileBC(BCCscript *script) {
3973 {
3974#if defined(__arm__)
3975 android::StopWatch compileTimer("RenderScript compile time");
3976#endif
3977 int result = script->compiler.compile();
3978 if (result)
3979 script->setError(BCC_INVALID_OPERATION);
3980 }
3981}
3982
3983extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003984void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003985 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08003986 BCCsizei *length,
3987 BCCchar *infoLog) {
3988 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003989 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003990 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003991 *length = messageLength;
3992
3993 if (infoLog && maxLength > 0) {
3994 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
3995 memcpy(infoLog, message, trimmedLength);
3996 infoLog[trimmedLength] = 0;
3997 }
3998}
3999
4000extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004001void bccGetScriptLabel(BCCscript *script,
4002 const BCCchar *name,
4003 BCCvoid **address) {
4004 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004005 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004006 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004007 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004008 script->setError(BCC_INVALID_VALUE);
4009}
4010
4011extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004012void bccGetExportVars(BCCscript *script,
4013 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004014 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004015 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004016 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4017}
4018
4019extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004020void bccGetExportFuncs(BCCscript *script,
4021 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004022 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004023 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004024 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4025}
4026
4027extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004028void bccGetPragmas(BCCscript *script,
4029 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004030 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004031 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004032 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4033}
4034
4035extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004036void bccGetFunctions(BCCscript *script,
4037 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004038 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004039 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004040 script->compiler.getFunctions(actualFunctionCount,
4041 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004042 functions);
4043}
4044
4045extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004046void bccGetFunctionBinary(BCCscript *script,
4047 BCCchar *function,
4048 BCCvoid **base,
4049 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004050 script->compiler.getFunctionBinary(function, base, length);
4051}
4052
4053struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004054 const Compiler *compiler;
4055 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004056};
4057
Zonr Chang932648d2010-10-13 22:23:56 +08004058} // namespace bcc