blob: d44d241a280b07f19e47f83fcc90faa4fdf67dd2 [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.
21// So when mLoaded == 1, will set mCacheNever to true.
22#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;
302
Zonr Chang932648d2010-10-13 22:23:56 +0800303 // If given, this will be the name of the target triple to compile for.
304 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700305 static std::string Triple;
306
307 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700308
Zonr Chang932648d2010-10-13 22:23:56 +0800309 // End of section of GlobalInitializing variables
310 //////////////////////////////////////////////////////////////////////////////
311
312 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700313 static std::string CPU;
314
Zonr Chang932648d2010-10-13 22:23:56 +0800315 // The list of target specific features to enable or disable -- this should
316 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700317 static std::vector<std::string> Features;
318
319 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800320 const char *mName;
321 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700322 };
323 static struct Runtime Runtimes[];
324
325 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800326 if (GlobalInitialized)
327 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700328
Zonr Chang932648d2010-10-13 22:23:56 +0800329 // if (!llvm::llvm_is_multithreaded())
330 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700331
Zonr Chang932648d2010-10-13 22:23:56 +0800332 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700333 Triple = TARGET_TRIPLE_STRING;
334
Zonr Chang932648d2010-10-13 22:23:56 +0800335 // TODO(zonr): NEON for JIT
336 // Features.push_back("+neon");
337 // Features.push_back("+vmlx");
338 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700339 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700340 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700341
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700342#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
343 LLVMInitializeARMTargetInfo();
344 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700345#if defined(USE_DISASSEMBLER)
346 LLVMInitializeARMDisassembler();
347 LLVMInitializeARMAsmPrinter();
348#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700349#endif
350
351#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
352 LLVMInitializeX86TargetInfo();
353 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700354#if defined(USE_DISASSEMBLER)
355 LLVMInitializeX86Disassembler();
356 LLVMInitializeX86AsmPrinter();
357#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700358#endif
359
360#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
361 LLVMInitializeX86TargetInfo();
362 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700363#if defined(USE_DISASSEMBLER)
364 LLVMInitializeX86Disassembler();
365 LLVMInitializeX86AsmPrinter();
366#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700367#endif
368
Zonr Chang932648d2010-10-13 22:23:56 +0800369 // -O0: llvm::CodeGenOpt::None
370 // -O1: llvm::CodeGenOpt::Less
371 // -O2: llvm::CodeGenOpt::Default
372 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700373 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700374
Zonr Chang932648d2010-10-13 22:23:56 +0800375 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700376
Zonr Chang932648d2010-10-13 22:23:56 +0800377 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700378 llvm::NoFramePointerElim = false;
379
Zonr Chang932648d2010-10-13 22:23:56 +0800380 // Use hardfloat ABI
381 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800382 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800383 // softfp. To use softfp, change following 2 lines to
384 //
385 // llvm::FloatABIType = llvm::FloatABI::Soft;
386 // llvm::UseSoftFloat = true;
387 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700388 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700389 llvm::UseSoftFloat = false;
390
Zonr Chang932648d2010-10-13 22:23:56 +0800391 // BCC needs all unknown symbols resolved at JIT/compilation time.
392 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700393 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
394
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700395#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800396 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700397 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
398#else
Zonr Chang932648d2010-10-13 22:23:56 +0800399 // This is set for the linker (specify how large of the virtual addresses
400 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700401 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
402#endif
403
Zonr Chang932648d2010-10-13 22:23:56 +0800404 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700405 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
406
Zonr Chang932648d2010-10-13 22:23:56 +0800407 // Register allocation policy:
408 // createFastRegisterAllocator: fast but bad quality
409 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700410 llvm::RegisterRegAlloc::setDefault
411 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700412 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700413 llvm::createLinearScanRegisterAllocator);
414
415 GlobalInitialized = true;
416 return;
417 }
418
419 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800420 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700421 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700422 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800423 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700424 }
425
426 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700427 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700428 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700429
430 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700431 std::string mError;
432
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700433 inline bool hasError() const {
434 return !mError.empty();
435 }
Zonr Chang932648d2010-10-13 22:23:56 +0800436 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700437 mError.assign(Error); // Copying
438 return;
439 }
Zonr Chang932648d2010-10-13 22:23:56 +0800440 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700441 mError = Error;
442 return;
443 }
444
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800445 bool mNeverCache; // Set by readBC()
446 bool mCacheNew; // Set by readBC()
447 int mCacheFd; // Set by readBC()
448 char *mCacheMapAddr; // Set by loader() if mCacheNew is false
449 oBCCHeader *mCacheHdr; // Set by loader()
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800450 size_t mCacheSize; // Set by loader()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800451 ptrdiff_t mCacheDiff; // Set by loader()
452 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
453 // Used by genCacheFile() for dumping
454
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700455 typedef std::list< std::pair<std::string, std::string> > PragmaList;
456 PragmaList mPragmas;
457
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700458 typedef std::list<void*> ExportVarList;
459 ExportVarList mExportVars;
460
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700461 typedef std::list<void*> ExportFuncList;
462 ExportFuncList mExportFuncs;
463
Zonr Chang932648d2010-10-13 22:23:56 +0800464 //////////////////////////////////////////////////////////////////////////////
465 // Memory manager for the code reside in memory
466 //
467 // The memory for our code emitter is very simple and is conforming to the
468 // design decisions of Android RenderScript's Exection Environment:
469 // The code, data, and symbol sizes are limited (currently 100KB.)
470 //
471 // It's very different from typical compiler, which has no limitation
472 // on the code size. How does code emitter know the size of the code
473 // it is about to emit? It does not know beforehand. We want to solve
474 // this without complicating the code emitter too much.
475 //
476 // We solve this by pre-allocating a certain amount of memory,
477 // and then start the code emission. Once the buffer overflows, the emitter
478 // simply discards all the subsequent emission but still has a counter
479 // on how many bytes have been emitted.
480 //
481 // So once the whole emission is done, if there's a buffer overflow,
482 // it re-allocates the buffer with enough size (based on the
483 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800484
485 // 128 KiB for code
486 static const unsigned int MaxCodeSize = 128 * 1024;
487 // 1 KiB for global offset table (GOT)
488 static const unsigned int MaxGOTSize = 1 * 1024;
489 // 128 KiB for global variable
490 static const unsigned int MaxGlobalVarSize = 128 * 1024;
491
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700492 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700493 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800494 //
495 // Our memory layout is as follows:
496 //
497 // The direction of arrows (-> and <-) shows memory's growth direction
498 // when more space is needed.
499 //
500 // @mpCodeMem:
501 // +--------------------------------------------------------------+
502 // | Function Memory ... -> <- ... Stub/GOT |
503 // +--------------------------------------------------------------+
504 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
505 //
506 // Where size of GOT is @MaxGOTSize KiB.
507 //
508 // @mpGVMem:
509 // +--------------------------------------------------------------+
510 // | Global variable ... -> |
511 // +--------------------------------------------------------------+
512 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
513 //
514 //
515 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
516 // of function code's memory usage
517 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
518 // of stub/GOT's memory usage
519 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
520 // of global variable's memory usage
521 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700522 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700523 uintptr_t mCurSGMemIdx;
524 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800525 void *mpCodeMem;
526 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700527
Zonr Chang932648d2010-10-13 22:23:56 +0800528 // GOT Base
529 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700530
531 typedef std::map<const llvm::Function*, pair<void* /* start address */,
532 void* /* end address */>
533 > FunctionMapTy;
534 FunctionMapTy mFunctionMap;
535
Zonr Chang932648d2010-10-13 22:23:56 +0800536 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700537 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700538 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700539
Zonr Chang932648d2010-10-13 22:23:56 +0800540 uint8_t *allocateSGMemory(uintptr_t Size,
541 unsigned Alignment = 1 /* no alignment */) {
542 intptr_t FreeMemSize = getFreeCodeMemSize();
543 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
544 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700545 return NULL;
546
Zonr Chang932648d2010-10-13 22:23:56 +0800547 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700548 Alignment = 1;
549
Zonr Chang932648d2010-10-13 22:23:56 +0800550 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700551 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
552
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700553 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700554
555 return result;
556 }
557
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700558 inline uintptr_t getFreeGVMemSize() const {
559 return MaxGlobalVarSize - mCurGVMemIdx;
560 }
Zonr Chang932648d2010-10-13 22:23:56 +0800561 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700562 return reinterpret_cast<uint8_t*>(mpGVMem);
563 }
564
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700565 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700566 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700567 reset();
568 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700569
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800570#ifdef BCC_CODE_ADDR
571 mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
572 MaxCodeSize + MaxGlobalVarSize,
573 PROT_READ | PROT_EXEC | PROT_WRITE,
574 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
575 -1,
576 0);
577#else
578 mpCodeMem = mmap(NULL,
579 MaxCodeSize + MaxGlobalVarSize,
580 PROT_READ | PROT_EXEC | PROT_WRITE,
581 MAP_PRIVATE | MAP_ANON,
582 -1,
583 0);
584#endif
585
586 if (mpCodeMem == MAP_FAILED) {
587 llvm::report_fatal_error("Failed to allocate memory for emitting "
588 "codes\n" + ErrMsg);
589 }
590 mpGVMem = (void *) ((int) mpCodeMem + MaxCodeSize);
591
592 /* mpCodeMem = mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700593 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700594 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800595 llvm::report_fatal_error("Failed to allocate memory for emitting "
596 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700597
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800598 mpGVMem = mmap(mpCodeMem, MaxGlobalVarSize,
599 PROT_READ | PROT_WRITE,
600 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700601 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800602 llvm::report_fatal_error("Failed to allocate memory for emitting "
603 "global variables\n" + ErrMsg);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800604 */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700605 return;
606 }
607
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800608 inline uint8_t *getCodeMemBase() const {
609 return reinterpret_cast<uint8_t*>(mpCodeMem);
610 }
611
Zonr Chang932648d2010-10-13 22:23:56 +0800612 // setMemoryWritable - When code generation is in progress, the code pages
613 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700614 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700615 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700616 return;
617 }
618
Zonr Chang932648d2010-10-13 22:23:56 +0800619 // When code generation is done and we're ready to start execution, the
620 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700621 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700622 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700623 return;
624 }
625
Zonr Chang932648d2010-10-13 22:23:56 +0800626 // Setting this flag to true makes the memory manager garbage values over
627 // freed memory. This is useful for testing and debugging, and is to be
628 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700629 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800630 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700631 return;
632 }
633
Zonr Chang932648d2010-10-13 22:23:56 +0800634 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700635
Zonr Chang932648d2010-10-13 22:23:56 +0800636 // If the current table requires a Global Offset Table, this method is
637 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700638 void AllocateGOT() {
639 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700640 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700641 HasGOT = true;
642 return;
643 }
644
Zonr Chang932648d2010-10-13 22:23:56 +0800645 // If this is managing a Global Offset Table, this method should return a
646 // pointer to its base.
647 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700648 return mpGOTBase;
649 }
650
Zonr Chang932648d2010-10-13 22:23:56 +0800651 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700652
Zonr Chang932648d2010-10-13 22:23:56 +0800653 // When we start JITing a function, the JIT calls this method to allocate a
654 // block of free RWX memory, which returns a pointer to it. If the JIT wants
655 // to request a block of memory of at least a certain size, it passes that
656 // value as ActualSize, and this method returns a block with at least that
657 // much space. If the JIT doesn't know ahead of time how much space it will
658 // need to emit the function, it passes 0 for the ActualSize. In either
659 // case, this method is required to pass back the size of the allocated
660 // block through ActualSize. The JIT will be careful to not write more than
661 // the returned ActualSize bytes of memory.
662 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
663 intptr_t FreeMemSize = getFreeCodeMemSize();
664 if ((FreeMemSize < 0) ||
665 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
666 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700667 return NULL;
668
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700669 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700670 return (getCodeMemBase() + mCurFuncMemIdx);
671 }
672
Zonr Chang932648d2010-10-13 22:23:56 +0800673 // This method is called by the JIT to allocate space for a function stub
674 // (used to handle limited branch displacements) while it is JIT compiling a
675 // function. For example, if foo calls bar, and if bar either needs to be
676 // lazily compiled or is a native function that exists too far away from the
677 // call site to work, this method will be used to make a thunk for it. The
678 // stub should be "close" to the current function body, but should not be
679 // included in the 'actualsize' returned by startFunctionBody.
680 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700681 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700682 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700683 }
684
Zonr Chang932648d2010-10-13 22:23:56 +0800685 // This method is called when the JIT is done codegen'ing the specified
686 // function. At this point we know the size of the JIT compiled function.
687 // This passes in FunctionStart (which was returned by the startFunctionBody
688 // method) and FunctionEnd which is a pointer to the actual end of the
689 // function. This method should mark the space allocated and remember where
690 // it is in case the client wants to deallocate it.
691 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
692 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700693 assert(FunctionEnd > FunctionStart);
694 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
695 "Mismatched function start/end!");
696
Zonr Chang932648d2010-10-13 22:23:56 +0800697 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700698 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700699 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700700 "Code size excess the limitation!");
701 mCurFuncMemIdx += FunctionCodeSize;
702
Zonr Chang932648d2010-10-13 22:23:56 +0800703 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700704 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
705 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800706 mFunctionMap.insert(
707 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
708 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700709
710 return;
711 }
712
Zonr Chang932648d2010-10-13 22:23:56 +0800713 // Allocate a (function code) memory block of the given size. This method
714 // cannot be called between calls to startFunctionBody and endFunctionBody.
715 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
716 if (getFreeCodeMemSize() < Size)
717 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700718 return NULL;
719
Zonr Chang932648d2010-10-13 22:23:56 +0800720 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700721 Alignment = 1;
722
Zonr Chang932648d2010-10-13 22:23:56 +0800723 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700724 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800725 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700726
727 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
728
729 return result;
730 }
731
Zonr Chang932648d2010-10-13 22:23:56 +0800732 // Allocate memory for a global variable.
733 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700734 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800735 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700736 LOGE("No Global Memory");
737 return NULL;
738 }
739
Zonr Chang932648d2010-10-13 22:23:56 +0800740 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700741 Alignment = 1;
742
Zonr Chang932648d2010-10-13 22:23:56 +0800743 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700744 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800745 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700746
747 mCurGVMemIdx = (result + Size) - getGVMemBase();
748
749 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700750 }
751
Zonr Chang932648d2010-10-13 22:23:56 +0800752 // Free the specified function body. The argument must be the return value
753 // from a call to startFunctionBody() that hasn't been deallocated yet. This
754 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700755 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800756 // linear search
757 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
758 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
759 E = mFunctionMap.end();
760 I != E;
761 I++)
762 if (I->second.first == Body) {
763 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
764 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700765 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800766 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700767
Zonr Chang932648d2010-10-13 22:23:56 +0800768 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700769
Zonr Chang932648d2010-10-13 22:23:56 +0800770 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700771 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
772
773 assert(SizeNeedMove >= 0 &&
774 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
775 " be correctly calculated!");
776
Zonr Chang932648d2010-10-13 22:23:56 +0800777 if (SizeNeedMove > 0)
778 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700779 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
780 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
781
782 return;
783 }
784
Zonr Chang932648d2010-10-13 22:23:56 +0800785 // When we finished JITing the function, if exception handling is set, we
786 // emit the exception table.
787 uint8_t *startExceptionTable(const llvm::Function *F,
788 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700789 assert(false && "Exception is not allowed in our language specification");
790 return NULL;
791 }
792
Zonr Chang932648d2010-10-13 22:23:56 +0800793 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700794 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800795 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700796 assert(false && "Exception is not allowed in our language specification");
797 return;
798 }
799
Zonr Chang932648d2010-10-13 22:23:56 +0800800 // Free the specified exception table's memory. The argument must be the
801 // return value from a call to startExceptionTable() that hasn't been
802 // deallocated yet. This is never called when the JIT is currently emitting
803 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700804 void deallocateExceptionTable(void *ET) {
805 assert(false && "Exception is not allowed in our language specification");
806 return;
807 }
808
Zonr Chang932648d2010-10-13 22:23:56 +0800809 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700810 void reset() {
811 mpGOTBase = NULL;
812 HasGOT = false;
813
814 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700815 mCurSGMemIdx = MaxCodeSize - 1;
816 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700817
818 mFunctionMap.clear();
819
820 return;
821 }
822
823 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800824 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700825 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800826 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700827 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700828 return;
829 }
Zonr Chang932648d2010-10-13 22:23:56 +0800830 };
831 // End of class CodeMemoryManager
832 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700833
Zonr Chang932648d2010-10-13 22:23:56 +0800834 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700835 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800836 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700837 mCodeMemMgr.reset(new CodeMemoryManager());
838 return mCodeMemMgr.get();
839 }
840
Zonr Chang932648d2010-10-13 22:23:56 +0800841 //////////////////////////////////////////////////////////////////////////////
842 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700843 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700844 public:
845 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
846 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
847
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800848 GlobalAddressMapTy mGlobalAddressMap;
849
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700850 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800851 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700852
Zonr Chang932648d2010-10-13 22:23:56 +0800853 // The JITInfo for the target we are compiling to
854 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700855
Zonr Chang932648d2010-10-13 22:23:56 +0800856 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700857
Zonr Chang932648d2010-10-13 22:23:56 +0800858 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700859
860 class EmittedFunctionCode {
861 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800862 // Beginning of the function's allocation.
863 void *FunctionBody;
864
865 // The address the function's code actually starts at.
866 void *Code;
867
868 // The size of the function code
869 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700870
871 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
872 };
Zonr Chang932648d2010-10-13 22:23:56 +0800873 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700874
Zonr Chang932648d2010-10-13 22:23:56 +0800875 typedef std::map<const std::string,
876 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700877 EmittedFunctionsMapTy mEmittedFunctions;
878
Zonr Chang932648d2010-10-13 22:23:56 +0800879 // This vector is a mapping from MBB ID's to their address. It is filled in
880 // by the StartMachineBasicBlock callback and queried by the
881 // getMachineBasicBlockAddress callback.
882 std::vector<uintptr_t> mMBBLocations;
883
884 // The constant pool for the current function.
885 llvm::MachineConstantPool *mpConstantPool;
886
887 // A pointer to the first entry in the constant pool.
888 void *mpConstantPoolBase;
889
890 // Addresses of individual constant pool entries.
891 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
892
893 // The jump tables for the current function.
894 llvm::MachineJumpTableInfo *mpJumpTable;
895
896 // A pointer to the first entry in the jump table.
897 void *mpJumpTableBase;
898
899 // When outputting a function stub in the context of some other function, we
900 // save BufferBegin/BufferEnd/CurBufferPtr here.
901 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
902
903 // These are the relocations that the function needs, as emitted.
904 std::vector<llvm::MachineRelocation> mRelocations;
905
Logan824dd0a2010-11-20 01:45:54 +0800906 std::vector<oBCCRelocEntry> mCachingRelocations;
907
Zonr Chang932648d2010-10-13 22:23:56 +0800908 // This vector is a mapping from Label ID's to their address.
909 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
910
911 // Machine module info for exception informations
912 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700913
Zonr Chang932648d2010-10-13 22:23:56 +0800914 // Replace an existing mapping for GV with a new address. This updates both
915 // maps as required. If Addr is null, the entry for the global is removed
916 // from the mappings.
917 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
918 if (Addr == NULL) {
919 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700920 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
921 void *OldVal;
922
Zonr Chang932648d2010-10-13 22:23:56 +0800923 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700924 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800925 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700926 OldVal = I->second;
927 mGlobalAddressMap.erase(I);
928 }
929
930 return OldVal;
931 }
932
Zonr Chang932648d2010-10-13 22:23:56 +0800933 void *&CurVal = mGlobalAddressMap[GV];
934 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700935
936 CurVal = Addr;
937
938 return OldVal;
939 }
940
Zonr Chang932648d2010-10-13 22:23:56 +0800941 // Tell the execution engine that the specified global is at the specified
942 // location. This is used internally as functions are JIT'd and as global
943 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700944 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800945 void *&CurVal = mGlobalAddressMap[GV];
946 assert((CurVal == 0 || Addr == 0) &&
947 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700948 CurVal = Addr;
949 return;
950 }
951
Zonr Chang932648d2010-10-13 22:23:56 +0800952 // This returns the address of the specified global value if it is has
953 // already been codegen'd, otherwise it returns null.
954 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700955 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700956 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
957 }
958
Zonr Chang932648d2010-10-13 22:23:56 +0800959 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
960 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700961 MCP->getConstants();
962
Zonr Chang932648d2010-10-13 22:23:56 +0800963 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700964 return 0;
965
966 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800967 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700968 llvm::MachineConstantPoolEntry CPE = Constants[i];
969 unsigned int AlignMask = CPE.getAlignment() - 1;
970 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800971 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700972 Size += mpTD->getTypeAllocSize(Ty);
973 }
974
975 return Size;
976 }
977
Zonr Chang932648d2010-10-13 22:23:56 +0800978 // This function converts a Constant* into a GenericValue. The interesting
979 // part is if C is a ConstantExpr.
980 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
981 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700982 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800983 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
984 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
985 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700986
Zonr Chang932648d2010-10-13 22:23:56 +0800987 switch (CE->getOpcode()) {
988 case llvm::Instruction::GetElementPtr: {
989 // Compute the index
990 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
991 CE->op_end());
992 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
993 &Indices[0],
994 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700995
Zonr Chang932648d2010-10-13 22:23:56 +0800996 GetConstantValue(Op0, Result);
997 Result.PointerVal =
998 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700999
Zonr Chang932648d2010-10-13 22:23:56 +08001000 return;
1001 }
1002 case llvm::Instruction::Trunc: {
1003 uint32_t BitWidth =
1004 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1005
1006 GetConstantValue(Op0, Result);
1007 Result.IntVal = Result.IntVal.trunc(BitWidth);
1008
1009 return;
1010 }
1011 case llvm::Instruction::ZExt: {
1012 uint32_t BitWidth =
1013 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1014
1015 GetConstantValue(Op0, Result);
1016 Result.IntVal = Result.IntVal.zext(BitWidth);
1017
1018 return;
1019 }
1020 case llvm::Instruction::SExt: {
1021 uint32_t BitWidth =
1022 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1023
1024 GetConstantValue(Op0, Result);
1025 Result.IntVal = Result.IntVal.sext(BitWidth);
1026
1027 return;
1028 }
1029 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001030 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001031 GetConstantValue(Op0, Result);
1032 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1033 return;
1034 }
1035 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001036 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001037 GetConstantValue(Op0, Result);
1038 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1039 return;
1040 }
1041 case llvm::Instruction::UIToFP: {
1042 GetConstantValue(Op0, Result);
1043 if (CE->getType()->isFloatTy())
1044 Result.FloatVal =
1045 static_cast<float>(Result.IntVal.roundToDouble());
1046 else if (CE->getType()->isDoubleTy())
1047 Result.DoubleVal = Result.IntVal.roundToDouble();
1048 else if (CE->getType()->isX86_FP80Ty()) {
1049 const uint64_t zero[] = { 0, 0 };
1050 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1051 apf.convertFromAPInt(Result.IntVal,
1052 false,
1053 llvm::APFloat::rmNearestTiesToEven);
1054 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001055 }
Zonr Chang932648d2010-10-13 22:23:56 +08001056 return;
1057 }
1058 case llvm::Instruction::SIToFP: {
1059 GetConstantValue(Op0, Result);
1060 if (CE->getType()->isFloatTy())
1061 Result.FloatVal =
1062 static_cast<float>(Result.IntVal.signedRoundToDouble());
1063 else if (CE->getType()->isDoubleTy())
1064 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1065 else if (CE->getType()->isX86_FP80Ty()) {
1066 const uint64_t zero[] = { 0, 0 };
1067 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1068 apf.convertFromAPInt(Result.IntVal,
1069 true,
1070 llvm::APFloat::rmNearestTiesToEven);
1071 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001072 }
Zonr Chang932648d2010-10-13 22:23:56 +08001073 return;
1074 }
1075 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001076 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001077 case llvm::Instruction::FPToSI: {
1078 uint32_t BitWidth =
1079 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001080
Zonr Chang932648d2010-10-13 22:23:56 +08001081 GetConstantValue(Op0, Result);
1082 if (Op0->getType()->isFloatTy())
1083 Result.IntVal =
1084 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1085 else if (Op0->getType()->isDoubleTy())
1086 Result.IntVal =
1087 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1088 BitWidth);
1089 else if (Op0->getType()->isX86_FP80Ty()) {
1090 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1091 uint64_t V;
1092 bool Ignored;
1093 apf.convertToInteger(&V,
1094 BitWidth,
1095 CE->getOpcode() == llvm::Instruction::FPToSI,
1096 llvm::APFloat::rmTowardZero,
1097 &Ignored);
1098 Result.IntVal = V; // endian?
1099 }
1100 return;
1101 }
1102 case llvm::Instruction::PtrToInt: {
1103 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1104
1105 GetConstantValue(Op0, Result);
1106 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1107 (Result.PointerVal));
1108
1109 return;
1110 }
1111 case llvm::Instruction::IntToPtr: {
1112 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1113
1114 GetConstantValue(Op0, Result);
1115 if (PtrWidth != Result.IntVal.getBitWidth())
1116 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1117 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1118
1119 Result.PointerVal =
1120 llvm::PointerTy(
1121 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1122
1123 return;
1124 }
1125 case llvm::Instruction::BitCast: {
1126 GetConstantValue(Op0, Result);
1127 const llvm::Type *DestTy = CE->getType();
1128
1129 switch (Op0->getType()->getTypeID()) {
1130 case llvm::Type::IntegerTyID: {
1131 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1132 if (DestTy->isFloatTy())
1133 Result.FloatVal = Result.IntVal.bitsToFloat();
1134 else if (DestTy->isDoubleTy())
1135 Result.DoubleVal = Result.IntVal.bitsToDouble();
1136 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001137 }
Zonr Chang932648d2010-10-13 22:23:56 +08001138 case llvm::Type::FloatTyID: {
1139 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1140 Result.IntVal.floatToBits(Result.FloatVal);
1141 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001142 }
Zonr Chang932648d2010-10-13 22:23:56 +08001143 case llvm::Type::DoubleTyID: {
1144 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1145 Result.IntVal.doubleToBits(Result.DoubleVal);
1146 break;
1147 }
1148 case llvm::Type::PointerTyID: {
1149 assert(DestTy->isPointerTy() && "Invalid bitcast");
1150 break; // getConstantValue(Op0) above already converted it
1151 }
1152 default: {
1153 llvm_unreachable("Invalid bitcast operand");
1154 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001155 }
Zonr Chang932648d2010-10-13 22:23:56 +08001156 return;
1157 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001158 case llvm::Instruction::Add:
1159 case llvm::Instruction::FAdd:
1160 case llvm::Instruction::Sub:
1161 case llvm::Instruction::FSub:
1162 case llvm::Instruction::Mul:
1163 case llvm::Instruction::FMul:
1164 case llvm::Instruction::UDiv:
1165 case llvm::Instruction::SDiv:
1166 case llvm::Instruction::URem:
1167 case llvm::Instruction::SRem:
1168 case llvm::Instruction::And:
1169 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001170 case llvm::Instruction::Xor: {
1171 llvm::GenericValue LHS, RHS;
1172 GetConstantValue(Op0, LHS);
1173 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001174
Zonr Chang932648d2010-10-13 22:23:56 +08001175 switch (Op0->getType()->getTypeID()) {
1176 case llvm::Type::IntegerTyID: {
1177 switch (CE->getOpcode()) {
1178 case llvm::Instruction::Add: {
1179 Result.IntVal = LHS.IntVal + RHS.IntVal;
1180 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001181 }
Zonr Chang932648d2010-10-13 22:23:56 +08001182 case llvm::Instruction::Sub: {
1183 Result.IntVal = LHS.IntVal - RHS.IntVal;
1184 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001185 }
Zonr Chang932648d2010-10-13 22:23:56 +08001186 case llvm::Instruction::Mul: {
1187 Result.IntVal = LHS.IntVal * RHS.IntVal;
1188 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001189 }
Zonr Chang932648d2010-10-13 22:23:56 +08001190 case llvm::Instruction::UDiv: {
1191 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1192 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001193 }
Zonr Chang932648d2010-10-13 22:23:56 +08001194 case llvm::Instruction::SDiv: {
1195 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1196 break;
1197 }
1198 case llvm::Instruction::URem: {
1199 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1200 break;
1201 }
1202 case llvm::Instruction::SRem: {
1203 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1204 break;
1205 }
1206 case llvm::Instruction::And: {
1207 Result.IntVal = LHS.IntVal & RHS.IntVal;
1208 break;
1209 }
1210 case llvm::Instruction::Or: {
1211 Result.IntVal = LHS.IntVal | RHS.IntVal;
1212 break;
1213 }
1214 case llvm::Instruction::Xor: {
1215 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1216 break;
1217 }
1218 default: {
1219 llvm_unreachable("Invalid integer opcode");
1220 }
1221 }
1222 break;
1223 }
1224 case llvm::Type::FloatTyID: {
1225 switch (CE->getOpcode()) {
1226 case llvm::Instruction::FAdd: {
1227 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1228 break;
1229 }
1230 case llvm::Instruction::FSub: {
1231 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1232 break;
1233 }
1234 case llvm::Instruction::FMul: {
1235 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1236 break;
1237 }
1238 case llvm::Instruction::FDiv: {
1239 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1240 break;
1241 }
1242 case llvm::Instruction::FRem: {
1243 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1244 break;
1245 }
1246 default: {
1247 llvm_unreachable("Invalid float opcode");
1248 }
1249 }
1250 break;
1251 }
1252 case llvm::Type::DoubleTyID: {
1253 switch (CE->getOpcode()) {
1254 case llvm::Instruction::FAdd: {
1255 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1256 break;
1257 }
1258 case llvm::Instruction::FSub: {
1259 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1260 break;
1261 }
1262 case llvm::Instruction::FMul: {
1263 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1264 break;
1265 }
1266 case llvm::Instruction::FDiv: {
1267 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1268 break;
1269 }
1270 case llvm::Instruction::FRem: {
1271 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1272 break;
1273 }
1274 default: {
1275 llvm_unreachable("Invalid double opcode");
1276 }
1277 }
1278 break;
1279 }
1280 case llvm::Type::X86_FP80TyID:
1281 case llvm::Type::PPC_FP128TyID:
1282 case llvm::Type::FP128TyID: {
1283 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1284 switch (CE->getOpcode()) {
1285 case llvm::Instruction::FAdd: {
1286 apfLHS.add(llvm::APFloat(RHS.IntVal),
1287 llvm::APFloat::rmNearestTiesToEven);
1288 break;
1289 }
1290 case llvm::Instruction::FSub: {
1291 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1292 llvm::APFloat::rmNearestTiesToEven);
1293 break;
1294 }
1295 case llvm::Instruction::FMul: {
1296 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1297 llvm::APFloat::rmNearestTiesToEven);
1298 break;
1299 }
1300 case llvm::Instruction::FDiv: {
1301 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1302 llvm::APFloat::rmNearestTiesToEven);
1303 break;
1304 }
1305 case llvm::Instruction::FRem: {
1306 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1307 llvm::APFloat::rmNearestTiesToEven);
1308 break;
1309 }
1310 default: {
1311 llvm_unreachable("Invalid long double opcode");
1312 }
1313 }
1314 Result.IntVal = apfLHS.bitcastToAPInt();
1315 break;
1316 }
1317 default: {
1318 llvm_unreachable("Bad add type!");
1319 }
1320 } // End switch (Op0->getType()->getTypeID())
1321 return;
1322 }
1323 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001324 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001325 }
1326 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001327
1328 std::string msg;
1329 llvm::raw_string_ostream Msg(msg);
1330 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001331 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001332 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001333
1334 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001335 case llvm::Type::FloatTyID: {
1336 Result.FloatVal =
1337 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001338 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001339 }
1340 case llvm::Type::DoubleTyID: {
1341 Result.DoubleVal =
1342 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001343 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001344 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001345 case llvm::Type::X86_FP80TyID:
1346 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001347 case llvm::Type::PPC_FP128TyID: {
1348 Result.IntVal =
1349 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001350 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001351 }
1352 case llvm::Type::IntegerTyID: {
1353 Result.IntVal =
1354 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001355 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001356 }
1357 case llvm::Type::PointerTyID: {
1358 switch (C->getValueID()) {
1359 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001360 Result.PointerVal = NULL;
1361 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001362 }
1363 case llvm::Value::FunctionVal: {
1364 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1365 Result.PointerVal =
1366 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001367 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001368 }
1369 case llvm::Value::GlobalVariableVal: {
1370 const llvm::GlobalVariable *GV =
1371 static_cast<const llvm::GlobalVariable*>(C);
1372 Result.PointerVal =
1373 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001374 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001375 }
1376 case llvm::Value::BlockAddressVal: {
1377 assert(false && "JIT does not support address-of-label yet!");
1378 }
1379 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001380 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001381 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001382 }
1383 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001384 }
1385 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001386 std::string msg;
1387 llvm::raw_string_ostream Msg(msg);
1388 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001389 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001390 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001391 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001392 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001393 return;
1394 }
1395
Zonr Chang932648d2010-10-13 22:23:56 +08001396 // Stores the data in @Val of type @Ty at address @Addr.
1397 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001398 const llvm::Type *Ty) {
1399 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1400
Zonr Chang932648d2010-10-13 22:23:56 +08001401 switch (Ty->getTypeID()) {
1402 case llvm::Type::IntegerTyID: {
1403 const llvm::APInt &IntVal = Val.IntVal;
1404 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1405 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001406
Zonr Chang932648d2010-10-13 22:23:56 +08001407 const uint8_t *Src =
1408 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001409
Zonr Chang932648d2010-10-13 22:23:56 +08001410 if (llvm::sys::isLittleEndianHost()) {
1411 // Little-endian host - the source is ordered from LSB to MSB.
1412 // Order the destination from LSB to MSB: Do a straight copy.
1413 memcpy(Addr, Src, StoreBytes);
1414 } else {
1415 // Big-endian host - the source is an array of 64 bit words
1416 // ordered from LSW to MSW.
1417 //
1418 // Each word is ordered from MSB to LSB.
1419 //
1420 // Order the destination from MSB to LSB:
1421 // Reverse the word order, but not the bytes in a word.
1422 unsigned int i = StoreBytes;
1423 while (i > sizeof(uint64_t)) {
1424 i -= sizeof(uint64_t);
1425 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1426 Src,
1427 sizeof(uint64_t));
1428 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001429 }
Zonr Chang932648d2010-10-13 22:23:56 +08001430 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001431 }
1432 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001433 }
1434 case llvm::Type::FloatTyID: {
1435 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001436 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001437 }
1438 case llvm::Type::DoubleTyID: {
1439 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001440 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001441 }
1442 case llvm::Type::X86_FP80TyID: {
1443 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001444 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001445 }
1446 case llvm::Type::PointerTyID: {
1447 // Ensure 64 bit target pointers are fully initialized on 32 bit
1448 // hosts.
1449 if (StoreBytes != sizeof(llvm::PointerTy))
1450 memset(Addr, 0, StoreBytes);
1451 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001452 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001453 }
1454 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001455 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001456 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001457 }
1458
Zonr Chang932648d2010-10-13 22:23:56 +08001459 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1460 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1461 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001462
1463 return;
1464 }
1465
Zonr Chang932648d2010-10-13 22:23:56 +08001466 // Recursive function to apply a @Constant value into the specified memory
1467 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001468 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001469 switch (C->getValueID()) {
1470 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001471 // Nothing to do
1472 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001473 }
1474 case llvm::Value::ConstantVectorVal: {
1475 // dynamic cast may hurt performance
1476 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001477
Zonr Chang932648d2010-10-13 22:23:56 +08001478 unsigned int ElementSize = mpTD->getTypeAllocSize
1479 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001480
Zonr Chang932648d2010-10-13 22:23:56 +08001481 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1482 InitializeConstantToMemory(
1483 CP->getOperand(i),
1484 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001485 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001486 }
1487 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001488 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1489 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001490 }
1491 case llvm::Value::ConstantArrayVal: {
1492 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1493 unsigned int ElementSize = mpTD->getTypeAllocSize
1494 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001495
Zonr Chang932648d2010-10-13 22:23:56 +08001496 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1497 InitializeConstantToMemory(
1498 CPA->getOperand(i),
1499 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1500 break;
1501 }
1502 case llvm::Value::ConstantStructVal: {
1503 const llvm::ConstantStruct *CPS =
1504 static_cast<const llvm::ConstantStruct*>(C);
1505 const llvm::StructLayout *SL = mpTD->getStructLayout
1506 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001507
Zonr Chang932648d2010-10-13 22:23:56 +08001508 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1509 InitializeConstantToMemory(
1510 CPS->getOperand(i),
1511 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1512 break;
1513 }
1514 default: {
1515 if (C->getType()->isFirstClassType()) {
1516 llvm::GenericValue Val;
1517 GetConstantValue(C, Val);
1518 StoreValueToMemory(Val, Addr, C->getType());
1519 } else {
1520 llvm_unreachable("Unknown constant type to initialize memory "
1521 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001522 }
1523 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001524 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001525 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001526 return;
1527 }
1528
1529 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001530 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001531 return;
1532
Zonr Chang932648d2010-10-13 22:23:56 +08001533 // Constant pool address resolution is handled by the target itself in ARM
1534 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001535#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001536 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1537 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001538
Zonr Chang932648d2010-10-13 22:23:56 +08001539 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001540 return;
1541
1542 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1543 unsigned Align = MCP->getConstantPoolAlignment();
1544
1545 mpConstantPoolBase = allocateSpace(Size, Align);
1546 mpConstantPool = MCP;
1547
Zonr Chang932648d2010-10-13 22:23:56 +08001548 if (mpConstantPoolBase == NULL)
1549 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001550
1551 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001552 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001553 llvm::MachineConstantPoolEntry CPE = Constants[i];
1554 unsigned AlignMask = CPE.getAlignment() - 1;
1555 Offset = (Offset + AlignMask) & ~AlignMask;
1556
1557 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1558 mConstPoolAddresses.push_back(CAddr);
1559
Zonr Chang932648d2010-10-13 22:23:56 +08001560 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001561 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001562 ("Initialize memory with machine specific constant pool"
1563 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001564
1565 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1566
1567 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1568 Offset += mpTD->getTypeAllocSize(Ty);
1569 }
1570#endif
1571 return;
1572 }
1573
1574 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001575 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001576 return;
1577
Zonr Chang932648d2010-10-13 22:23:56 +08001578 const std::vector<llvm::MachineJumpTableEntry> &JT =
1579 MJTI->getJumpTables();
1580 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001581 return;
1582
1583 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001584 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001585 NumEntries += JT[i].MBBs.size();
1586
1587 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1588
Zonr Chang932648d2010-10-13 22:23:56 +08001589 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001590 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001591 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001592
1593 return;
1594 }
1595
1596 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001597 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001598 return;
1599
Zonr Chang932648d2010-10-13 22:23:56 +08001600 const std::vector<llvm::MachineJumpTableEntry> &JT =
1601 MJTI->getJumpTables();
1602 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001603 return;
1604
Zonr Chang932648d2010-10-13 22:23:56 +08001605 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1606 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1607 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001608
Zonr Chang932648d2010-10-13 22:23:56 +08001609 // For each jump table, map each target in the jump table to the
1610 // address of an emitted MachineBasicBlock.
1611 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1612 for (int i = 0, ie = JT.size(); i != ie; i++) {
1613 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1614 // Store the address of the basic block for this jump table slot in the
1615 // memory we allocated for the jump table in 'initJumpTableInfo'
1616 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001617 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1618 }
1619 }
1620
Zonr Chang932648d2010-10-13 22:23:56 +08001621 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1622 bool MayNeedFarStub) {
1623 switch (V->getValueID()) {
1624 case llvm::Value::FunctionVal: {
1625 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001626
Zonr Chang932648d2010-10-13 22:23:56 +08001627 // If we have code, go ahead and return that.
1628 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1629 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001630
Zonr Chang932648d2010-10-13 22:23:56 +08001631 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1632 // Return the function stub if it's already created.
1633 // We do this first so that:
1634 // we're returning the same address for the function as any
1635 // previous call.
1636 //
1637 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1638 // guaranteed to be close enough to call.
1639 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001640
Zonr Chang932648d2010-10-13 22:23:56 +08001641 // If we know the target can handle arbitrary-distance calls, try to
1642 // return a direct pointer.
1643 if (!MayNeedFarStub) {
1644 //
1645 // x86_64 architecture may encounter the bug:
1646 // http://llvm.org/bugs/show_bug.cgi?id=5201
1647 // which generate instruction "call" instead of "callq".
1648 //
1649 // And once the real address of stub is greater than 64-bit
1650 // long, the replacement will truncate to 32-bit resulting a
1651 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001652#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001653 // If this is an external function pointer, we can force the JIT
1654 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001655 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1656 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1657 // Changing to false because wanting to allow later calls to
1658 // mpTJI->relocate() without aborting. For caching purpose
1659 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001660#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001661 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001662
Zonr Chang932648d2010-10-13 22:23:56 +08001663 // Otherwise, we may need a to emit a stub, and, conservatively, we
1664 // always do so.
1665 return GetLazyFunctionStub(F);
1666 break;
1667 }
1668 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001669 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1670 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001671 }
1672 case llvm::Value::GlobalAliasVal: {
1673 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1674 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001675
Zonr Chang932648d2010-10-13 22:23:56 +08001676 switch (GV->getValueID()) {
1677 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001678 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001679 // code-gen'd?
1680 return GetPointerToFunction(
1681 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001682 /* AbortOnFailure = */false);
1683 // Changing to false because wanting to allow later calls to
1684 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001685 break;
1686 }
1687 case llvm::Value::GlobalVariableVal: {
1688 if (void *P = mGlobalAddressMap[GV])
1689 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001690
Zonr Chang932648d2010-10-13 22:23:56 +08001691 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1692 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001693
Zonr Chang932648d2010-10-13 22:23:56 +08001694 return mGlobalAddressMap[GV];
1695 break;
1696 }
1697 case llvm::Value::GlobalAliasVal: {
1698 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001699 }
1700 }
1701 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001702 }
1703 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001704 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001705 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001706 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001707 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001708 }
1709
Zonr Chang932648d2010-10-13 22:23:56 +08001710 // If the specified function has been code-gen'd, return a pointer to the
1711 // function. If not, compile it, or use a stub to implement lazy compilation
1712 // if available.
1713 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1714 // If we have already code generated the function, just return the
1715 // address.
1716 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001717 return Addr;
1718
Zonr Chang932648d2010-10-13 22:23:56 +08001719 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001720 return GetLazyFunctionStub(F);
1721 }
1722
Zonr Chang932648d2010-10-13 22:23:56 +08001723 typedef llvm::DenseMap<const llvm::Function*,
1724 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001725 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1726
Zonr Chang932648d2010-10-13 22:23:56 +08001727 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001728 return mFunctionToLazyStubMap.lookup(F);
1729 }
1730
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001731 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001732 void *GetLazyFunctionStub(llvm::Function *F) {
1733 // If we already have a lazy stub for this function, recycle it.
1734 void *&Stub = mFunctionToLazyStubMap[F];
1735 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001736 return Stub;
1737
Zonr Chang932648d2010-10-13 22:23:56 +08001738 // In any cases, we should NOT resolve function at runtime (though we are
1739 // able to). We resolve this right now.
1740 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001741 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1742 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1743 // Changing to false because wanting to allow later calls to
1744 // mpTJI->relocate() without aborting. For caching purpose
1745 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001746
Zonr Chang932648d2010-10-13 22:23:56 +08001747 // Codegen a new stub, calling the actual address of the external
1748 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001749 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1750 startGVStub(F, SL.Size, SL.Alignment);
1751 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1752 finishGVStub();
1753
Zonr Chang932648d2010-10-13 22:23:56 +08001754 // We really want the address of the stub in the GlobalAddressMap for the
1755 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001756 UpdateGlobalMapping(F, Stub);
1757
Zonr Chang932648d2010-10-13 22:23:56 +08001758 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001759 PendingFunctions.insert(F);
1760 else
Zonr Chang932648d2010-10-13 22:23:56 +08001761 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1762 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001763
1764 return Stub;
1765 }
1766
Zonr Chang932648d2010-10-13 22:23:56 +08001767 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1768 void *Addr = GetPointerToGlobalIfAvailable(F);
1769 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001770 return Addr;
1771
1772 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1773 "Internal error: only external defined function routes here!");
1774
Zonr Chang932648d2010-10-13 22:23:56 +08001775 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001776 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001777 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001778
Zonr Chang932648d2010-10-13 22:23:56 +08001779 // If we resolved the symbol to a null address (eg. a weak external)
1780 // return a null pointer let the application handle it.
1781 if (Addr == NULL) {
1782 if (AbortOnFailure)
1783 llvm::report_fatal_error("Could not resolve external function "
1784 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001785 else
1786 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001787 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001788
1789 AddGlobalMapping(F, Addr);
1790
1791 return Addr;
1792 }
1793
Zonr Chang932648d2010-10-13 22:23:56 +08001794 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001795 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001796 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001797 return Addr;
1798
Zonr Chang932648d2010-10-13 22:23:56 +08001799 if (mpSymbolLookupFn)
1800 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001801 return Addr;
1802
Zonr Chang932648d2010-10-13 22:23:56 +08001803 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001804 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001805 "' which could not be resolved!");
1806
1807 return NULL;
1808 }
1809
Zonr Chang932648d2010-10-13 22:23:56 +08001810 // Return the address of the specified global variable, possibly emitting it
1811 // to memory if needed. This is used by the Emitter.
1812 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1813 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1814 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001815 return Ptr;
1816
Zonr Chang932648d2010-10-13 22:23:56 +08001817 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1818 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001819 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1820 AddGlobalMapping(GV, Ptr);
1821 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001822 // If the global hasn't been emitted to memory yet, allocate space and
1823 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001824 Ptr = GetMemoryForGV(GV);
1825 AddGlobalMapping(GV, Ptr);
1826 EmitGlobalVariable(GV);
1827 }
1828
1829 return Ptr;
1830 }
1831
Zonr Chang932648d2010-10-13 22:23:56 +08001832 // This method abstracts memory allocation of global variable so that the
1833 // JIT can allocate thread local variables depending on the target.
1834 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1835 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001836
Zonr Chang932648d2010-10-13 22:23:56 +08001837 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001838 size_t S = mpTD->getTypeAllocSize(GlobalType);
1839 size_t A = mpTD->getPreferredAlignment(GV);
1840
Zonr Chang932648d2010-10-13 22:23:56 +08001841 if (GV->isThreadLocal()) {
1842 // We can support TLS by
1843 //
1844 // Ptr = TJI.allocateThreadLocalMemory(S);
1845 //
1846 // But I tend not to.
1847 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001848 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001849 ("Compilation of Thread Local Storage (TLS) is disabled!");
1850
Zonr Chang932648d2010-10-13 22:23:56 +08001851 } else if (mpTJI->allocateSeparateGVMemory()) {
1852 if (A <= 8) {
1853 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001854 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001855 // Allocate (S + A) bytes of memory, then use an aligned pointer
1856 // within that space.
1857 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001858 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001859 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1860 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001861 }
1862 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001863 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001864 }
1865
1866 return Ptr;
1867 }
1868
1869 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001870 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001871
Zonr Chang932648d2010-10-13 22:23:56 +08001872 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001873 llvm::report_fatal_error
1874 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001875
Zonr Chang932648d2010-10-13 22:23:56 +08001876 if (GA == NULL) {
1877 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001878 GA = GetMemoryForGV(GV);
1879 AddGlobalMapping(GV, GA);
1880 }
1881
1882 InitializeConstantToMemory(GV->getInitializer(), GA);
1883
Zonr Chang932648d2010-10-13 22:23:56 +08001884 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001885 return;
1886 }
1887
1888 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1889 > GlobalToIndirectSymMapTy;
1890 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1891
Zonr Chang932648d2010-10-13 22:23:56 +08001892 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1893 // Make sure GV is emitted first, and create a stub containing the fully
1894 // resolved address.
1895 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001896
Zonr Chang932648d2010-10-13 22:23:56 +08001897 // If we already have a stub for this global variable, recycle it.
1898 void *&IndirectSym = GlobalToIndirectSymMap[V];
1899 // Otherwise, codegen a new indirect symbol.
1900 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001901 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1902
1903 return IndirectSym;
1904 }
1905
Zonr Chang932648d2010-10-13 22:23:56 +08001906 // This is the equivalent of FunctionToLazyStubMap for external functions.
1907 //
1908 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1909 // It's actually here to make it more likely that far calls
1910 // succeed, but no single stub can guarantee that. I'll
1911 // remove this in a subsequent checkin when I actually fix
1912 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001913 std::map<void*, void*> ExternalFnToStubMap;
1914
Zonr Chang932648d2010-10-13 22:23:56 +08001915 // Return a stub for the function at the specified address.
1916 void *GetExternalFunctionStub(void *FnAddr) {
1917 void *&Stub = ExternalFnToStubMap[FnAddr];
1918 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001919 return Stub;
1920
1921 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1922 startGVStub(0, SL.Size, SL.Alignment);
1923 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1924 finishGVStub();
1925
1926 return Stub;
1927 }
1928
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001929#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001930 const llvm::MCAsmInfo *mpAsmInfo;
1931 const llvm::MCDisassembler *mpDisassmbler;
1932 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001933
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001934 class BufferMemoryObject : public llvm::MemoryObject {
1935 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001936 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001937 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001938
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001939 public:
1940 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1941 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001942
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001943 uint64_t getBase() const { return 0; }
1944 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001945
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001946 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001947 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001948 return -1;
1949 *Byte = mBytes[Addr];
1950 return 0;
1951 }
1952 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001953
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08001954 public:
Zonr Chang932648d2010-10-13 22:23:56 +08001955 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001956 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001957 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001958#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001959 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001960 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1961 ErrorInfo,
1962 llvm::raw_fd_ostream::F_Append);
1963 if (!ErrorInfo.empty()) { // some errors occurred
1964 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001965 delete OS;
1966 return;
1967 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001968#else
1969 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001970#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001971 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1972 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001973
Zonr Chang932648d2010-10-13 22:23:56 +08001974 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001975 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001976 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001977 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001978 if (mpIP == NULL)
1979 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1980 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001981
Zonr Chang932648d2010-10-13 22:23:56 +08001982 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1983 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001984 uint64_t Size;
1985 uint64_t Index;
1986
Zonr Chang932648d2010-10-13 22:23:56 +08001987 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001988 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001989
Zonr Chang932648d2010-10-13 22:23:56 +08001990 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1991 /* REMOVED */ llvm::nulls())) {
1992 (*OS).indent(4)
1993 .write("0x", 2)
1994 .write_hex((uint32_t) Start + Index)
1995 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001996 mpIP->printInst(&Inst, *OS);
1997 *OS << "\n";
1998 } else {
1999 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08002000 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002001 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002002 }
2003
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002004 *OS << "\n";
2005 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002006
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002007#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002008 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002009 OS->close();
2010 delete OS;
2011#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002012 return;
2013 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002014#else
Zonr Chang932648d2010-10-13 22:23:56 +08002015 inline void Disassemble(const std::string &Name, uint8_t *Start,
2016 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002017 return;
2018 }
Zonr Chang932648d2010-10-13 22:23:56 +08002019#endif // defined(USE_DISASSEMBLER)
2020
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002021 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002022 // Resolver to undefined symbol in CodeEmitter
2023 BCCSymbolLookupFn mpSymbolLookupFn;
2024 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002025
2026 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002027 // Will take the ownership of @MemMgr
2028 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2029 : mpMemMgr(pMemMgr),
2030 mpTarget(NULL),
2031 mpTJI(NULL),
2032 mpTD(NULL),
2033 mpCurEmitFunction(NULL),
2034 mpConstantPool(NULL),
2035 mpJumpTable(NULL),
2036 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002037#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002038 mpAsmInfo(NULL),
2039 mpDisassmbler(NULL),
2040 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002041#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002042 mpSymbolLookupFn(NULL),
2043 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002044 return;
2045 }
2046
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002047 inline global_addresses_const_iterator global_address_begin() const {
2048 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002049 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002050 inline global_addresses_const_iterator global_address_end() const {
2051 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002052 }
2053
Logan824dd0a2010-11-20 01:45:54 +08002054 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2055 return mCachingRelocations;
2056 }
2057
Zonr Chang932648d2010-10-13 22:23:56 +08002058 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002059 mpSymbolLookupFn = pFn;
2060 mpSymbolLookupContext = pContext;
2061 return;
2062 }
2063
Zonr Chang932648d2010-10-13 22:23:56 +08002064 void setTargetMachine(llvm::TargetMachine &TM) {
2065 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002066 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002067 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002068 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002069 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002070 mpTD = TM.getTargetData();
2071
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002072 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2073
2074 return;
2075 }
2076
Zonr Chang932648d2010-10-13 22:23:56 +08002077 // This callback is invoked when the specified function is about to be code
2078 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002079 void startFunction(llvm::MachineFunction &F) {
2080 uintptr_t ActualSize = 0;
2081
2082 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002083
2084 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2085 // MachineCodeEmitter, which is the super class of the class
2086 // JITCodeEmitter.
2087 //
2088 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2089 // allocated for this code buffer.
2090 //
2091 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2092 // code. This is guranteed to be in the range
2093 // [BufferBegin, BufferEnd]. If this pointer is at
2094 // BufferEnd, it will never move due to code emission, and
2095 // all code emission requests will be ignored (this is the
2096 // buffer overflow condition).
2097 BufferBegin = CurBufferPtr =
2098 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002099 BufferEnd = BufferBegin + ActualSize;
2100
Zonr Chang932648d2010-10-13 22:23:56 +08002101 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002102 mpCurEmitFunction = new EmittedFunctionCode();
2103 mpCurEmitFunction->FunctionBody = BufferBegin;
2104
Zonr Chang932648d2010-10-13 22:23:56 +08002105 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002106 emitAlignment(16);
2107
2108 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002109 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002110 initJumpTableInfo(MJTI);
2111
Zonr Chang932648d2010-10-13 22:23:56 +08002112 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002113 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2114
2115 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2116
2117 mpCurEmitFunction->Code = CurBufferPtr;
2118
2119 mMBBLocations.clear();
2120
2121 return;
2122 }
2123
Zonr Chang932648d2010-10-13 22:23:56 +08002124 // This callback is invoked when the specified function has finished code
2125 // generation. If a buffer overflow has occurred, this method returns true
2126 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002127 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002128 if (CurBufferPtr == BufferEnd) {
2129 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002130 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2131 return false;
2132 }
2133
Zonr Chang932648d2010-10-13 22:23:56 +08002134 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002135 emitJumpTableInfo(MJTI);
2136
Zonr Chang932648d2010-10-13 22:23:56 +08002137 // FnStart is the start of the text, not the start of the constant pool
2138 // and other per-function data.
2139 uint8_t *FnStart =
2140 reinterpret_cast<uint8_t*>(
2141 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002142
Zonr Chang932648d2010-10-13 22:23:56 +08002143 // FnEnd is the end of the function's machine code.
2144 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002145
Zonr Chang932648d2010-10-13 22:23:56 +08002146 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002147 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2148
Zonr Chang932648d2010-10-13 22:23:56 +08002149 // Resolve the relocations to concrete pointers.
2150 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2151 llvm::MachineRelocation &MR = mRelocations[i];
2152 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002153
Zonr Chang932648d2010-10-13 22:23:56 +08002154 if (!MR.letTargetResolve()) {
2155 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002156 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002157
2158 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002159 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002160 }
2161
Zonr Chang932648d2010-10-13 22:23:56 +08002162 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002163 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2164 BufferBegin
2165 + MR.getMachineCodeOffset(),
2166 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002167 } else if (MR.isIndirectSymbol()) {
2168 ResultPtr =
2169 GetPointerToGVIndirectSym(
2170 MR.getGlobalValue(),
2171 BufferBegin + MR.getMachineCodeOffset());
2172 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002173 ResultPtr =
2174 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002175 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002176 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002177 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002178 } else {
2179 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2180 ResultPtr =
2181 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2182 }
2183
Logan824dd0a2010-11-20 01:45:54 +08002184 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2185 // TODO(logan): Cache external symbol relocation entry.
2186 // Currently, we are not caching them. But since Android
2187 // system is using prelink, it is not a problem.
2188
2189 // Cache the relocation result address
2190 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002191 oBCCRelocEntry(MR.getRelocationType(),
2192 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002193 ResultPtr));
2194 }
2195
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002196 MR.setResultPointer(ResultPtr);
2197 }
2198 }
2199
2200 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2201 mpMemMgr->getGOTBase());
2202 }
2203
2204 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002205 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2206 // global variables that were referenced in the relocations.
2207 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002208 return false;
2209
Zonr Chang932648d2010-10-13 22:23:56 +08002210 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002211 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2212 BufferBegin = CurBufferPtr = 0;
2213
Zonr Chang932648d2010-10-13 22:23:56 +08002214 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002215 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2216 mpCurEmitFunction = NULL;
2217
2218 mRelocations.clear();
2219 mConstPoolAddresses.clear();
2220
Zonr Chang932648d2010-10-13 22:23:56 +08002221 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002222 mpMMI->EndFunction();
2223
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002224 updateFunctionStub(F.getFunction());
2225
Zonr Chang932648d2010-10-13 22:23:56 +08002226 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002227 mpMemMgr->setMemoryExecutable();
2228
2229 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2230
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002231 return false;
2232 }
2233
Zonr Chang932648d2010-10-13 22:23:56 +08002234 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002235 unsigned Alignment) {
2236 mpSavedBufferBegin = BufferBegin;
2237 mpSavedBufferEnd = BufferEnd;
2238 mpSavedCurBufferPtr = CurBufferPtr;
2239
2240 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2241 Alignment);
2242 BufferEnd = BufferBegin + StubSize + 1;
2243
2244 return;
2245 }
2246
Zonr Chang932648d2010-10-13 22:23:56 +08002247 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002248 mpSavedBufferBegin = BufferBegin;
2249 mpSavedBufferEnd = BufferEnd;
2250 mpSavedCurBufferPtr = CurBufferPtr;
2251
Zonr Chang932648d2010-10-13 22:23:56 +08002252 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002253 BufferEnd = BufferBegin + StubSize + 1;
2254
2255 return;
2256 }
2257
2258 void finishGVStub() {
2259 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2260
Zonr Chang932648d2010-10-13 22:23:56 +08002261 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002262 BufferBegin = mpSavedBufferBegin;
2263 BufferEnd = mpSavedBufferEnd;
2264 CurBufferPtr = mpSavedCurBufferPtr;
2265
2266 return;
2267 }
2268
Zonr Chang932648d2010-10-13 22:23:56 +08002269 // Allocates and fills storage for an indirect GlobalValue, and returns the
2270 // address.
2271 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002272 const uint8_t *Buffer, size_t Size,
2273 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002274 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002275 memcpy(IndGV, Buffer, Size);
2276 return IndGV;
2277 }
2278
Zonr Chang932648d2010-10-13 22:23:56 +08002279 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002280 void emitLabel(llvm::MCSymbol *Label) {
2281 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002282 return;
2283 }
2284
Zonr Chang932648d2010-10-13 22:23:56 +08002285 // Allocate memory for a global. Unlike allocateSpace, this method does not
2286 // allocate memory in the current output buffer, because a global may live
2287 // longer than the current function.
2288 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2289 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002290 return mpMemMgr->allocateGlobal(Size, Alignment);
2291 }
2292
Zonr Chang932648d2010-10-13 22:23:56 +08002293 // This should be called by the target when a new basic block is about to be
2294 // emitted. This way the MCE knows where the start of the block is, and can
2295 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002296 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002297 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002298 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2299 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2300 return;
2301 }
2302
Zonr Chang932648d2010-10-13 22:23:56 +08002303 // Whenever a relocatable address is needed, it should be noted with this
2304 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002305 void addRelocation(const llvm::MachineRelocation &MR) {
2306 mRelocations.push_back(MR);
2307 return;
2308 }
2309
Zonr Chang932648d2010-10-13 22:23:56 +08002310 // Return the address of the @Index entry in the constant pool that was
2311 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002312 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2313 assert(Index < mpConstantPool->getConstants().size() &&
2314 "Invalid constant pool index!");
2315 return mConstPoolAddresses[Index];
2316 }
2317
Zonr Chang932648d2010-10-13 22:23:56 +08002318 // Return the address of the jump table with index @Index in the function
2319 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002320 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002321 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002322 mpJumpTable->getJumpTables();
2323
Zonr Chang932648d2010-10-13 22:23:56 +08002324 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002325
2326 unsigned int Offset = 0;
2327 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2328
Zonr Chang932648d2010-10-13 22:23:56 +08002329 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002330 Offset += JT[i].MBBs.size();
2331 Offset *= EntrySize;
2332
Zonr Chang932648d2010-10-13 22:23:56 +08002333 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002334 }
2335
Zonr Chang932648d2010-10-13 22:23:56 +08002336 // Return the address of the specified MachineBasicBlock, only usable after
2337 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002338 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2339 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002340 mMBBLocations[MBB->getNumber()] &&
2341 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002342 return mMBBLocations[MBB->getNumber()];
2343 }
2344
Zonr Chang932648d2010-10-13 22:23:56 +08002345 // Return the address of the specified LabelID, only usable after the
2346 // LabelID has been emitted.
2347 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002348 assert(mLabelLocations.count(Label) && "Label not emitted!");
2349 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002350 }
2351
Zonr Chang932648d2010-10-13 22:23:56 +08002352 // Specifies the MachineModuleInfo object. This is used for exception
2353 // handling purposes.
2354 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002355 mpMMI = Info;
2356 return;
2357 }
2358
Zonr Chang932648d2010-10-13 22:23:56 +08002359 void updateFunctionStub(const llvm::Function *F) {
2360 // Get the empty stub we generated earlier.
2361 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002362 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002363 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002364 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002365 else
2366 return;
2367
Zonr Chang932648d2010-10-13 22:23:56 +08002368 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002369
2370 assert(Addr != Stub &&
2371 "Function must have non-stub address to be updated.");
2372
Zonr Chang932648d2010-10-13 22:23:56 +08002373 // Tell the target jit info to rewrite the stub at the specified address,
2374 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002375 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2376 startGVStub(Stub, SL.Size);
2377 mpTJI->emitFunctionStub(F, Addr, *this);
2378 finishGVStub();
2379
Zonr Chang932648d2010-10-13 22:23:56 +08002380 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2381 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002382
2383 PendingFunctions.erase(I);
2384
2385 return;
2386 }
2387
Zonr Chang932648d2010-10-13 22:23:56 +08002388 // Once you finish the compilation on a translation unit, you can call this
2389 // function to recycle the memory (which is used at compilation time and not
2390 // needed for runtime).
2391 //
2392 // NOTE: You should not call this funtion until the code-gen passes for a
2393 // given module is done. Otherwise, the results is undefined and may
2394 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002395 void releaseUnnecessary() {
2396 mMBBLocations.clear();
2397 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002398 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002399 mFunctionToLazyStubMap.clear();
2400 GlobalToIndirectSymMap.clear();
2401 ExternalFnToStubMap.clear();
2402 PendingFunctions.clear();
2403
2404 return;
2405 }
2406
2407 void reset() {
2408 releaseUnnecessary();
2409
2410 mpSymbolLookupFn = NULL;
2411 mpSymbolLookupContext = NULL;
2412
2413 mpTJI = NULL;
2414 mpTD = NULL;
2415
Zonr Chang932648d2010-10-13 22:23:56 +08002416 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2417 E = mEmittedFunctions.end();
2418 I != E;
2419 I++)
2420 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002421 delete I->second;
2422 mEmittedFunctions.clear();
2423
2424 mpMemMgr->reset();
2425
2426 return;
2427 }
2428
Zonr Chang932648d2010-10-13 22:23:56 +08002429 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002430 return lookup( llvm::StringRef(Name) );
2431 }
2432
Zonr Chang932648d2010-10-13 22:23:56 +08002433 void *lookup(const llvm::StringRef &Name) {
2434 EmittedFunctionsMapTy::const_iterator I =
2435 mEmittedFunctions.find(Name.str());
2436 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002437 return NULL;
2438 else
2439 return I->second->Code;
2440 }
2441
Zonr Chang932648d2010-10-13 22:23:56 +08002442 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002443 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002444 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002445 int functionCount = mEmittedFunctions.size();
2446
Zonr Chang932648d2010-10-13 22:23:56 +08002447 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002448 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002449 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002450 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002451 if (functions)
2452 for (EmittedFunctionsMapTy::const_iterator
2453 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2454 (I != E) && (functionCount > 0);
2455 I++, functionCount--)
2456 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002457
2458 return;
2459 }
2460
Zonr Chang932648d2010-10-13 22:23:56 +08002461 void getFunctionBinary(BCCchar *label,
2462 BCCvoid **base,
2463 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002464 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002465 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002466 *base = NULL;
2467 *length = 0;
2468 } else {
2469 *base = I->second->Code;
2470 *length = I->second->Size;
2471 }
2472 return;
2473 }
2474
2475 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002476 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002477#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002478 delete mpAsmInfo;
2479 delete mpDisassmbler;
2480 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002481#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002482 return;
2483 }
Zonr Chang932648d2010-10-13 22:23:56 +08002484 };
2485 // End of Class CodeEmitter
2486 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002487
Zonr Chang932648d2010-10-13 22:23:56 +08002488 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002489 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002490 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002491 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2492 return mCodeEmitter.get();
2493 }
2494
2495 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002496 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002497
Zonr Chang932648d2010-10-13 22:23:56 +08002498 llvm::LLVMContext *mContext;
2499 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002500
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002501 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002502
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002503 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002504 Compiler()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002505 : mNeverCache(true),
2506 mCacheNew(false),
2507 mCacheFd(-1),
2508 mCacheMapAddr(NULL),
2509 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002510 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002511 mCacheDiff(0),
2512 mCodeDataAddr(NULL),
2513 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002514 mpSymbolLookupContext(NULL),
2515 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002516 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002517 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002518 llvm::remove_fatal_error_handler();
2519 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002520 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002521 return;
2522 }
2523
Zonr Chang932648d2010-10-13 22:23:56 +08002524 // interface for BCCscript::registerSymbolCallback()
2525 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002526 mpSymbolLookupFn = pFn;
2527 mpSymbolLookupContext = pContext;
2528 return;
2529 }
2530
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002531 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002532 GlobalInitialization();
2533 mModule = module;
2534 return hasError();
2535 }
2536
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002537 int readBC(const char *bitcode,
2538 size_t bitcodeSize,
2539 const BCCchar *resName) {
2540 GlobalInitialization();
2541
2542 if (resName) {
2543 // Turn off the default NeverCaching mode
2544 mNeverCache = false;
2545
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002546 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2547 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2548 return -mCacheFd;
2549 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002550 }
2551
2552 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002553
Zonr Chang932648d2010-10-13 22:23:56 +08002554 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002555 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002556
Zonr Chang932648d2010-10-13 22:23:56 +08002557 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002558 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002559 llvm::StringRef(bitcode, bitcodeSize)));
2560
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002561 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002562 setError("Error reading input program bitcode into memory");
2563 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002564 }
2565
Zonr Chang932648d2010-10-13 22:23:56 +08002566 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002567 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2568 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002569 return hasError();
2570 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002571
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002572 int linkBC(const char *bitcode, size_t bitcodeSize) {
2573 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002574
2575 if (bitcode == NULL || bitcodeSize <= 0)
2576 return 0;
2577
2578 if (mModule == NULL) {
2579 setError("No module presents for linking");
2580 return hasError();
2581 }
2582
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002583 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002584 llvm::StringRef(bitcode, bitcodeSize)));
2585
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002586 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002587 setError("Error reading input library bitcode into memory");
2588 return hasError();
2589 }
2590
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002591 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002592 *mContext,
2593 &mError));
2594 if (Lib.get() == NULL)
2595 return hasError();
2596
2597 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2598 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002599
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002600 // Everything for linking should be settled down here with no error occurs
2601 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002602 return hasError();
2603 }
2604
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002605
2606 // interface for bccLoadBinary()
2607 int loader() {
2608 // Check File Descriptor
2609 if (mCacheFd < 0) {
2610 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2611 goto giveup;
2612 }
2613
2614
2615 // Check File Size
2616 struct stat statCacheFd;
2617 if (fstat(mCacheFd, &statCacheFd) < 0) {
2618 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2619 goto giveup;
2620 }
2621
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002622 mCacheSize = statCacheFd.st_size;
2623
2624 if (mCacheSize < sizeof(oBCCHeader) ||
2625 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002626 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2627 goto giveup;
2628 }
2629
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002630 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
2631 LOGE("Unable to seek to 0: %s\n", strerror(errno));
2632 goto giveup;
2633 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002634
2635 // Read File Content
2636 {
2637#ifdef BCC_CODE_ADDR
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002638 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002639
2640 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2641 MaxCodeSize + MaxGlobalVarSize,
2642 PROT_READ | PROT_EXEC | PROT_WRITE,
2643 MAP_PRIVATE | MAP_FIXED,
2644 mCacheFd, heuristicCodeOffset);
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002645 LOGE("sliao@Loader: mCacheSize=%x, heuristicCodeOffset=%x", mCacheSize, heuristicCodeOffset);
2646 LOGE("sliao@Loader: mCodeDataAddr=%x", mCodeDataAddr);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002647
2648 if (mCodeDataAddr == MAP_FAILED) {
2649 LOGE("unable to mmap .oBBC cache code/data: %s\n", strerror(errno));
2650 flock(mCacheFd, LOCK_UN);
2651 goto giveup;
2652 }
2653
2654 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
2655
2656 if (!mCacheMapAddr) {
2657 flock(mCacheFd, LOCK_UN);
2658 LOGE("allocation failed.\n");
2659 // TODO(all)
2660 goto bail;
2661 }
2662
2663 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2664 heuristicCodeOffset));
2665
2666 flock(mCacheFd, LOCK_UN);
2667
2668 if (nread != (size_t)heuristicCodeOffset) {
2669 LOGE("read(mCacheFd) failed\n");
2670 free(mCacheMapAddr);
2671 goto bail;
2672 }
2673
2674 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
Shih-wei Liao3d77c422010-11-21 19:51:59 -08002675 LOGE("sliao: mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
2676 LOGE("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
2677 LOGE("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
2678 LOGE("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
2679 LOGE("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002680
2681 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2682 LOGE("assertion failed: heuristic code offset is not correct.\n");
2683 goto bail;
2684 }
2685#else
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002686 mCacheMapAddr = (char *) mmap(0, mCacheSize,
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002687 PROT_READ | PROT_EXEC | PROT_WRITE,
2688 MAP_PRIVATE, mCacheFd, 0);
2689
Logan798280d2010-11-20 04:06:16 +08002690 if (mCacheMapAddr == MAP_FAILED) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002691 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2692 flock(mCacheFd, LOCK_UN);
2693 goto giveup;
2694 }
2695
2696 flock(mCacheFd, LOCK_UN);
2697
2698 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
2699
2700 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2701#endif
2702 }
2703
2704
2705 // Verify the Cache File
2706 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2707 LOGE("bad magic word\n");
2708 goto bail;
2709 }
2710
2711 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2712 LOGE("bad oBCC version 0x%08x\n",
2713 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2714 goto bail;
2715 }
2716
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002717 if (mCacheSize < mCacheHdr->relocOffset +
Logan824dd0a2010-11-20 01:45:54 +08002718 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002719 LOGE("relocate table overflow\n");
2720 goto bail;
2721 }
2722
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002723 if (mCacheSize < mCacheHdr->exportVarsOffset +
2724 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002725 LOGE("export variables table overflow\n");
2726 goto bail;
2727 }
2728
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002729 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2730 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002731 LOGE("export functions table overflow\n");
2732 goto bail;
2733 }
2734
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002735 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2736 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002737 LOGE("export pragmas table overflow\n");
2738 goto bail;
2739 }
2740
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002741 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002742 LOGE("code cache overflow\n");
2743 goto bail;
2744 }
2745
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002746 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002747 LOGE("data (global variable) cache overflow\n");
2748 goto bail;
2749 }
2750
2751
2752 // Relocate
2753 {
2754 mCacheDiff = mCodeDataAddr -
2755 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2756
2757#ifdef BCC_CODE_ADDR
2758 if (mCacheDiff != 0) {
2759 LOGE("mCacheDiff should be zero but mCacheDiff = %d\n", mCacheDiff);
2760 goto bail;
2761 }
2762#else
Logan7f00bef2010-11-20 02:01:48 +08002763 if (mCacheHdr->rootAddr) {
2764 mCacheHdr->rootAddr += mCacheDiff;
2765 }
2766
2767 if (mCacheHdr->initAddr) {
2768 mCacheHdr->initAddr += mCacheDiff;
2769 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002770
Logan824dd0a2010-11-20 01:45:54 +08002771 oBCCRelocEntry *cachedRelocTable =
2772 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2773 mCacheHdr->relocOffset);
2774
2775 std::vector<llvm::MachineRelocation> relocations;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002776
2777 // Read in the relocs
2778 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
Logan824dd0a2010-11-20 01:45:54 +08002779 oBCCRelocEntry *entry = &cachedRelocTable[i];
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002780
Logan824dd0a2010-11-20 01:45:54 +08002781 llvm::MachineRelocation reloc =
2782 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2783 (unsigned)entry->relocType, 0, 0);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002784
Logan824dd0a2010-11-20 01:45:54 +08002785 reloc.setResultPointer(
2786 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2787
2788 relocations.push_back(reloc);
2789 }
2790
2791 // Rewrite machine code using llvm::TargetJITInfo relocate
2792 {
2793 llvm::TargetMachine *TM = NULL;
2794 const llvm::Target *Target;
2795 std::string FeaturesStr;
2796
2797 // Create TargetMachine
2798 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2799 if (hasError())
2800 goto bail;
2801
2802 if (!CPU.empty() || !Features.empty()) {
2803 llvm::SubtargetFeatures F;
2804 F.setCPU(CPU);
2805 for (std::vector<std::string>::const_iterator I = Features.begin(),
2806 E = Features.end(); I != E; I++)
2807 F.AddFeature(*I);
2808 FeaturesStr = F.getString();
2809 }
2810
2811 TM = Target->createTargetMachine(Triple, FeaturesStr);
2812 if (TM == NULL) {
2813 setError("Failed to create target machine implementation for the"
2814 " specified triple '" + Triple + "'");
2815 goto bail;
2816 }
2817
2818 TM->getJITInfo()->relocate(mCodeDataAddr,
2819 &relocations[0], relocations.size(),
2820 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2821
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002822 if (mCodeEmitter.get()) {
2823 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2824 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2825 2 * 1024 /*MaxCodeSize*/,
2826 false);
2827 }
2828
Logan824dd0a2010-11-20 01:45:54 +08002829 delete TM;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002830 }
2831#endif
2832 }
2833
2834 return 0;
2835
2836 bail:
2837#ifdef BCC_CODE_ADDR
2838 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2839 LOGE("munmap failed: %s\n", strerror(errno));
2840 }
2841
2842 if (mCacheMapAddr) {
2843 free(mCacheMapAddr);
2844 }
2845#else
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002846 if (munmap(mCacheMapAddr, mCacheSize) != 0) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002847 LOGE("munmap failed: %s\n", strerror(errno));
2848 }
2849#endif
2850
2851 giveup:
2852 return 1;
2853 }
2854
2855 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002856 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002857 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002858
Zonr Chang932648d2010-10-13 22:23:56 +08002859 llvm::TargetMachine *TM = NULL;
2860 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002861 std::string FeaturesStr;
2862
Zonr Chang932648d2010-10-13 22:23:56 +08002863 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002864
Zonr Chang932648d2010-10-13 22:23:56 +08002865 const llvm::NamedMDNode *PragmaMetadata;
2866 const llvm::NamedMDNode *ExportVarMetadata;
2867 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002868
Zonr Chang932648d2010-10-13 22:23:56 +08002869 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002870 return 0;
2871
Zonr Chang932648d2010-10-13 22:23:56 +08002872 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002873 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002874 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002875 goto on_bcc_compile_error;
2876
Zonr Chang932648d2010-10-13 22:23:56 +08002877 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002878 llvm::SubtargetFeatures F;
2879 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002880 for (std::vector<std::string>::const_iterator I = Features.begin(),
2881 E = Features.end();
2882 I != E;
2883 I++)
2884 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002885 FeaturesStr = F.getString();
2886 }
2887
2888 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002889 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002890 setError("Failed to create target machine implementation for the"
2891 " specified triple '" + Triple + "'");
2892 goto on_bcc_compile_error;
2893 }
2894
Zonr Chang932648d2010-10-13 22:23:56 +08002895 // Create memory manager for creation of code emitter later.
2896 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002897 setError("Failed to startup memory management for further compilation");
2898 goto on_bcc_compile_error;
2899 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002900 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002901
Zonr Chang932648d2010-10-13 22:23:56 +08002902 // Create code emitter
2903 if (!mCodeEmitter.get()) {
2904 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002905 setError("Failed to create machine code emitter to complete"
2906 " the compilation");
2907 goto on_bcc_compile_error;
2908 }
2909 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002910 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002911 mCodeEmitter->reset();
2912 }
2913
2914 mCodeEmitter->setTargetMachine(*TM);
2915 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2916 mpSymbolLookupContext);
2917
Zonr Chang932648d2010-10-13 22:23:56 +08002918 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002919 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002920
Zonr Chang5d35b972010-10-23 14:36:47 +08002921 // Load named metadata
2922 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2923 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2924 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2925
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002926 // Create LTO passes and run them on the mModule
2927 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002928 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002929 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08002930 LTOPasses.add(new llvm::TargetData(*TD));
2931
2932 std::vector<const char*> ExportSymbols;
2933
2934 // A workaround for getting export variable and function name. Will refine
2935 // it soon.
2936 if (ExportVarMetadata) {
2937 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2938 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2939 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2940 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2941 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2942 llvm::StringRef ExportVarName =
2943 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2944 ExportSymbols.push_back(ExportVarName.data());
2945 }
2946 }
2947 }
2948 }
2949
2950 if (ExportFuncMetadata) {
2951 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2952 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2953 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2954 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2955 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2956 llvm::StringRef ExportFuncName =
2957 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2958 ExportSymbols.push_back(ExportFuncName.data());
2959 }
2960 }
2961 }
2962 }
2963 // root() and init() are born to be exported
2964 ExportSymbols.push_back("root");
2965 ExportSymbols.push_back("init");
2966
Zonr Change5c7a542010-10-24 01:07:27 +08002967 // We now create passes list performing LTO. These are copied from
2968 // (including comments) llvm::createStandardLTOPasses().
2969
2970 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08002971 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002972
Zonr Change5c7a542010-10-24 01:07:27 +08002973 // Propagate constants at call sites into the functions they call. This
2974 // opens opportunities for globalopt (and inlining) by substituting
2975 // function pointers passed as arguments to direct uses of functions.
2976 LTOPasses.add(llvm::createIPSCCPPass());
2977
2978 // Now that we internalized some globals, see if we can hack on them!
2979 LTOPasses.add(llvm::createGlobalOptimizerPass());
2980
2981 // Linking modules together can lead to duplicated global constants, only
2982 // keep one copy of each constant...
2983 LTOPasses.add(llvm::createConstantMergePass());
2984
2985 // Remove unused arguments from functions...
2986 LTOPasses.add(llvm::createDeadArgEliminationPass());
2987
2988 // Reduce the code after globalopt and ipsccp. Both can open up
2989 // significant simplification opportunities, and both can propagate
2990 // functions through function pointers. When this happens, we often have
2991 // to resolve varargs calls, etc, so let instcombine do this.
2992 LTOPasses.add(llvm::createInstructionCombiningPass());
2993
2994 // Inline small functions
2995 LTOPasses.add(llvm::createFunctionInliningPass());
2996
2997 // Remove dead EH info.
2998 LTOPasses.add(llvm::createPruneEHPass());
2999
3000 // Internalize the globals again after inlining
3001 LTOPasses.add(llvm::createGlobalOptimizerPass());
3002
3003 // Remove dead functions.
3004 LTOPasses.add(llvm::createGlobalDCEPass());
3005
3006 // If we didn't decide to inline a function, check to see if we can
3007 // transform it to pass arguments by value instead of by reference.
3008 LTOPasses.add(llvm::createArgumentPromotionPass());
3009
3010 // The IPO passes may leave cruft around. Clean up after them.
3011 LTOPasses.add(llvm::createInstructionCombiningPass());
3012 LTOPasses.add(llvm::createJumpThreadingPass());
3013
3014 // Break up allocas
3015 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3016
3017 // Run a few AA driven optimizations here and now, to cleanup the code.
3018 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3019 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3020
3021 // Hoist loop invariants.
3022 LTOPasses.add(llvm::createLICMPass());
3023
3024 // Remove redundancies.
3025 LTOPasses.add(llvm::createGVNPass());
3026
3027 // Remove dead memcpys.
3028 LTOPasses.add(llvm::createMemCpyOptPass());
3029
3030 // Nuke dead stores.
3031 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3032
3033 // Cleanup and simplify the code after the scalar optimizations.
3034 LTOPasses.add(llvm::createInstructionCombiningPass());
3035
3036 LTOPasses.add(llvm::createJumpThreadingPass());
3037
3038 // Delete basic blocks, which optimization passes may have killed.
3039 LTOPasses.add(llvm::createCFGSimplificationPass());
3040
3041 // Now that we have optimized the program, discard unreachable functions.
3042 LTOPasses.add(llvm::createGlobalDCEPass());
3043
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003044 LTOPasses.run(*mModule);
3045 }
3046
Zonr Chang932648d2010-10-13 22:23:56 +08003047 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003048 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003049 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003050
Zonr Chang932648d2010-10-13 22:23:56 +08003051 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3052 *mCodeEmitter,
3053 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003054 setError("The machine code emission is not supported by BCC on target '"
3055 + Triple + "'");
3056 goto on_bcc_compile_error;
3057 }
3058
Zonr Chang932648d2010-10-13 22:23:56 +08003059 // Run the pass (the code emitter) on every non-declaration function in the
3060 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003061 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003062 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3063 I != E;
3064 I++)
3065 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003066 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003067
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003068 CodeGenPasses->doFinalization();
3069
Zonr Chang932648d2010-10-13 22:23:56 +08003070 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003071 if (ExportVarMetadata) {
3072 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3073 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3074 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3075 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3076 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003077 llvm::StringRef ExportVarName =
3078 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003079 CodeEmitter::global_addresses_const_iterator I, E;
3080 for (I = mCodeEmitter->global_address_begin(),
3081 E = mCodeEmitter->global_address_end();
3082 I != E;
3083 I++) {
3084 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003085 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003086 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003087 mExportVars.push_back(I->second);
3088 break;
3089 }
3090 }
Zonr Chang932648d2010-10-13 22:23:56 +08003091 if (I != mCodeEmitter->global_address_end())
3092 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003093 }
3094 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003095 // if reaching here, we know the global variable record in metadata is
3096 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003097 mExportVars.push_back(NULL);
3098 }
3099 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3100 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003101 }
3102
Zonr Chang932648d2010-10-13 22:23:56 +08003103 if (ExportFuncMetadata) {
3104 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3105 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3106 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3107 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3108 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003109 llvm::StringRef ExportFuncName =
3110 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3111 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3112 }
3113 }
3114 }
3115 }
3116
Zonr Chang932648d2010-10-13 22:23:56 +08003117 // Tell code emitter now can release the memory using during the JIT since
3118 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003119 mCodeEmitter->releaseUnnecessary();
3120
Zonr Chang932648d2010-10-13 22:23:56 +08003121 // Finally, read pragma information from the metadata node of the @Module if
3122 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003123 if (PragmaMetadata)
3124 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3125 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3126 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003127 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003128 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3129 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003130
Zonr Chang932648d2010-10-13 22:23:56 +08003131 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003132 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3133 llvm::StringRef PragmaName =
3134 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3135 llvm::StringRef PragmaValue =
3136 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3137
Zonr Chang932648d2010-10-13 22:23:56 +08003138 mPragmas.push_back(
3139 std::make_pair(std::string(PragmaName.data(),
3140 PragmaName.size()),
3141 std::string(PragmaValue.data(),
3142 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003143 }
3144 }
3145 }
3146
3147 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003148 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003149 if (CodeGenPasses) {
3150 delete CodeGenPasses;
3151 } else if (TD) {
3152 delete TD;
3153 }
3154 if (TM)
3155 delete TM;
3156
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003157 if (mError.empty()) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003158 if (!mNeverCache && mCacheFd >= 0 && mCacheNew) {
3159 genCacheFile();
3160 flock(mCacheFd, LOCK_UN);
3161 }
3162
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003163 return false;
3164 }
3165
Zonr Chang932648d2010-10-13 22:23:56 +08003166 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003167 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003168 }
3169
Zonr Chang932648d2010-10-13 22:23:56 +08003170 // interface for bccGetScriptInfoLog()
3171 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003172 return const_cast<char*>(mError.c_str());
3173 }
3174
Zonr Chang932648d2010-10-13 22:23:56 +08003175 // interface for bccGetScriptLabel()
3176 void *lookup(const char *name) {
3177 void *addr = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003178 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3179 if (!strcmp(name, "root")) {
3180 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3181 } else if (!strcmp(name, "init")) {
3182 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3183 }
3184 return addr;
3185 }
3186
Zonr Chang932648d2010-10-13 22:23:56 +08003187 if (mCodeEmitter.get())
3188 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003189 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003190 return addr;
3191 }
3192
Zonr Chang932648d2010-10-13 22:23:56 +08003193 // Interface for bccGetExportVars()
3194 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003195 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003196 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003197 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003198
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003199 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3200 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3201 if (actualVarCount)
3202 *actualVarCount = varCount;
3203 if (varCount > maxVarCount)
3204 varCount = maxVarCount;
3205 if (vars) {
3206 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3207 mCacheHdr->exportVarsOffset);
3208
3209 for (int i = 0; i < varCount; i++) {
3210 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3211 mCacheDiff);
3212 cachedVars++;
3213 }
3214 }
3215 return;
3216 }
3217
3218 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003219 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003220 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003221 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003222 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003223 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003224 for (ExportVarList::const_iterator I = mExportVars.begin(),
3225 E = mExportVars.end();
3226 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003227 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003228 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003229 }
3230 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003231
3232 return;
3233 }
3234
Zonr Chang932648d2010-10-13 22:23:56 +08003235 // Interface for bccGetExportFuncs()
3236 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003237 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003238 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003239 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003240
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003241 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3242 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3243 if (actualFuncCount)
3244 *actualFuncCount = funcCount;
3245 if (funcCount > maxFuncCount)
3246 funcCount = maxFuncCount;
3247 if (funcs) {
3248 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3249 mCacheHdr->exportFuncsOffset);
3250
3251 for (int i = 0; i < funcCount; i++) {
3252 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3253 mCacheDiff);
3254 cachedFuncs++;
3255 }
3256 }
3257 return;
3258 }
3259
3260 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003261 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003262 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003263 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003264 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003265 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003266 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3267 E = mExportFuncs.end();
3268 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003269 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003270 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003271 }
3272 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003273
3274 return;
3275 }
3276
Zonr Chang932648d2010-10-13 22:23:56 +08003277 // Interface for bccGetPragmas()
3278 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003279 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003280 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003281 int stringCount;
3282 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3283 if (actualStringCount)
3284 *actualStringCount = 0; // XXX
3285 return;
3286 }
3287
3288 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003289
Zonr Chang932648d2010-10-13 22:23:56 +08003290 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003291 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003292 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003293 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003294 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003295 for (PragmaList::const_iterator it = mPragmas.begin();
3296 stringCount > 0;
3297 stringCount -= 2, it++) {
3298 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3299 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003300 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003301 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003302
3303 return;
3304 }
3305
Zonr Chang932648d2010-10-13 22:23:56 +08003306 // Interface for bccGetFunctions()
3307 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003308 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003309 BCCchar **functions) {
3310 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003311 mCodeEmitter->getFunctionNames(actualFunctionCount,
3312 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003313 functions);
3314 else
3315 *actualFunctionCount = 0;
3316
3317 return;
3318 }
3319
Zonr Chang932648d2010-10-13 22:23:56 +08003320 // Interface for bccGetFunctionBinary()
3321 void getFunctionBinary(BCCchar *function,
3322 BCCvoid **base,
3323 BCCsizei *length) {
3324 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003325 mCodeEmitter->getFunctionBinary(function, base, length);
3326 } else {
3327 *base = NULL;
3328 *length = 0;
3329 }
3330 return;
3331 }
3332
Zonr Chang932648d2010-10-13 22:23:56 +08003333 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003334 return mModule;
3335 }
3336
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003337 ~Compiler() {
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003338#ifdef BCC_CODE_ADDR
3339 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3340 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3341 LOGE("munmap failed while releasing mCodeDataAddr\n");
3342 }
3343 }
3344
3345 if (mCacheMapAddr) {
3346 free(mCacheMapAddr);
3347 }
3348#else
3349 if (mCacheMapAddr != 0 && mCacheMapAddr != MAP_FAILED) {
3350 if (munmap(mCacheMapAddr, mCacheSize) < 0) {
3351 LOGE("munmap failed while releasing mCacheMapAddr\n");
3352 }
3353 }
3354#endif
3355
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003356 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003357 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003358 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003359 return;
3360 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003361
3362 private:
3363 // Note: loader() and genCacheFile() go hand in hand
3364 void genCacheFile() {
3365 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3366 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3367 return;
3368 }
3369
3370 bool codeOffsetNeedPadding = false;
3371
3372 uint32_t offset = sizeof(oBCCHeader);
3373
3374 // BCC Cache File Header
3375 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3376
3377 if (!hdr) {
3378 LOGE("Unable to allocate oBCCHeader.\n");
3379 return;
3380 }
3381
3382 // Magic Words
3383 memcpy(hdr->magic, OBCC_MAGIC, 4);
3384 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3385
3386 // Timestamp
3387 hdr->sourceWhen = 0; // TODO(all)
3388 hdr->rslibWhen = 0; // TODO(all)
3389 hdr->libRSWhen = 0; // TODO(all)
3390 hdr->libbccWhen = 0; // TODO(all)
3391
3392 // Current Memory Address (Saved for Recalculation)
3393 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3394 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3395 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3396
3397 // Relocation Table Offset and Entry Count
3398 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003399 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003400
Logan824dd0a2010-11-20 01:45:54 +08003401 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003402
3403 // Export Variable Table Offset and Entry Count
3404 hdr->exportVarsOffset = offset;
3405 hdr->exportVarsCount = mExportVars.size();
3406
3407 offset += hdr->exportVarsCount * sizeof(uint32_t);
3408
3409 // Export Function Table Offset and Entry Count
3410 hdr->exportFuncsOffset = offset;
3411 hdr->exportFuncsCount = mExportFuncs.size();
3412
3413 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3414
3415 // Export Pragmas Table Offset and Entry Count
3416 hdr->exportPragmasOffset = offset;
3417 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3418
3419 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3420
3421 // Code Offset and Size
3422
3423#ifdef BCC_CODE_ADDR
3424 {
3425 long pagesize = sysconf(_SC_PAGESIZE);
3426
3427 if (offset % pagesize > 0) {
3428 codeOffsetNeedPadding = true;
3429 offset += pagesize - (offset % pagesize);
3430 }
3431 }
3432#else
3433 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3434 codeOffsetNeedPadding = true;
3435 offset += 0x08 - (offset & 0x07);
3436 }
3437#endif
3438
3439 hdr->codeOffset = offset;
3440 hdr->codeSize = MaxCodeSize;
3441
3442 offset += hdr->codeSize;
3443
3444 // Data (Global Variable) Offset and Size
3445 hdr->dataOffset = offset;
3446 hdr->dataSize = MaxGlobalVarSize;
3447
3448 offset += hdr->dataSize;
3449
3450 // Checksum
3451 hdr->checksum = 0; // Set Field checksum. TODO(all)
3452
3453 // Write Header
3454 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3455 sizeof(oBCCHeader), "Write oBCC header");
3456
Logan824dd0a2010-11-20 01:45:54 +08003457 // Write Relocation Entry Table
3458 {
3459 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003460
Logan824dd0a2010-11-20 01:45:54 +08003461 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3462
3463 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3464 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003465 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003466
3467 // Write Export Variables Table
3468 {
3469 uint32_t *record, *ptr;
3470
3471 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3472 ptr = record;
3473
3474 if (!record) {
3475 goto bail;
3476 }
3477
3478 for (ExportVarList::const_iterator I = mExportVars.begin(),
3479 E = mExportVars.end(); I != E; I++) {
3480 *ptr++ = reinterpret_cast<uint32_t>(*I);
3481 }
3482
3483 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3484 hdr->exportVarsCount * sizeof(uint32_t),
3485 "Write ExportVars");
3486
3487 free(record);
3488 }
3489
3490 // Write Export Functions Table
3491 {
3492 uint32_t *record, *ptr;
3493
3494 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3495 ptr = record;
3496
3497 if (!record) {
3498 goto bail;
3499 }
3500
3501 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3502 E = mExportFuncs.end(); I != E; I++) {
3503 *ptr++ = reinterpret_cast<uint32_t>(*I);
3504 }
3505
3506 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3507 hdr->exportFuncsCount * sizeof(uint32_t),
3508 "Write ExportFuncs");
3509
3510 free(record);
3511 }
3512
3513
3514 // TODO(all): Write Export Pragmas Table
3515#if 0
3516#else
3517 // Note: As long as we have comment out export pragmas table code,
3518 // we have to seek the position to correct offset.
3519
3520 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3521#endif
3522
3523 if (codeOffsetNeedPadding) {
3524 // requires additional padding
3525 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3526 }
3527
3528 // Write Generated Code and Global Variable
3529 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3530 "Write code and global variable");
3531
3532 goto close_return;
3533
3534 bail:
3535 if (ftruncate(mCacheFd, 0) != 0) {
3536 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3537 }
3538
3539 close_return:
3540 free(hdr);
3541 close(mCacheFd);
3542 mCacheFd = -1;
3543 return;
3544 }
3545
3546 // OpenCacheFile() returns fd of the cache file.
3547 // Input:
3548 // BCCchar *resName: Used to genCacheFileName()
3549 // bool createIfMissing: If false, turn off caching
3550 // Output:
3551 // returns fd: If -1: Failed
3552 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3553 // cache file's file descriptor
3554 // Note: openCacheFile() will check the cache file's validity,
3555 // such as Magic number, sourceWhen... dependencies.
3556 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3557 int fd, cc;
3558 struct stat fdStat, fileStat;
3559 bool readOnly = false;
3560
3561 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3562
3563 mCacheNew = false;
3564
3565 retry:
3566 /*
3567 * Try to open the cache file. If we've been asked to,
3568 * create it if it doesn't exist.
3569 */
3570 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3571 if (fd < 0) {
3572 fd = open(cacheFileName, O_RDONLY, 0);
3573 if (fd < 0) {
3574 if (createIfMissing) {
3575 LOGE("Can't open bcc-cache '%s': %s\n",
3576 cacheFileName, strerror(errno));
3577 mCacheNew = true;
3578 }
3579 return fd;
3580 }
3581 readOnly = true;
3582 }
3583
3584 /*
3585 * Grab an exclusive lock on the cache file. If somebody else is
3586 * working on it, we'll block here until they complete.
3587 */
3588 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3589 cacheFileName, fd);
3590
3591 cc = flock(fd, LOCK_EX | LOCK_NB);
3592 if (cc != 0) {
3593 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3594 cc = flock(fd, LOCK_EX);
3595 }
3596
3597 if (cc != 0) {
3598 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3599 close(fd);
3600 return -1;
3601 }
3602 LOGV("bcc: locked cache file\n");
3603
3604 /*
3605 * Check to see if the fd we opened and locked matches the file in
3606 * the filesystem. If they don't, then somebody else unlinked ours
3607 * and created a new file, and we need to use that one instead. (If
3608 * we caught them between the unlink and the create, we'll get an
3609 * ENOENT from the file stat.)
3610 */
3611 cc = fstat(fd, &fdStat);
3612 if (cc != 0) {
3613 LOGE("Can't stat open file '%s'\n", cacheFileName);
3614 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3615 goto close_fail;
3616 }
3617 cc = stat(cacheFileName, &fileStat);
3618 if (cc != 0 ||
3619 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3620 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3621 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3622 flock(fd, LOCK_UN);
3623 close(fd);
3624 usleep(250 * 1000); // if something is hosed, don't peg machine
3625 goto retry;
3626 }
3627
3628 /*
3629 * We have the correct file open and locked. If the file size is zero,
3630 * then it was just created by us, and we want to fill in some fields
3631 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3632 * verify that the fields in the header match our expectations, and
3633 * reset the file if they don't.
3634 */
3635 if (fdStat.st_size == 0) {
3636 if (readOnly) { // The device is readOnly --> close_fail
3637 LOGW("bcc: file has zero length and isn't writable\n");
3638 goto close_fail;
3639 }
3640 /*cc = createEmptyHeader(fd);
3641 if (cc != 0)
3642 goto close_fail;
3643 */
3644 mCacheNew = true;
3645 LOGV("bcc: successfully initialized new cache file\n");
3646 } else {
3647 // Calculate sourceWhen
3648 // XXX
3649 uint32_t sourceWhen = 0;
3650 uint32_t rslibWhen = 0;
3651 uint32_t libRSWhen = 0;
3652 uint32_t libbccWhen = 0;
3653 if (!checkHeaderAndDependencies(fd,
3654 sourceWhen,
3655 rslibWhen,
3656 libRSWhen,
3657 libbccWhen)) {
3658 // If checkHeaderAndDependencies returns 0: FAILED
3659 // Will truncate the file and retry to createIfMissing the file
3660
3661 if (readOnly) { // Shouldn't be readonly.
3662 /*
3663 * We could unlink and rewrite the file if we own it or
3664 * the "sticky" bit isn't set on the directory. However,
3665 * we're not able to truncate it, which spoils things. So,
3666 * give up now.
3667 */
3668 if (createIfMissing) {
3669 LOGW("Cached file %s is stale and not writable\n",
3670 cacheFileName);
3671 }
3672 goto close_fail;
3673 }
3674
3675 /*
3676 * If we truncate the existing file before unlinking it, any
3677 * process that has it mapped will fail when it tries to touch
3678 * the pages? Probably OK because we use MAP_PRIVATE.
3679 */
3680 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3681 cacheFileName);
3682 if (ftruncate(fd, 0) != 0) {
3683 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3684 cacheFileName, strerror(errno));
3685 /* keep going */
3686 }
3687 if (unlink(cacheFileName) != 0) {
3688 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3689 cacheFileName, errno, strerror(errno));
3690 /* keep going; permission failure should probably be fatal */
3691 }
3692 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3693 flock(fd, LOCK_UN);
3694 close(fd);
3695 goto retry;
3696 } else {
3697 // Got cacheFile! Good to go.
3698 LOGV("Good cache file\n");
3699 }
3700 }
3701
3702 assert(fd >= 0);
3703 return fd;
3704
3705 close_fail:
3706 flock(fd, LOCK_UN);
3707 close(fd);
3708 return -1;
3709 } // End of openCacheFile()
3710
3711 char *genCacheFileName(const char *fileName, const char *subFileName) {
3712 char nameBuf[512];
3713 static const char kCachePath[] = "bcc-cache";
3714 char absoluteFile[sizeof(nameBuf)];
3715 const size_t kBufLen = sizeof(nameBuf) - 1;
3716 const char *dataRoot;
3717 char *cp;
3718
3719 // Get the absolute path of the raw/***.bc file.
3720 absoluteFile[0] = '\0';
3721 if (fileName[0] != '/') {
3722 /*
3723 * Generate the absolute path. This doesn't do everything it
3724 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3725 * the leading "./" out, but it'll do.
3726 */
3727 if (getcwd(absoluteFile, kBufLen) == NULL) {
3728 LOGE("Can't get CWD while opening raw/***.bc file\n");
3729 return NULL;
3730 }
3731 // TODO(srhines): strncat() is a bit dangerous
3732 strncat(absoluteFile, "/", kBufLen);
3733 }
3734 strncat(absoluteFile, fileName, kBufLen);
3735
3736 if (subFileName != NULL) {
3737 strncat(absoluteFile, "/", kBufLen);
3738 strncat(absoluteFile, subFileName, kBufLen);
3739 }
3740
3741 /* Turn the path into a flat filename by replacing
3742 * any slashes after the first one with '@' characters.
3743 */
3744 cp = absoluteFile + 1;
3745 while (*cp != '\0') {
3746 if (*cp == '/') {
3747 *cp = '@';
3748 }
3749 cp++;
3750 }
3751
3752 /* Build the name of the cache directory.
3753 */
3754 dataRoot = getenv("ANDROID_DATA");
3755 if (dataRoot == NULL)
3756 dataRoot = "/data";
3757 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3758
3759 /* Tack on the file name for the actual cache file path.
3760 */
3761 strncat(nameBuf, absoluteFile, kBufLen);
3762
3763 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3764 return strdup(nameBuf);
3765 }
3766
3767 /*
3768 * Read the oBCC header, verify it, then read the dependent section
3769 * and verify that data as well.
3770 *
3771 * On successful return, the file will be seeked immediately past the
3772 * oBCC header.
3773 */
3774 bool checkHeaderAndDependencies(int fd,
3775 uint32_t sourceWhen,
3776 uint32_t rslibWhen,
3777 uint32_t libRSWhen,
3778 uint32_t libbccWhen) {
3779 ssize_t actual;
3780 oBCCHeader optHdr;
3781 uint32_t val;
3782 uint8_t const *magic, *magicVer;
3783
3784 /*
3785 * Start at the start. The "bcc" header, when present, will always be
3786 * the first thing in the file.
3787 */
3788 if (lseek(fd, 0, SEEK_SET) != 0) {
3789 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3790 goto bail;
3791 }
3792
3793 /*
3794 * Read and do trivial verification on the bcc header. The header is
3795 * always in host byte order.
3796 */
3797 actual = read(fd, &optHdr, sizeof(optHdr));
3798 if (actual < 0) {
3799 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3800 goto bail;
3801 } else if (actual != sizeof(optHdr)) {
3802 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3803 (int) actual, sizeof(optHdr));
3804 goto bail;
3805 }
3806
3807 magic = optHdr.magic;
3808 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3809 /* not an oBCC file, or previous attempt was interrupted */
3810 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3811 magic[0], magic[1], magic[2], magic[3]);
3812 goto bail;
3813 }
3814
3815 magicVer = optHdr.magicVersion;
3816 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3817 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3818 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3819 goto bail;
3820 }
3821
3822 /*
3823 * Do the header flags match up with what we want?
3824 *
3825 * This is useful because it allows us to automatically regenerate
3826 * a file when settings change (e.g. verification is now mandatory),
3827 * but can cause difficulties if the thing we depend upon
3828 * were handled differently than the current options specify.
3829 *
3830 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3831 * by limiting the match mask.
3832 *
3833 * The only thing we really can't handle is incorrect byte-ordering.
3834 */
3835
3836 val = optHdr.sourceWhen;
3837 if (val && (val != sourceWhen)) {
3838 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3839 val, sourceWhen);
3840 goto bail;
3841 }
3842 val = optHdr.rslibWhen;
3843 if (val && (val != rslibWhen)) {
3844 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3845 val, rslibWhen);
3846 goto bail;
3847 }
3848 val = optHdr.libRSWhen;
3849 if (val && (val != libRSWhen)) {
3850 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3851 val, libRSWhen);
3852 goto bail;
3853 }
3854 val = optHdr.libbccWhen;
3855 if (val && (val != libbccWhen)) {
3856 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3857 val, libbccWhen);
3858 goto bail;
3859 }
3860
3861 return true;
3862
3863 bail:
3864 return false;
3865 }
3866
Zonr Chang932648d2010-10-13 22:23:56 +08003867};
3868// End of Class Compiler
3869////////////////////////////////////////////////////////////////////////////////
3870
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003871
3872bool Compiler::GlobalInitialized = false;
3873
Zonr Chang932648d2010-10-13 22:23:56 +08003874// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003875llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3876
3877std::string Compiler::Triple;
3878
3879std::string Compiler::CPU;
3880
3881std::vector<std::string> Compiler::Features;
3882
Zonr Chang932648d2010-10-13 22:23:56 +08003883// The named of metadata node that pragma resides (should be synced with
3884// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003885const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3886
Zonr Chang932648d2010-10-13 22:23:56 +08003887// The named of metadata node that export variable name resides (should be
3888// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003889const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3890
Zonr Chang932648d2010-10-13 22:23:56 +08003891// The named of metadata node that export function name resides (should be
3892// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003893const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3894
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003895struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003896 //////////////////////////////////////////////////////////////////////////////
3897 // Part I. Compiler
3898 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003899 Compiler compiler;
3900
Zonr Chang932648d2010-10-13 22:23:56 +08003901 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003902 compiler.registerSymbolCallback(pFn, pContext);
3903 }
3904
Zonr Chang932648d2010-10-13 22:23:56 +08003905 //////////////////////////////////////////////////////////////////////////////
3906 // Part II. Logistics & Error handling
3907 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003908 BCCscript() {
3909 bccError = BCC_NO_ERROR;
3910 }
3911
3912 ~BCCscript() {
3913 }
3914
3915 void setError(BCCenum error) {
3916 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3917 bccError = error;
3918 }
3919 }
3920
3921 BCCenum getError() {
3922 BCCenum result = bccError;
3923 bccError = BCC_NO_ERROR;
3924 return result;
3925 }
3926
3927 BCCenum bccError;
3928};
3929
3930
3931extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003932BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003933 return new BCCscript();
3934}
3935
3936extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003937BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003938 return script->getError();
3939}
3940
3941extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003942void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003943 delete script;
3944}
3945
3946extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003947void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003948 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08003949 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003950 script->registerSymbolCallback(pFn, pContext);
3951}
3952
3953extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003954int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08003955 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003956 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08003957}
3958
3959extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003960int bccReadBC(BCCscript *script,
3961 const BCCchar *bitcode,
3962 BCCint size,
3963 const BCCchar *resName) {
3964 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003965}
3966
3967extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003968void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08003969 const BCCchar *bitcode,
3970 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003971 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08003972}
3973
3974extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003975void bccLoadBinary(BCCscript *script) {
3976 int result = script->compiler.loader();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003977 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003978 script->setError(BCC_INVALID_OPERATION);
3979}
3980
3981extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003982void bccCompileBC(BCCscript *script) {
3983 {
3984#if defined(__arm__)
3985 android::StopWatch compileTimer("RenderScript compile time");
3986#endif
3987 int result = script->compiler.compile();
3988 if (result)
3989 script->setError(BCC_INVALID_OPERATION);
3990 }
3991}
3992
3993extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003994void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003995 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08003996 BCCsizei *length,
3997 BCCchar *infoLog) {
3998 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003999 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004000 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004001 *length = messageLength;
4002
4003 if (infoLog && maxLength > 0) {
4004 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4005 memcpy(infoLog, message, trimmedLength);
4006 infoLog[trimmedLength] = 0;
4007 }
4008}
4009
4010extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004011void bccGetScriptLabel(BCCscript *script,
4012 const BCCchar *name,
4013 BCCvoid **address) {
4014 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004015 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004016 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004017 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004018 script->setError(BCC_INVALID_VALUE);
4019}
4020
4021extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004022void bccGetExportVars(BCCscript *script,
4023 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004024 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004025 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004026 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4027}
4028
4029extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004030void bccGetExportFuncs(BCCscript *script,
4031 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004032 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004033 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004034 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4035}
4036
4037extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004038void bccGetPragmas(BCCscript *script,
4039 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004040 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004041 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004042 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4043}
4044
4045extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004046void bccGetFunctions(BCCscript *script,
4047 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004048 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004049 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004050 script->compiler.getFunctions(actualFunctionCount,
4051 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004052 functions);
4053}
4054
4055extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004056void bccGetFunctionBinary(BCCscript *script,
4057 BCCchar *function,
4058 BCCvoid **base,
4059 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004060 script->compiler.getFunctionBinary(function, base, length);
4061}
4062
4063struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004064 const Compiler *compiler;
4065 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004066};
4067
Zonr Chang932648d2010-10-13 22:23:56 +08004068} // namespace bcc