blob: aca6280b35e7dbe020543b5a2f2233f1efbd3b47 [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 Liao7c5a5f72010-11-08 01:59:13 -080020//#define BCC_CODE_ADDR 0x7e00000
21
Shih-wei Liao77ed6142010-04-07 12:21:42 -070022#define LOG_TAG "bcc"
23#include <cutils/log.h>
24
25#include <ctype.h>
26#include <errno.h>
27#include <limits.h>
28#include <stdarg.h>
29#include <stdint.h>
30#include <stdio.h>
31#include <stdlib.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080032#include <stddef.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070033#include <string.h>
34#include <unistd.h>
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -070035#include <sys/mman.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080036#include <sys/file.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070039
40#include <cutils/hashmap.h>
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -080041#include <utils/StopWatch.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070042
Shih-wei Liao77ed6142010-04-07 12:21:42 -070043#if defined(__arm__)
Zonr Chang932648d2010-10-13 22:23:56 +080044# define DEFAULT_ARM_CODEGEN
45# define PROVIDE_ARM_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070046#elif defined(__i386__)
Zonr Chang932648d2010-10-13 22:23:56 +080047# define DEFAULT_X86_CODEGEN
48# define PROVIDE_X86_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070049#elif defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +080050# define DEFAULT_X64_CODEGEN
51# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070052#endif
53
54#if defined(FORCE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080055# define DEFAULT_ARM_CODEGEN
56# undef DEFAULT_X86_CODEGEN
57# undef DEFAULT_X64_CODEGEN
58# define PROVIDE_ARM_CODEGEN
59# undef PROVIDE_X86_CODEGEN
60# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070061#elif defined(FORCE_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080062# undef DEFAULT_ARM_CODEGEN
63# define DEFAULT_X86_CODEGEN
64# undef DEFAULT_X64_CODEGEN
65# undef PROVIDE_ARM_CODEGEN
66# define PROVIDE_X86_CODEGEN
67# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070068#elif defined(FORCE_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080069# undef DEFAULT_ARM_CODEGEN
70# undef DEFAULT_X86_CODEGEN
71# define DEFAULT_X64_CODEGEN
72# undef PROVIDE_ARM_CODEGEN
73# undef PROVIDE_X86_CODEGEN
74# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070075#endif
76
77#if defined(DEFAULT_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080078# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070079#elif defined(DEFAULT_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080080# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070081#elif defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080082# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070083#endif
84
85#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
Zonr Chang932648d2010-10-13 22:23:56 +080086# define ARM_USE_VFP
Shih-wei Liao77ed6142010-04-07 12:21:42 -070087#endif
88
89#include <bcc/bcc.h>
90#include "bcc_runtime.h"
91
Zonr Chang932648d2010-10-13 22:23:56 +080092#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070093// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
94
Zonr Chang932648d2010-10-13 22:23:56 +080095#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070096// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
97
98// #define PROVIDE_TRACE_CODEGEN
99
100#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +0800101# include "llvm/MC/MCInst.h"
102# include "llvm/MC/MCAsmInfo.h"
103# include "llvm/MC/MCInstPrinter.h"
104# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700105// If you want the disassemble results written to file, define this:
106# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700107#endif
108
109#include <set>
110#include <map>
111#include <list>
112#include <cmath>
113#include <string>
114#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800115#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700116
Zonr Chang932648d2010-10-13 22:23:56 +0800117// VMCore
118#include "llvm/Use.h"
119#include "llvm/User.h"
Zonr Chang97f5e612010-10-22 20:38:26 +0800120#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800121#include "llvm/Module.h"
122#include "llvm/Function.h"
123#include "llvm/Constant.h"
124#include "llvm/Constants.h"
125#include "llvm/Instruction.h"
126#include "llvm/PassManager.h"
127#include "llvm/LLVMContext.h"
128#include "llvm/GlobalValue.h"
129#include "llvm/Instructions.h"
130#include "llvm/OperandTraits.h"
131#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700132
133// System
Zonr Chang932648d2010-10-13 22:23:56 +0800134#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700135
136// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800137#include "llvm/ADT/APInt.h"
138#include "llvm/ADT/APFloat.h"
139#include "llvm/ADT/DenseMap.h"
140#include "llvm/ADT/ValueMap.h"
141#include "llvm/ADT/StringMap.h"
142#include "llvm/ADT/OwningPtr.h"
143#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700144
145// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800146#include "llvm/Target/TargetData.h"
147#include "llvm/Target/TargetSelect.h"
148#include "llvm/Target/TargetOptions.h"
149#include "llvm/Target/TargetMachine.h"
150#include "llvm/Target/TargetJITInfo.h"
151#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700152#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700153
154// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800155#include "llvm/Support/Casting.h"
156#include "llvm/Support/raw_ostream.h"
157#include "llvm/Support/ValueHandle.h"
158#include "llvm/Support/MemoryBuffer.h"
159#include "llvm/Support/MemoryObject.h"
160#include "llvm/Support/ManagedStatic.h"
161#include "llvm/Support/ErrorHandling.h"
162#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700163#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700164
165// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800166#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700167
168// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800169#include "llvm/CodeGen/Passes.h"
170#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700171#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700172#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700173#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700174#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700175#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700176#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700177#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700178#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700179
180// ExecutionEngine
181#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700182#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700183
Shih-wei Liaoe64c2872010-10-25 13:44:53 -0700184extern "C" void LLVMInitializeARMDisassembler();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700185
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800186// For caching
187struct oBCCHeader {
188 uint8_t magic[4]; // includes version number
189 uint8_t magicVersion[4];
190
191 uint32_t sourceWhen;
192 uint32_t rslibWhen;
193 uint32_t libRSWhen;
194 uint32_t libbccWhen;
195
196 uint32_t cachedCodeDataAddr;
197 uint32_t rootAddr;
198 uint32_t initAddr;
199
200 uint32_t relocOffset; // offset of reloc table.
201 uint32_t relocCount;
202 uint32_t exportVarsOffset; // offset of export var table
203 uint32_t exportVarsCount;
204 uint32_t exportFuncsOffset; // offset of export func table
205 uint32_t exportFuncsCount;
206 uint32_t exportPragmasOffset; // offset of export pragma table
207 uint32_t exportPragmasCount;
208
209 uint32_t codeOffset; // offset of code: 64-bit alignment
210 uint32_t codeSize;
211 uint32_t dataOffset; // offset of data section
212 uint32_t dataSize;
213
214 // uint32_t flags; // some info flags
215 uint32_t checksum; // adler32 checksum covering deps/opt
216};
217
Logan824dd0a2010-11-20 01:45:54 +0800218struct oBCCRelocEntry {
219 uint32_t relocType; // target instruction relocation type
220 uint32_t relocOffset; // offset of hole (holeAddr - codeAddr)
221 uint32_t cachedResultAddr; // address resolved at compile time
222
Logan634bd832010-11-20 09:00:36 +0800223 oBCCRelocEntry(uint32_t ty, uintptr_t off, void *addr)
Logan824dd0a2010-11-20 01:45:54 +0800224 : relocType(ty),
225 relocOffset(static_cast<uint32_t>(off)),
226 cachedResultAddr(reinterpret_cast<uint32_t>(addr)) {
227 }
228};
229
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800230/* oBCCHeader Offset Table */
231#define k_magic offsetof(oBCCHeader, magic)
232#define k_magicVersion offsetof(oBCCHeader, magicVersion)
233#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
234#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
235#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
236#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
237#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
238#define k_rootAddr offsetof(oBCCHeader, rootAddr)
239#define k_initAddr offsetof(oBCCHeader, initAddr)
240#define k_relocOffset offsetof(oBCCHeader, relocOffset)
241#define k_relocCount offsetof(oBCCHeader, relocCount)
242#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
243#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
244#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
245#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
246#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
247#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
248#define k_codeOffset offsetof(oBCCHeader, codeOffset)
249#define k_codeSize offsetof(oBCCHeader, codeSize)
250#define k_dataOffset offsetof(oBCCHeader, dataOffset)
251#define k_dataSize offsetof(oBCCHeader, dataSize)
252#define k_checksum offsetof(oBCCHeader, checksum)
253
254/* oBCC file magic number */
255#define OBCC_MAGIC "bcc\n"
256/* version, encoded in 4 bytes of ASCII */
257#define OBCC_MAGIC_VERS "001\0"
258
259#define TEMP_FAILURE_RETRY1(exp) ({ \
260 typeof (exp) _rc; \
261 do { \
262 _rc = (exp); \
263 } while (_rc == -1 && errno == EINTR); \
264 _rc; })
265
266static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
267{
268 while (count != 0) {
269 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
270 if (actual < 0) {
271 int err = errno;
272 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
273 return err;
274 } else if (actual != (ssize_t) count) {
275 LOGD("%s: partial write (will retry): (%d of %zd)\n",
276 logMsg, (int) actual, count);
277 buf = (const void*) (((const uint8_t*) buf) + actual);
278 }
279 count -= actual;
280 }
281
282 return 0;
283}
284
Zonr Chang932648d2010-10-13 22:23:56 +0800285//
286// Compilation class that suits Android's needs.
287// (Support: no argument passed, ...)
288//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700289namespace bcc {
290
291class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800292 // This part is designed to be orthogonal to those exported bcc*() functions
293 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700294
Zonr Chang932648d2010-10-13 22:23:56 +0800295 //////////////////////////////////////////////////////////////////////////////
296 // The variable section below (e.g., Triple, CodeGenOptLevel)
297 // is initialized in GlobalInitialization()
298 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700299 static bool GlobalInitialized;
300
Zonr Chang932648d2010-10-13 22:23:56 +0800301 // If given, this will be the name of the target triple to compile for.
302 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700303 static std::string Triple;
304
305 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700306
Zonr Chang932648d2010-10-13 22:23:56 +0800307 // End of section of GlobalInitializing variables
308 //////////////////////////////////////////////////////////////////////////////
309
310 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700311 static std::string CPU;
312
Zonr Chang932648d2010-10-13 22:23:56 +0800313 // The list of target specific features to enable or disable -- this should
314 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700315 static std::vector<std::string> Features;
316
317 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800318 const char *mName;
319 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700320 };
321 static struct Runtime Runtimes[];
322
323 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800324 if (GlobalInitialized)
325 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700326
Zonr Chang932648d2010-10-13 22:23:56 +0800327 // if (!llvm::llvm_is_multithreaded())
328 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700329
Zonr Chang932648d2010-10-13 22:23:56 +0800330 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700331 Triple = TARGET_TRIPLE_STRING;
332
Zonr Chang932648d2010-10-13 22:23:56 +0800333 // TODO(zonr): NEON for JIT
334 // Features.push_back("+neon");
335 // Features.push_back("+vmlx");
336 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700337 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700338 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700339
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700340#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
341 LLVMInitializeARMTargetInfo();
342 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700343#if defined(USE_DISASSEMBLER)
344 LLVMInitializeARMDisassembler();
345 LLVMInitializeARMAsmPrinter();
346#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700347#endif
348
349#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
350 LLVMInitializeX86TargetInfo();
351 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700352#if defined(USE_DISASSEMBLER)
353 LLVMInitializeX86Disassembler();
354 LLVMInitializeX86AsmPrinter();
355#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700356#endif
357
358#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
359 LLVMInitializeX86TargetInfo();
360 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700361#if defined(USE_DISASSEMBLER)
362 LLVMInitializeX86Disassembler();
363 LLVMInitializeX86AsmPrinter();
364#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700365#endif
366
Zonr Chang932648d2010-10-13 22:23:56 +0800367 // -O0: llvm::CodeGenOpt::None
368 // -O1: llvm::CodeGenOpt::Less
369 // -O2: llvm::CodeGenOpt::Default
370 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700371 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700372
Zonr Chang932648d2010-10-13 22:23:56 +0800373 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700374
Zonr Chang932648d2010-10-13 22:23:56 +0800375 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700376 llvm::NoFramePointerElim = false;
377
Zonr Chang932648d2010-10-13 22:23:56 +0800378 // Use hardfloat ABI
379 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800380 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800381 // softfp. To use softfp, change following 2 lines to
382 //
383 // llvm::FloatABIType = llvm::FloatABI::Soft;
384 // llvm::UseSoftFloat = true;
385 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700386 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700387 llvm::UseSoftFloat = false;
388
Zonr Chang932648d2010-10-13 22:23:56 +0800389 // BCC needs all unknown symbols resolved at JIT/compilation time.
390 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700391 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
392
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700393#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800394 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700395 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
396#else
Zonr Chang932648d2010-10-13 22:23:56 +0800397 // This is set for the linker (specify how large of the virtual addresses
398 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700399 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
400#endif
401
Zonr Chang932648d2010-10-13 22:23:56 +0800402 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700403 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
404
Zonr Chang932648d2010-10-13 22:23:56 +0800405 // Register allocation policy:
406 // createFastRegisterAllocator: fast but bad quality
407 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700408 llvm::RegisterRegAlloc::setDefault
409 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700410 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700411 llvm::createLinearScanRegisterAllocator);
412
413 GlobalInitialized = true;
414 return;
415 }
416
417 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800418 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700419 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700420 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800421 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700422 }
423
424 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700425 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700426 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700427
428 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700429 std::string mError;
430
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700431 inline bool hasError() const {
432 return !mError.empty();
433 }
Zonr Chang932648d2010-10-13 22:23:56 +0800434 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700435 mError.assign(Error); // Copying
436 return;
437 }
Zonr Chang932648d2010-10-13 22:23:56 +0800438 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700439 mError = Error;
440 return;
441 }
442
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800443 bool mNeverCache; // Set by readBC()
444 bool mCacheNew; // Set by readBC()
445 int mCacheFd; // Set by readBC()
446 char *mCacheMapAddr; // Set by loader() if mCacheNew is false
447 oBCCHeader *mCacheHdr; // Set by loader()
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800448 size_t mCacheSize; // Set by loader()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800449 ptrdiff_t mCacheDiff; // Set by loader()
450 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
451 // Used by genCacheFile() for dumping
452
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700453 typedef std::list< std::pair<std::string, std::string> > PragmaList;
454 PragmaList mPragmas;
455
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700456 typedef std::list<void*> ExportVarList;
457 ExportVarList mExportVars;
458
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700459 typedef std::list<void*> ExportFuncList;
460 ExportFuncList mExportFuncs;
461
Zonr Chang932648d2010-10-13 22:23:56 +0800462 //////////////////////////////////////////////////////////////////////////////
463 // Memory manager for the code reside in memory
464 //
465 // The memory for our code emitter is very simple and is conforming to the
466 // design decisions of Android RenderScript's Exection Environment:
467 // The code, data, and symbol sizes are limited (currently 100KB.)
468 //
469 // It's very different from typical compiler, which has no limitation
470 // on the code size. How does code emitter know the size of the code
471 // it is about to emit? It does not know beforehand. We want to solve
472 // this without complicating the code emitter too much.
473 //
474 // We solve this by pre-allocating a certain amount of memory,
475 // and then start the code emission. Once the buffer overflows, the emitter
476 // simply discards all the subsequent emission but still has a counter
477 // on how many bytes have been emitted.
478 //
479 // So once the whole emission is done, if there's a buffer overflow,
480 // it re-allocates the buffer with enough size (based on the
481 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800482
483 // 128 KiB for code
484 static const unsigned int MaxCodeSize = 128 * 1024;
485 // 1 KiB for global offset table (GOT)
486 static const unsigned int MaxGOTSize = 1 * 1024;
487 // 128 KiB for global variable
488 static const unsigned int MaxGlobalVarSize = 128 * 1024;
489
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700490 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700491 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800492 //
493 // Our memory layout is as follows:
494 //
495 // The direction of arrows (-> and <-) shows memory's growth direction
496 // when more space is needed.
497 //
498 // @mpCodeMem:
499 // +--------------------------------------------------------------+
500 // | Function Memory ... -> <- ... Stub/GOT |
501 // +--------------------------------------------------------------+
502 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
503 //
504 // Where size of GOT is @MaxGOTSize KiB.
505 //
506 // @mpGVMem:
507 // +--------------------------------------------------------------+
508 // | Global variable ... -> |
509 // +--------------------------------------------------------------+
510 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
511 //
512 //
513 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
514 // of function code's memory usage
515 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
516 // of stub/GOT's memory usage
517 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
518 // of global variable's memory usage
519 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700520 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700521 uintptr_t mCurSGMemIdx;
522 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800523 void *mpCodeMem;
524 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700525
Zonr Chang932648d2010-10-13 22:23:56 +0800526 // GOT Base
527 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700528
529 typedef std::map<const llvm::Function*, pair<void* /* start address */,
530 void* /* end address */>
531 > FunctionMapTy;
532 FunctionMapTy mFunctionMap;
533
Zonr Chang932648d2010-10-13 22:23:56 +0800534 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700535 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700536 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700537
Zonr Chang932648d2010-10-13 22:23:56 +0800538 uint8_t *allocateSGMemory(uintptr_t Size,
539 unsigned Alignment = 1 /* no alignment */) {
540 intptr_t FreeMemSize = getFreeCodeMemSize();
541 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
542 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700543 return NULL;
544
Zonr Chang932648d2010-10-13 22:23:56 +0800545 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700546 Alignment = 1;
547
Zonr Chang932648d2010-10-13 22:23:56 +0800548 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700549 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
550
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700551 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700552
553 return result;
554 }
555
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700556 inline uintptr_t getFreeGVMemSize() const {
557 return MaxGlobalVarSize - mCurGVMemIdx;
558 }
Zonr Chang932648d2010-10-13 22:23:56 +0800559 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700560 return reinterpret_cast<uint8_t*>(mpGVMem);
561 }
562
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700563 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700564 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700565 reset();
566 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700567
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800568#ifdef BCC_CODE_ADDR
569 mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
570 MaxCodeSize + MaxGlobalVarSize,
571 PROT_READ | PROT_EXEC | PROT_WRITE,
572 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
573 -1,
574 0);
575#else
576 mpCodeMem = mmap(NULL,
577 MaxCodeSize + MaxGlobalVarSize,
578 PROT_READ | PROT_EXEC | PROT_WRITE,
579 MAP_PRIVATE | MAP_ANON,
580 -1,
581 0);
582#endif
583
584 if (mpCodeMem == MAP_FAILED) {
585 llvm::report_fatal_error("Failed to allocate memory for emitting "
586 "codes\n" + ErrMsg);
587 }
588 mpGVMem = (void *) ((int) mpCodeMem + MaxCodeSize);
589
590 /* mpCodeMem = mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700591 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700592 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800593 llvm::report_fatal_error("Failed to allocate memory for emitting "
594 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700595
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800596 mpGVMem = mmap(mpCodeMem, MaxGlobalVarSize,
597 PROT_READ | PROT_WRITE,
598 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700599 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800600 llvm::report_fatal_error("Failed to allocate memory for emitting "
601 "global variables\n" + ErrMsg);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800602 */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700603 return;
604 }
605
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800606 inline uint8_t *getCodeMemBase() const {
607 return reinterpret_cast<uint8_t*>(mpCodeMem);
608 }
609
Zonr Chang932648d2010-10-13 22:23:56 +0800610 // setMemoryWritable - When code generation is in progress, the code pages
611 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700612 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700613 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700614 return;
615 }
616
Zonr Chang932648d2010-10-13 22:23:56 +0800617 // When code generation is done and we're ready to start execution, the
618 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700619 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700620 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700621 return;
622 }
623
Zonr Chang932648d2010-10-13 22:23:56 +0800624 // Setting this flag to true makes the memory manager garbage values over
625 // freed memory. This is useful for testing and debugging, and is to be
626 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700627 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800628 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700629 return;
630 }
631
Zonr Chang932648d2010-10-13 22:23:56 +0800632 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700633
Zonr Chang932648d2010-10-13 22:23:56 +0800634 // If the current table requires a Global Offset Table, this method is
635 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700636 void AllocateGOT() {
637 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700638 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700639 HasGOT = true;
640 return;
641 }
642
Zonr Chang932648d2010-10-13 22:23:56 +0800643 // If this is managing a Global Offset Table, this method should return a
644 // pointer to its base.
645 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700646 return mpGOTBase;
647 }
648
Zonr Chang932648d2010-10-13 22:23:56 +0800649 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700650
Zonr Chang932648d2010-10-13 22:23:56 +0800651 // When we start JITing a function, the JIT calls this method to allocate a
652 // block of free RWX memory, which returns a pointer to it. If the JIT wants
653 // to request a block of memory of at least a certain size, it passes that
654 // value as ActualSize, and this method returns a block with at least that
655 // much space. If the JIT doesn't know ahead of time how much space it will
656 // need to emit the function, it passes 0 for the ActualSize. In either
657 // case, this method is required to pass back the size of the allocated
658 // block through ActualSize. The JIT will be careful to not write more than
659 // the returned ActualSize bytes of memory.
660 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
661 intptr_t FreeMemSize = getFreeCodeMemSize();
662 if ((FreeMemSize < 0) ||
663 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
664 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700665 return NULL;
666
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700667 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700668 return (getCodeMemBase() + mCurFuncMemIdx);
669 }
670
Zonr Chang932648d2010-10-13 22:23:56 +0800671 // This method is called by the JIT to allocate space for a function stub
672 // (used to handle limited branch displacements) while it is JIT compiling a
673 // function. For example, if foo calls bar, and if bar either needs to be
674 // lazily compiled or is a native function that exists too far away from the
675 // call site to work, this method will be used to make a thunk for it. The
676 // stub should be "close" to the current function body, but should not be
677 // included in the 'actualsize' returned by startFunctionBody.
678 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700679 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700680 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700681 }
682
Zonr Chang932648d2010-10-13 22:23:56 +0800683 // This method is called when the JIT is done codegen'ing the specified
684 // function. At this point we know the size of the JIT compiled function.
685 // This passes in FunctionStart (which was returned by the startFunctionBody
686 // method) and FunctionEnd which is a pointer to the actual end of the
687 // function. This method should mark the space allocated and remember where
688 // it is in case the client wants to deallocate it.
689 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
690 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700691 assert(FunctionEnd > FunctionStart);
692 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
693 "Mismatched function start/end!");
694
Zonr Chang932648d2010-10-13 22:23:56 +0800695 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700696 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700697 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700698 "Code size excess the limitation!");
699 mCurFuncMemIdx += FunctionCodeSize;
700
Zonr Chang932648d2010-10-13 22:23:56 +0800701 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700702 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
703 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800704 mFunctionMap.insert(
705 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
706 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700707
708 return;
709 }
710
Zonr Chang932648d2010-10-13 22:23:56 +0800711 // Allocate a (function code) memory block of the given size. This method
712 // cannot be called between calls to startFunctionBody and endFunctionBody.
713 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
714 if (getFreeCodeMemSize() < Size)
715 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700716 return NULL;
717
Zonr Chang932648d2010-10-13 22:23:56 +0800718 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700719 Alignment = 1;
720
Zonr Chang932648d2010-10-13 22:23:56 +0800721 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700722 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800723 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700724
725 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
726
727 return result;
728 }
729
Zonr Chang932648d2010-10-13 22:23:56 +0800730 // Allocate memory for a global variable.
731 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700732 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800733 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700734 LOGE("No Global Memory");
735 return NULL;
736 }
737
Zonr Chang932648d2010-10-13 22:23:56 +0800738 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700739 Alignment = 1;
740
Zonr Chang932648d2010-10-13 22:23:56 +0800741 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700742 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800743 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700744
745 mCurGVMemIdx = (result + Size) - getGVMemBase();
746
747 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700748 }
749
Zonr Chang932648d2010-10-13 22:23:56 +0800750 // Free the specified function body. The argument must be the return value
751 // from a call to startFunctionBody() that hasn't been deallocated yet. This
752 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700753 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800754 // linear search
755 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
756 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
757 E = mFunctionMap.end();
758 I != E;
759 I++)
760 if (I->second.first == Body) {
761 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
762 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700763 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800764 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700765
Zonr Chang932648d2010-10-13 22:23:56 +0800766 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700767
Zonr Chang932648d2010-10-13 22:23:56 +0800768 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700769 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
770
771 assert(SizeNeedMove >= 0 &&
772 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
773 " be correctly calculated!");
774
Zonr Chang932648d2010-10-13 22:23:56 +0800775 if (SizeNeedMove > 0)
776 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700777 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
778 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
779
780 return;
781 }
782
Zonr Chang932648d2010-10-13 22:23:56 +0800783 // When we finished JITing the function, if exception handling is set, we
784 // emit the exception table.
785 uint8_t *startExceptionTable(const llvm::Function *F,
786 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700787 assert(false && "Exception is not allowed in our language specification");
788 return NULL;
789 }
790
Zonr Chang932648d2010-10-13 22:23:56 +0800791 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700792 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800793 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700794 assert(false && "Exception is not allowed in our language specification");
795 return;
796 }
797
Zonr Chang932648d2010-10-13 22:23:56 +0800798 // Free the specified exception table's memory. The argument must be the
799 // return value from a call to startExceptionTable() that hasn't been
800 // deallocated yet. This is never called when the JIT is currently emitting
801 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700802 void deallocateExceptionTable(void *ET) {
803 assert(false && "Exception is not allowed in our language specification");
804 return;
805 }
806
Zonr Chang932648d2010-10-13 22:23:56 +0800807 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700808 void reset() {
809 mpGOTBase = NULL;
810 HasGOT = false;
811
812 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700813 mCurSGMemIdx = MaxCodeSize - 1;
814 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700815
816 mFunctionMap.clear();
817
818 return;
819 }
820
821 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800822 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700823 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800824 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700825 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700826 return;
827 }
Zonr Chang932648d2010-10-13 22:23:56 +0800828 };
829 // End of class CodeMemoryManager
830 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700831
Zonr Chang932648d2010-10-13 22:23:56 +0800832 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700833 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800834 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700835 mCodeMemMgr.reset(new CodeMemoryManager());
836 return mCodeMemMgr.get();
837 }
838
Zonr Chang932648d2010-10-13 22:23:56 +0800839 //////////////////////////////////////////////////////////////////////////////
840 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700841 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700842 public:
843 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
844 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
845
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800846 GlobalAddressMapTy mGlobalAddressMap;
847
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700848 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800849 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700850
Zonr Chang932648d2010-10-13 22:23:56 +0800851 // The JITInfo for the target we are compiling to
852 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700853
Zonr Chang932648d2010-10-13 22:23:56 +0800854 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700855
Zonr Chang932648d2010-10-13 22:23:56 +0800856 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700857
858 class EmittedFunctionCode {
859 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800860 // Beginning of the function's allocation.
861 void *FunctionBody;
862
863 // The address the function's code actually starts at.
864 void *Code;
865
866 // The size of the function code
867 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700868
869 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
870 };
Zonr Chang932648d2010-10-13 22:23:56 +0800871 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700872
Zonr Chang932648d2010-10-13 22:23:56 +0800873 typedef std::map<const std::string,
874 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700875 EmittedFunctionsMapTy mEmittedFunctions;
876
Zonr Chang932648d2010-10-13 22:23:56 +0800877 // This vector is a mapping from MBB ID's to their address. It is filled in
878 // by the StartMachineBasicBlock callback and queried by the
879 // getMachineBasicBlockAddress callback.
880 std::vector<uintptr_t> mMBBLocations;
881
882 // The constant pool for the current function.
883 llvm::MachineConstantPool *mpConstantPool;
884
885 // A pointer to the first entry in the constant pool.
886 void *mpConstantPoolBase;
887
888 // Addresses of individual constant pool entries.
889 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
890
891 // The jump tables for the current function.
892 llvm::MachineJumpTableInfo *mpJumpTable;
893
894 // A pointer to the first entry in the jump table.
895 void *mpJumpTableBase;
896
897 // When outputting a function stub in the context of some other function, we
898 // save BufferBegin/BufferEnd/CurBufferPtr here.
899 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
900
901 // These are the relocations that the function needs, as emitted.
902 std::vector<llvm::MachineRelocation> mRelocations;
903
Logan824dd0a2010-11-20 01:45:54 +0800904 std::vector<oBCCRelocEntry> mCachingRelocations;
905
Zonr Chang932648d2010-10-13 22:23:56 +0800906 // This vector is a mapping from Label ID's to their address.
907 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
908
909 // Machine module info for exception informations
910 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700911
Zonr Chang932648d2010-10-13 22:23:56 +0800912 // Replace an existing mapping for GV with a new address. This updates both
913 // maps as required. If Addr is null, the entry for the global is removed
914 // from the mappings.
915 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
916 if (Addr == NULL) {
917 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700918 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
919 void *OldVal;
920
Zonr Chang932648d2010-10-13 22:23:56 +0800921 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700922 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800923 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700924 OldVal = I->second;
925 mGlobalAddressMap.erase(I);
926 }
927
928 return OldVal;
929 }
930
Zonr Chang932648d2010-10-13 22:23:56 +0800931 void *&CurVal = mGlobalAddressMap[GV];
932 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700933
934 CurVal = Addr;
935
936 return OldVal;
937 }
938
Zonr Chang932648d2010-10-13 22:23:56 +0800939 // Tell the execution engine that the specified global is at the specified
940 // location. This is used internally as functions are JIT'd and as global
941 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700942 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800943 void *&CurVal = mGlobalAddressMap[GV];
944 assert((CurVal == 0 || Addr == 0) &&
945 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700946 CurVal = Addr;
947 return;
948 }
949
Zonr Chang932648d2010-10-13 22:23:56 +0800950 // This returns the address of the specified global value if it is has
951 // already been codegen'd, otherwise it returns null.
952 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700953 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700954 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
955 }
956
Zonr Chang932648d2010-10-13 22:23:56 +0800957 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
958 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700959 MCP->getConstants();
960
Zonr Chang932648d2010-10-13 22:23:56 +0800961 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700962 return 0;
963
964 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800965 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700966 llvm::MachineConstantPoolEntry CPE = Constants[i];
967 unsigned int AlignMask = CPE.getAlignment() - 1;
968 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800969 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700970 Size += mpTD->getTypeAllocSize(Ty);
971 }
972
973 return Size;
974 }
975
Zonr Chang932648d2010-10-13 22:23:56 +0800976 // This function converts a Constant* into a GenericValue. The interesting
977 // part is if C is a ConstantExpr.
978 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
979 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700980 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800981 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
982 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
983 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700984
Zonr Chang932648d2010-10-13 22:23:56 +0800985 switch (CE->getOpcode()) {
986 case llvm::Instruction::GetElementPtr: {
987 // Compute the index
988 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
989 CE->op_end());
990 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
991 &Indices[0],
992 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700993
Zonr Chang932648d2010-10-13 22:23:56 +0800994 GetConstantValue(Op0, Result);
995 Result.PointerVal =
996 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700997
Zonr Chang932648d2010-10-13 22:23:56 +0800998 return;
999 }
1000 case llvm::Instruction::Trunc: {
1001 uint32_t BitWidth =
1002 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1003
1004 GetConstantValue(Op0, Result);
1005 Result.IntVal = Result.IntVal.trunc(BitWidth);
1006
1007 return;
1008 }
1009 case llvm::Instruction::ZExt: {
1010 uint32_t BitWidth =
1011 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1012
1013 GetConstantValue(Op0, Result);
1014 Result.IntVal = Result.IntVal.zext(BitWidth);
1015
1016 return;
1017 }
1018 case llvm::Instruction::SExt: {
1019 uint32_t BitWidth =
1020 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1021
1022 GetConstantValue(Op0, Result);
1023 Result.IntVal = Result.IntVal.sext(BitWidth);
1024
1025 return;
1026 }
1027 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001028 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001029 GetConstantValue(Op0, Result);
1030 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1031 return;
1032 }
1033 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001034 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001035 GetConstantValue(Op0, Result);
1036 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1037 return;
1038 }
1039 case llvm::Instruction::UIToFP: {
1040 GetConstantValue(Op0, Result);
1041 if (CE->getType()->isFloatTy())
1042 Result.FloatVal =
1043 static_cast<float>(Result.IntVal.roundToDouble());
1044 else if (CE->getType()->isDoubleTy())
1045 Result.DoubleVal = Result.IntVal.roundToDouble();
1046 else if (CE->getType()->isX86_FP80Ty()) {
1047 const uint64_t zero[] = { 0, 0 };
1048 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1049 apf.convertFromAPInt(Result.IntVal,
1050 false,
1051 llvm::APFloat::rmNearestTiesToEven);
1052 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001053 }
Zonr Chang932648d2010-10-13 22:23:56 +08001054 return;
1055 }
1056 case llvm::Instruction::SIToFP: {
1057 GetConstantValue(Op0, Result);
1058 if (CE->getType()->isFloatTy())
1059 Result.FloatVal =
1060 static_cast<float>(Result.IntVal.signedRoundToDouble());
1061 else if (CE->getType()->isDoubleTy())
1062 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1063 else if (CE->getType()->isX86_FP80Ty()) {
1064 const uint64_t zero[] = { 0, 0 };
1065 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1066 apf.convertFromAPInt(Result.IntVal,
1067 true,
1068 llvm::APFloat::rmNearestTiesToEven);
1069 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001070 }
Zonr Chang932648d2010-10-13 22:23:56 +08001071 return;
1072 }
1073 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001074 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001075 case llvm::Instruction::FPToSI: {
1076 uint32_t BitWidth =
1077 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001078
Zonr Chang932648d2010-10-13 22:23:56 +08001079 GetConstantValue(Op0, Result);
1080 if (Op0->getType()->isFloatTy())
1081 Result.IntVal =
1082 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1083 else if (Op0->getType()->isDoubleTy())
1084 Result.IntVal =
1085 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1086 BitWidth);
1087 else if (Op0->getType()->isX86_FP80Ty()) {
1088 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1089 uint64_t V;
1090 bool Ignored;
1091 apf.convertToInteger(&V,
1092 BitWidth,
1093 CE->getOpcode() == llvm::Instruction::FPToSI,
1094 llvm::APFloat::rmTowardZero,
1095 &Ignored);
1096 Result.IntVal = V; // endian?
1097 }
1098 return;
1099 }
1100 case llvm::Instruction::PtrToInt: {
1101 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1102
1103 GetConstantValue(Op0, Result);
1104 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1105 (Result.PointerVal));
1106
1107 return;
1108 }
1109 case llvm::Instruction::IntToPtr: {
1110 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1111
1112 GetConstantValue(Op0, Result);
1113 if (PtrWidth != Result.IntVal.getBitWidth())
1114 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1115 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1116
1117 Result.PointerVal =
1118 llvm::PointerTy(
1119 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1120
1121 return;
1122 }
1123 case llvm::Instruction::BitCast: {
1124 GetConstantValue(Op0, Result);
1125 const llvm::Type *DestTy = CE->getType();
1126
1127 switch (Op0->getType()->getTypeID()) {
1128 case llvm::Type::IntegerTyID: {
1129 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1130 if (DestTy->isFloatTy())
1131 Result.FloatVal = Result.IntVal.bitsToFloat();
1132 else if (DestTy->isDoubleTy())
1133 Result.DoubleVal = Result.IntVal.bitsToDouble();
1134 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001135 }
Zonr Chang932648d2010-10-13 22:23:56 +08001136 case llvm::Type::FloatTyID: {
1137 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1138 Result.IntVal.floatToBits(Result.FloatVal);
1139 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001140 }
Zonr Chang932648d2010-10-13 22:23:56 +08001141 case llvm::Type::DoubleTyID: {
1142 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1143 Result.IntVal.doubleToBits(Result.DoubleVal);
1144 break;
1145 }
1146 case llvm::Type::PointerTyID: {
1147 assert(DestTy->isPointerTy() && "Invalid bitcast");
1148 break; // getConstantValue(Op0) above already converted it
1149 }
1150 default: {
1151 llvm_unreachable("Invalid bitcast operand");
1152 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001153 }
Zonr Chang932648d2010-10-13 22:23:56 +08001154 return;
1155 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001156 case llvm::Instruction::Add:
1157 case llvm::Instruction::FAdd:
1158 case llvm::Instruction::Sub:
1159 case llvm::Instruction::FSub:
1160 case llvm::Instruction::Mul:
1161 case llvm::Instruction::FMul:
1162 case llvm::Instruction::UDiv:
1163 case llvm::Instruction::SDiv:
1164 case llvm::Instruction::URem:
1165 case llvm::Instruction::SRem:
1166 case llvm::Instruction::And:
1167 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001168 case llvm::Instruction::Xor: {
1169 llvm::GenericValue LHS, RHS;
1170 GetConstantValue(Op0, LHS);
1171 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001172
Zonr Chang932648d2010-10-13 22:23:56 +08001173 switch (Op0->getType()->getTypeID()) {
1174 case llvm::Type::IntegerTyID: {
1175 switch (CE->getOpcode()) {
1176 case llvm::Instruction::Add: {
1177 Result.IntVal = LHS.IntVal + RHS.IntVal;
1178 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001179 }
Zonr Chang932648d2010-10-13 22:23:56 +08001180 case llvm::Instruction::Sub: {
1181 Result.IntVal = LHS.IntVal - RHS.IntVal;
1182 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001183 }
Zonr Chang932648d2010-10-13 22:23:56 +08001184 case llvm::Instruction::Mul: {
1185 Result.IntVal = LHS.IntVal * RHS.IntVal;
1186 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001187 }
Zonr Chang932648d2010-10-13 22:23:56 +08001188 case llvm::Instruction::UDiv: {
1189 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1190 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001191 }
Zonr Chang932648d2010-10-13 22:23:56 +08001192 case llvm::Instruction::SDiv: {
1193 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1194 break;
1195 }
1196 case llvm::Instruction::URem: {
1197 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1198 break;
1199 }
1200 case llvm::Instruction::SRem: {
1201 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1202 break;
1203 }
1204 case llvm::Instruction::And: {
1205 Result.IntVal = LHS.IntVal & RHS.IntVal;
1206 break;
1207 }
1208 case llvm::Instruction::Or: {
1209 Result.IntVal = LHS.IntVal | RHS.IntVal;
1210 break;
1211 }
1212 case llvm::Instruction::Xor: {
1213 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1214 break;
1215 }
1216 default: {
1217 llvm_unreachable("Invalid integer opcode");
1218 }
1219 }
1220 break;
1221 }
1222 case llvm::Type::FloatTyID: {
1223 switch (CE->getOpcode()) {
1224 case llvm::Instruction::FAdd: {
1225 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1226 break;
1227 }
1228 case llvm::Instruction::FSub: {
1229 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1230 break;
1231 }
1232 case llvm::Instruction::FMul: {
1233 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1234 break;
1235 }
1236 case llvm::Instruction::FDiv: {
1237 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1238 break;
1239 }
1240 case llvm::Instruction::FRem: {
1241 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1242 break;
1243 }
1244 default: {
1245 llvm_unreachable("Invalid float opcode");
1246 }
1247 }
1248 break;
1249 }
1250 case llvm::Type::DoubleTyID: {
1251 switch (CE->getOpcode()) {
1252 case llvm::Instruction::FAdd: {
1253 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1254 break;
1255 }
1256 case llvm::Instruction::FSub: {
1257 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1258 break;
1259 }
1260 case llvm::Instruction::FMul: {
1261 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1262 break;
1263 }
1264 case llvm::Instruction::FDiv: {
1265 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1266 break;
1267 }
1268 case llvm::Instruction::FRem: {
1269 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1270 break;
1271 }
1272 default: {
1273 llvm_unreachable("Invalid double opcode");
1274 }
1275 }
1276 break;
1277 }
1278 case llvm::Type::X86_FP80TyID:
1279 case llvm::Type::PPC_FP128TyID:
1280 case llvm::Type::FP128TyID: {
1281 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1282 switch (CE->getOpcode()) {
1283 case llvm::Instruction::FAdd: {
1284 apfLHS.add(llvm::APFloat(RHS.IntVal),
1285 llvm::APFloat::rmNearestTiesToEven);
1286 break;
1287 }
1288 case llvm::Instruction::FSub: {
1289 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1290 llvm::APFloat::rmNearestTiesToEven);
1291 break;
1292 }
1293 case llvm::Instruction::FMul: {
1294 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1295 llvm::APFloat::rmNearestTiesToEven);
1296 break;
1297 }
1298 case llvm::Instruction::FDiv: {
1299 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1300 llvm::APFloat::rmNearestTiesToEven);
1301 break;
1302 }
1303 case llvm::Instruction::FRem: {
1304 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1305 llvm::APFloat::rmNearestTiesToEven);
1306 break;
1307 }
1308 default: {
1309 llvm_unreachable("Invalid long double opcode");
1310 }
1311 }
1312 Result.IntVal = apfLHS.bitcastToAPInt();
1313 break;
1314 }
1315 default: {
1316 llvm_unreachable("Bad add type!");
1317 }
1318 } // End switch (Op0->getType()->getTypeID())
1319 return;
1320 }
1321 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001322 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001323 }
1324 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001325
1326 std::string msg;
1327 llvm::raw_string_ostream Msg(msg);
1328 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001329 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001330 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001331
1332 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001333 case llvm::Type::FloatTyID: {
1334 Result.FloatVal =
1335 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001336 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001337 }
1338 case llvm::Type::DoubleTyID: {
1339 Result.DoubleVal =
1340 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001341 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001342 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001343 case llvm::Type::X86_FP80TyID:
1344 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001345 case llvm::Type::PPC_FP128TyID: {
1346 Result.IntVal =
1347 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001348 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001349 }
1350 case llvm::Type::IntegerTyID: {
1351 Result.IntVal =
1352 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001353 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001354 }
1355 case llvm::Type::PointerTyID: {
1356 switch (C->getValueID()) {
1357 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001358 Result.PointerVal = NULL;
1359 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001360 }
1361 case llvm::Value::FunctionVal: {
1362 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1363 Result.PointerVal =
1364 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001365 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001366 }
1367 case llvm::Value::GlobalVariableVal: {
1368 const llvm::GlobalVariable *GV =
1369 static_cast<const llvm::GlobalVariable*>(C);
1370 Result.PointerVal =
1371 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001372 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001373 }
1374 case llvm::Value::BlockAddressVal: {
1375 assert(false && "JIT does not support address-of-label yet!");
1376 }
1377 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001378 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001379 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001380 }
1381 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001382 }
1383 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001384 std::string msg;
1385 llvm::raw_string_ostream Msg(msg);
1386 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001387 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001388 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001389 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001390 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001391 return;
1392 }
1393
Zonr Chang932648d2010-10-13 22:23:56 +08001394 // Stores the data in @Val of type @Ty at address @Addr.
1395 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001396 const llvm::Type *Ty) {
1397 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1398
Zonr Chang932648d2010-10-13 22:23:56 +08001399 switch (Ty->getTypeID()) {
1400 case llvm::Type::IntegerTyID: {
1401 const llvm::APInt &IntVal = Val.IntVal;
1402 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1403 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001404
Zonr Chang932648d2010-10-13 22:23:56 +08001405 const uint8_t *Src =
1406 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001407
Zonr Chang932648d2010-10-13 22:23:56 +08001408 if (llvm::sys::isLittleEndianHost()) {
1409 // Little-endian host - the source is ordered from LSB to MSB.
1410 // Order the destination from LSB to MSB: Do a straight copy.
1411 memcpy(Addr, Src, StoreBytes);
1412 } else {
1413 // Big-endian host - the source is an array of 64 bit words
1414 // ordered from LSW to MSW.
1415 //
1416 // Each word is ordered from MSB to LSB.
1417 //
1418 // Order the destination from MSB to LSB:
1419 // Reverse the word order, but not the bytes in a word.
1420 unsigned int i = StoreBytes;
1421 while (i > sizeof(uint64_t)) {
1422 i -= sizeof(uint64_t);
1423 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1424 Src,
1425 sizeof(uint64_t));
1426 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001427 }
Zonr Chang932648d2010-10-13 22:23:56 +08001428 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001429 }
1430 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001431 }
1432 case llvm::Type::FloatTyID: {
1433 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001434 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001435 }
1436 case llvm::Type::DoubleTyID: {
1437 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001438 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001439 }
1440 case llvm::Type::X86_FP80TyID: {
1441 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001442 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001443 }
1444 case llvm::Type::PointerTyID: {
1445 // Ensure 64 bit target pointers are fully initialized on 32 bit
1446 // hosts.
1447 if (StoreBytes != sizeof(llvm::PointerTy))
1448 memset(Addr, 0, StoreBytes);
1449 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001450 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001451 }
1452 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001453 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001454 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001455 }
1456
Zonr Chang932648d2010-10-13 22:23:56 +08001457 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1458 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1459 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001460
1461 return;
1462 }
1463
Zonr Chang932648d2010-10-13 22:23:56 +08001464 // Recursive function to apply a @Constant value into the specified memory
1465 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001466 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001467 switch (C->getValueID()) {
1468 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001469 // Nothing to do
1470 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001471 }
1472 case llvm::Value::ConstantVectorVal: {
1473 // dynamic cast may hurt performance
1474 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001475
Zonr Chang932648d2010-10-13 22:23:56 +08001476 unsigned int ElementSize = mpTD->getTypeAllocSize
1477 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001478
Zonr Chang932648d2010-10-13 22:23:56 +08001479 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1480 InitializeConstantToMemory(
1481 CP->getOperand(i),
1482 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001483 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001484 }
1485 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001486 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1487 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001488 }
1489 case llvm::Value::ConstantArrayVal: {
1490 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1491 unsigned int ElementSize = mpTD->getTypeAllocSize
1492 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001493
Zonr Chang932648d2010-10-13 22:23:56 +08001494 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1495 InitializeConstantToMemory(
1496 CPA->getOperand(i),
1497 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1498 break;
1499 }
1500 case llvm::Value::ConstantStructVal: {
1501 const llvm::ConstantStruct *CPS =
1502 static_cast<const llvm::ConstantStruct*>(C);
1503 const llvm::StructLayout *SL = mpTD->getStructLayout
1504 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001505
Zonr Chang932648d2010-10-13 22:23:56 +08001506 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1507 InitializeConstantToMemory(
1508 CPS->getOperand(i),
1509 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1510 break;
1511 }
1512 default: {
1513 if (C->getType()->isFirstClassType()) {
1514 llvm::GenericValue Val;
1515 GetConstantValue(C, Val);
1516 StoreValueToMemory(Val, Addr, C->getType());
1517 } else {
1518 llvm_unreachable("Unknown constant type to initialize memory "
1519 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001520 }
1521 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001522 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001523 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001524 return;
1525 }
1526
1527 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001528 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001529 return;
1530
Zonr Chang932648d2010-10-13 22:23:56 +08001531 // Constant pool address resolution is handled by the target itself in ARM
1532 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001533#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001534 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1535 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001536
Zonr Chang932648d2010-10-13 22:23:56 +08001537 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001538 return;
1539
1540 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1541 unsigned Align = MCP->getConstantPoolAlignment();
1542
1543 mpConstantPoolBase = allocateSpace(Size, Align);
1544 mpConstantPool = MCP;
1545
Zonr Chang932648d2010-10-13 22:23:56 +08001546 if (mpConstantPoolBase == NULL)
1547 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001548
1549 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001550 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001551 llvm::MachineConstantPoolEntry CPE = Constants[i];
1552 unsigned AlignMask = CPE.getAlignment() - 1;
1553 Offset = (Offset + AlignMask) & ~AlignMask;
1554
1555 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1556 mConstPoolAddresses.push_back(CAddr);
1557
Zonr Chang932648d2010-10-13 22:23:56 +08001558 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001559 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001560 ("Initialize memory with machine specific constant pool"
1561 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001562
1563 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1564
1565 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1566 Offset += mpTD->getTypeAllocSize(Ty);
1567 }
1568#endif
1569 return;
1570 }
1571
1572 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001573 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001574 return;
1575
Zonr Chang932648d2010-10-13 22:23:56 +08001576 const std::vector<llvm::MachineJumpTableEntry> &JT =
1577 MJTI->getJumpTables();
1578 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001579 return;
1580
1581 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001582 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001583 NumEntries += JT[i].MBBs.size();
1584
1585 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1586
Zonr Chang932648d2010-10-13 22:23:56 +08001587 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001588 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001589 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001590
1591 return;
1592 }
1593
1594 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001595 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001596 return;
1597
Zonr Chang932648d2010-10-13 22:23:56 +08001598 const std::vector<llvm::MachineJumpTableEntry> &JT =
1599 MJTI->getJumpTables();
1600 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001601 return;
1602
Zonr Chang932648d2010-10-13 22:23:56 +08001603 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1604 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1605 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001606
Zonr Chang932648d2010-10-13 22:23:56 +08001607 // For each jump table, map each target in the jump table to the
1608 // address of an emitted MachineBasicBlock.
1609 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1610 for (int i = 0, ie = JT.size(); i != ie; i++) {
1611 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1612 // Store the address of the basic block for this jump table slot in the
1613 // memory we allocated for the jump table in 'initJumpTableInfo'
1614 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001615 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1616 }
1617 }
1618
Zonr Chang932648d2010-10-13 22:23:56 +08001619 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1620 bool MayNeedFarStub) {
1621 switch (V->getValueID()) {
1622 case llvm::Value::FunctionVal: {
1623 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001624
Zonr Chang932648d2010-10-13 22:23:56 +08001625 // If we have code, go ahead and return that.
1626 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1627 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001628
Zonr Chang932648d2010-10-13 22:23:56 +08001629 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1630 // Return the function stub if it's already created.
1631 // We do this first so that:
1632 // we're returning the same address for the function as any
1633 // previous call.
1634 //
1635 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1636 // guaranteed to be close enough to call.
1637 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001638
Zonr Chang932648d2010-10-13 22:23:56 +08001639 // If we know the target can handle arbitrary-distance calls, try to
1640 // return a direct pointer.
1641 if (!MayNeedFarStub) {
1642 //
1643 // x86_64 architecture may encounter the bug:
1644 // http://llvm.org/bugs/show_bug.cgi?id=5201
1645 // which generate instruction "call" instead of "callq".
1646 //
1647 // And once the real address of stub is greater than 64-bit
1648 // long, the replacement will truncate to 32-bit resulting a
1649 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001650#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001651 // If this is an external function pointer, we can force the JIT
1652 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001653 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1654 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1655 // Changing to false because wanting to allow later calls to
1656 // mpTJI->relocate() without aborting. For caching purpose
1657 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001658#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001659 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001660
Zonr Chang932648d2010-10-13 22:23:56 +08001661 // Otherwise, we may need a to emit a stub, and, conservatively, we
1662 // always do so.
1663 return GetLazyFunctionStub(F);
1664 break;
1665 }
1666 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001667 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1668 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001669 }
1670 case llvm::Value::GlobalAliasVal: {
1671 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1672 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001673
Zonr Chang932648d2010-10-13 22:23:56 +08001674 switch (GV->getValueID()) {
1675 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001676 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001677 // code-gen'd?
1678 return GetPointerToFunction(
1679 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001680 /* AbortOnFailure = */false);
1681 // Changing to false because wanting to allow later calls to
1682 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001683 break;
1684 }
1685 case llvm::Value::GlobalVariableVal: {
1686 if (void *P = mGlobalAddressMap[GV])
1687 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001688
Zonr Chang932648d2010-10-13 22:23:56 +08001689 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1690 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001691
Zonr Chang932648d2010-10-13 22:23:56 +08001692 return mGlobalAddressMap[GV];
1693 break;
1694 }
1695 case llvm::Value::GlobalAliasVal: {
1696 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001697 }
1698 }
1699 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001700 }
1701 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001702 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001703 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001704 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001705 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001706 }
1707
Zonr Chang932648d2010-10-13 22:23:56 +08001708 // If the specified function has been code-gen'd, return a pointer to the
1709 // function. If not, compile it, or use a stub to implement lazy compilation
1710 // if available.
1711 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1712 // If we have already code generated the function, just return the
1713 // address.
1714 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001715 return Addr;
1716
Zonr Chang932648d2010-10-13 22:23:56 +08001717 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001718 return GetLazyFunctionStub(F);
1719 }
1720
Zonr Chang932648d2010-10-13 22:23:56 +08001721 typedef llvm::DenseMap<const llvm::Function*,
1722 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001723 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1724
Zonr Chang932648d2010-10-13 22:23:56 +08001725 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001726 return mFunctionToLazyStubMap.lookup(F);
1727 }
1728
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001729 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001730 void *GetLazyFunctionStub(llvm::Function *F) {
1731 // If we already have a lazy stub for this function, recycle it.
1732 void *&Stub = mFunctionToLazyStubMap[F];
1733 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001734 return Stub;
1735
Zonr Chang932648d2010-10-13 22:23:56 +08001736 // In any cases, we should NOT resolve function at runtime (though we are
1737 // able to). We resolve this right now.
1738 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001739 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1740 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1741 // Changing to false because wanting to allow later calls to
1742 // mpTJI->relocate() without aborting. For caching purpose
1743 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001744
Zonr Chang932648d2010-10-13 22:23:56 +08001745 // Codegen a new stub, calling the actual address of the external
1746 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001747 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1748 startGVStub(F, SL.Size, SL.Alignment);
1749 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1750 finishGVStub();
1751
Zonr Chang932648d2010-10-13 22:23:56 +08001752 // We really want the address of the stub in the GlobalAddressMap for the
1753 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001754 UpdateGlobalMapping(F, Stub);
1755
Zonr Chang932648d2010-10-13 22:23:56 +08001756 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001757 PendingFunctions.insert(F);
1758 else
Zonr Chang932648d2010-10-13 22:23:56 +08001759 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1760 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001761
1762 return Stub;
1763 }
1764
Zonr Chang932648d2010-10-13 22:23:56 +08001765 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1766 void *Addr = GetPointerToGlobalIfAvailable(F);
1767 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001768 return Addr;
1769
1770 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1771 "Internal error: only external defined function routes here!");
1772
Zonr Chang932648d2010-10-13 22:23:56 +08001773 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001774 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001775 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001776
Zonr Chang932648d2010-10-13 22:23:56 +08001777 // If we resolved the symbol to a null address (eg. a weak external)
1778 // return a null pointer let the application handle it.
1779 if (Addr == NULL) {
1780 if (AbortOnFailure)
1781 llvm::report_fatal_error("Could not resolve external function "
1782 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001783 else
1784 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001785 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001786
1787 AddGlobalMapping(F, Addr);
1788
1789 return Addr;
1790 }
1791
Zonr Chang932648d2010-10-13 22:23:56 +08001792 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001793 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001794 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001795 return Addr;
1796
Zonr Chang932648d2010-10-13 22:23:56 +08001797 if (mpSymbolLookupFn)
1798 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001799 return Addr;
1800
Zonr Chang932648d2010-10-13 22:23:56 +08001801 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001802 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001803 "' which could not be resolved!");
1804
1805 return NULL;
1806 }
1807
Zonr Chang932648d2010-10-13 22:23:56 +08001808 // Return the address of the specified global variable, possibly emitting it
1809 // to memory if needed. This is used by the Emitter.
1810 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1811 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1812 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001813 return Ptr;
1814
Zonr Chang932648d2010-10-13 22:23:56 +08001815 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1816 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001817 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1818 AddGlobalMapping(GV, Ptr);
1819 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001820 // If the global hasn't been emitted to memory yet, allocate space and
1821 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001822 Ptr = GetMemoryForGV(GV);
1823 AddGlobalMapping(GV, Ptr);
1824 EmitGlobalVariable(GV);
1825 }
1826
1827 return Ptr;
1828 }
1829
Zonr Chang932648d2010-10-13 22:23:56 +08001830 // This method abstracts memory allocation of global variable so that the
1831 // JIT can allocate thread local variables depending on the target.
1832 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1833 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001834
Zonr Chang932648d2010-10-13 22:23:56 +08001835 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001836 size_t S = mpTD->getTypeAllocSize(GlobalType);
1837 size_t A = mpTD->getPreferredAlignment(GV);
1838
Zonr Chang932648d2010-10-13 22:23:56 +08001839 if (GV->isThreadLocal()) {
1840 // We can support TLS by
1841 //
1842 // Ptr = TJI.allocateThreadLocalMemory(S);
1843 //
1844 // But I tend not to.
1845 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001846 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001847 ("Compilation of Thread Local Storage (TLS) is disabled!");
1848
Zonr Chang932648d2010-10-13 22:23:56 +08001849 } else if (mpTJI->allocateSeparateGVMemory()) {
1850 if (A <= 8) {
1851 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001852 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001853 // Allocate (S + A) bytes of memory, then use an aligned pointer
1854 // within that space.
1855 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001856 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001857 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1858 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001859 }
1860 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001861 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001862 }
1863
1864 return Ptr;
1865 }
1866
1867 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001868 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001869
Zonr Chang932648d2010-10-13 22:23:56 +08001870 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001871 llvm::report_fatal_error
1872 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001873
Zonr Chang932648d2010-10-13 22:23:56 +08001874 if (GA == NULL) {
1875 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001876 GA = GetMemoryForGV(GV);
1877 AddGlobalMapping(GV, GA);
1878 }
1879
1880 InitializeConstantToMemory(GV->getInitializer(), GA);
1881
Zonr Chang932648d2010-10-13 22:23:56 +08001882 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001883 return;
1884 }
1885
1886 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1887 > GlobalToIndirectSymMapTy;
1888 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1889
Zonr Chang932648d2010-10-13 22:23:56 +08001890 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1891 // Make sure GV is emitted first, and create a stub containing the fully
1892 // resolved address.
1893 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001894
Zonr Chang932648d2010-10-13 22:23:56 +08001895 // If we already have a stub for this global variable, recycle it.
1896 void *&IndirectSym = GlobalToIndirectSymMap[V];
1897 // Otherwise, codegen a new indirect symbol.
1898 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001899 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1900
1901 return IndirectSym;
1902 }
1903
Zonr Chang932648d2010-10-13 22:23:56 +08001904 // This is the equivalent of FunctionToLazyStubMap for external functions.
1905 //
1906 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1907 // It's actually here to make it more likely that far calls
1908 // succeed, but no single stub can guarantee that. I'll
1909 // remove this in a subsequent checkin when I actually fix
1910 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001911 std::map<void*, void*> ExternalFnToStubMap;
1912
Zonr Chang932648d2010-10-13 22:23:56 +08001913 // Return a stub for the function at the specified address.
1914 void *GetExternalFunctionStub(void *FnAddr) {
1915 void *&Stub = ExternalFnToStubMap[FnAddr];
1916 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001917 return Stub;
1918
1919 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1920 startGVStub(0, SL.Size, SL.Alignment);
1921 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1922 finishGVStub();
1923
1924 return Stub;
1925 }
1926
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001927#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001928 const llvm::MCAsmInfo *mpAsmInfo;
1929 const llvm::MCDisassembler *mpDisassmbler;
1930 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001931
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001932 class BufferMemoryObject : public llvm::MemoryObject {
1933 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001934 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001935 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001936
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001937 public:
1938 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1939 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001940
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001941 uint64_t getBase() const { return 0; }
1942 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001943
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001944 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001945 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001946 return -1;
1947 *Byte = mBytes[Addr];
1948 return 0;
1949 }
1950 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001951
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08001952 public:
Zonr Chang932648d2010-10-13 22:23:56 +08001953 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001954 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001955 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001956#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001957 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001958 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1959 ErrorInfo,
1960 llvm::raw_fd_ostream::F_Append);
1961 if (!ErrorInfo.empty()) { // some errors occurred
1962 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001963 delete OS;
1964 return;
1965 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001966#else
1967 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001968#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001969 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1970 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001971
Zonr Chang932648d2010-10-13 22:23:56 +08001972 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001973 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001974 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001975 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001976 if (mpIP == NULL)
1977 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1978 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001979
Zonr Chang932648d2010-10-13 22:23:56 +08001980 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1981 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001982 uint64_t Size;
1983 uint64_t Index;
1984
Zonr Chang932648d2010-10-13 22:23:56 +08001985 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001986 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001987
Zonr Chang932648d2010-10-13 22:23:56 +08001988 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1989 /* REMOVED */ llvm::nulls())) {
1990 (*OS).indent(4)
1991 .write("0x", 2)
1992 .write_hex((uint32_t) Start + Index)
1993 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001994 mpIP->printInst(&Inst, *OS);
1995 *OS << "\n";
1996 } else {
1997 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08001998 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001999 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002000 }
2001
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002002 *OS << "\n";
2003 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002004
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002005#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08002006 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002007 OS->close();
2008 delete OS;
2009#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002010 return;
2011 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002012#else
Zonr Chang932648d2010-10-13 22:23:56 +08002013 inline void Disassemble(const std::string &Name, uint8_t *Start,
2014 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002015 return;
2016 }
Zonr Chang932648d2010-10-13 22:23:56 +08002017#endif // defined(USE_DISASSEMBLER)
2018
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002019 private:
Zonr Chang932648d2010-10-13 22:23:56 +08002020 // Resolver to undefined symbol in CodeEmitter
2021 BCCSymbolLookupFn mpSymbolLookupFn;
2022 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002023
2024 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002025 // Will take the ownership of @MemMgr
2026 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2027 : mpMemMgr(pMemMgr),
2028 mpTarget(NULL),
2029 mpTJI(NULL),
2030 mpTD(NULL),
2031 mpCurEmitFunction(NULL),
2032 mpConstantPool(NULL),
2033 mpJumpTable(NULL),
2034 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002035#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002036 mpAsmInfo(NULL),
2037 mpDisassmbler(NULL),
2038 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002039#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002040 mpSymbolLookupFn(NULL),
2041 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002042 return;
2043 }
2044
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002045 inline global_addresses_const_iterator global_address_begin() const {
2046 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002047 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002048 inline global_addresses_const_iterator global_address_end() const {
2049 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002050 }
2051
Logan824dd0a2010-11-20 01:45:54 +08002052 std::vector<oBCCRelocEntry> const &getCachingRelocations() const {
2053 return mCachingRelocations;
2054 }
2055
Zonr Chang932648d2010-10-13 22:23:56 +08002056 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002057 mpSymbolLookupFn = pFn;
2058 mpSymbolLookupContext = pContext;
2059 return;
2060 }
2061
Zonr Chang932648d2010-10-13 22:23:56 +08002062 void setTargetMachine(llvm::TargetMachine &TM) {
2063 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002064 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002065 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002066 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002067 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002068 mpTD = TM.getTargetData();
2069
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002070 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2071
2072 return;
2073 }
2074
Zonr Chang932648d2010-10-13 22:23:56 +08002075 // This callback is invoked when the specified function is about to be code
2076 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002077 void startFunction(llvm::MachineFunction &F) {
2078 uintptr_t ActualSize = 0;
2079
2080 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002081
2082 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2083 // MachineCodeEmitter, which is the super class of the class
2084 // JITCodeEmitter.
2085 //
2086 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2087 // allocated for this code buffer.
2088 //
2089 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2090 // code. This is guranteed to be in the range
2091 // [BufferBegin, BufferEnd]. If this pointer is at
2092 // BufferEnd, it will never move due to code emission, and
2093 // all code emission requests will be ignored (this is the
2094 // buffer overflow condition).
2095 BufferBegin = CurBufferPtr =
2096 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002097 BufferEnd = BufferBegin + ActualSize;
2098
Zonr Chang932648d2010-10-13 22:23:56 +08002099 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002100 mpCurEmitFunction = new EmittedFunctionCode();
2101 mpCurEmitFunction->FunctionBody = BufferBegin;
2102
Zonr Chang932648d2010-10-13 22:23:56 +08002103 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002104 emitAlignment(16);
2105
2106 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002107 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002108 initJumpTableInfo(MJTI);
2109
Zonr Chang932648d2010-10-13 22:23:56 +08002110 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002111 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2112
2113 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2114
2115 mpCurEmitFunction->Code = CurBufferPtr;
2116
2117 mMBBLocations.clear();
2118
2119 return;
2120 }
2121
Zonr Chang932648d2010-10-13 22:23:56 +08002122 // This callback is invoked when the specified function has finished code
2123 // generation. If a buffer overflow has occurred, this method returns true
2124 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002125 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002126 if (CurBufferPtr == BufferEnd) {
2127 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002128 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2129 return false;
2130 }
2131
Zonr Chang932648d2010-10-13 22:23:56 +08002132 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002133 emitJumpTableInfo(MJTI);
2134
Zonr Chang932648d2010-10-13 22:23:56 +08002135 // FnStart is the start of the text, not the start of the constant pool
2136 // and other per-function data.
2137 uint8_t *FnStart =
2138 reinterpret_cast<uint8_t*>(
2139 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002140
Zonr Chang932648d2010-10-13 22:23:56 +08002141 // FnEnd is the end of the function's machine code.
2142 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002143
Zonr Chang932648d2010-10-13 22:23:56 +08002144 if (!mRelocations.empty()) {
Logan824dd0a2010-11-20 01:45:54 +08002145 ptrdiff_t BufferOffset = BufferBegin - mpMemMgr->getCodeMemBase();
2146
Zonr Chang932648d2010-10-13 22:23:56 +08002147 // Resolve the relocations to concrete pointers.
2148 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2149 llvm::MachineRelocation &MR = mRelocations[i];
2150 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002151
Zonr Chang932648d2010-10-13 22:23:56 +08002152 if (!MR.letTargetResolve()) {
2153 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002154 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Logan824dd0a2010-11-20 01:45:54 +08002155
2156 if (MR.mayNeedFarStub()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002157 ResultPtr = GetExternalFunctionStub(ResultPtr);
Logan634bd832010-11-20 09:00:36 +08002158 fprintf(stderr, "reloc: external sym + far\t\toff=%d\taddr=%p\n",
2159 MR.getMachineCodeOffset() + BufferOffset,
2160 ResultPtr);
2161 } else {
2162 fprintf(stderr, "reloc: external sym\t\toff=%d\taddr=%p\n",
2163 MR.getMachineCodeOffset() + BufferOffset,
2164 ResultPtr);
Logan824dd0a2010-11-20 01:45:54 +08002165 }
2166
Zonr Chang932648d2010-10-13 22:23:56 +08002167 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002168 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2169 BufferBegin
2170 + MR.getMachineCodeOffset(),
2171 MR.mayNeedFarStub());
Logan634bd832010-11-20 09:00:36 +08002172 fprintf(stderr, "reloc: is global var\t\toff=%d\taddr=%p\n",
2173 MR.getMachineCodeOffset() + BufferOffset,
2174 ResultPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002175 } else if (MR.isIndirectSymbol()) {
2176 ResultPtr =
2177 GetPointerToGVIndirectSym(
2178 MR.getGlobalValue(),
2179 BufferBegin + MR.getMachineCodeOffset());
Logan634bd832010-11-20 09:00:36 +08002180 fprintf(stderr, "reloc: is indirect symbol\t\toff=%d\taddr=%p\n",
2181 MR.getMachineCodeOffset() + BufferOffset,
2182 ResultPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002183 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002184 ResultPtr =
2185 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Logan634bd832010-11-20 09:00:36 +08002186 fprintf(stderr, "reloc: is basic block\t\toff=%d\taddr=%p\n",
2187 MR.getMachineCodeOffset() + BufferOffset,
2188 ResultPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002189 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002190 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002191 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Logan634bd832010-11-20 09:00:36 +08002192 fprintf(stderr, "reloc: is const pool entry\t\toff=%d\taddr=%p\n",
2193 MR.getMachineCodeOffset() + BufferOffset,
2194 ResultPtr);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002195 } else {
2196 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2197 ResultPtr =
2198 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
Logan634bd832010-11-20 09:00:36 +08002199 fprintf(stderr, "reloc: is jump table\t\toff=%d\taddr=%p\n",
2200 MR.getMachineCodeOffset() + BufferOffset,
2201 ResultPtr);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002202 }
2203
Logan824dd0a2010-11-20 01:45:54 +08002204 if (!MR.isExternalSymbol() || MR.mayNeedFarStub()) {
2205 // TODO(logan): Cache external symbol relocation entry.
2206 // Currently, we are not caching them. But since Android
2207 // system is using prelink, it is not a problem.
2208
2209 // Cache the relocation result address
2210 mCachingRelocations.push_back(
Logan634bd832010-11-20 09:00:36 +08002211 oBCCRelocEntry(MR.getRelocationType(),
2212 MR.getMachineCodeOffset() + BufferOffset,
Logan824dd0a2010-11-20 01:45:54 +08002213 ResultPtr));
2214 }
2215
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002216 MR.setResultPointer(ResultPtr);
2217 }
2218 }
2219
2220 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2221 mpMemMgr->getGOTBase());
2222 }
2223
2224 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002225 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2226 // global variables that were referenced in the relocations.
2227 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002228 return false;
2229
Zonr Chang932648d2010-10-13 22:23:56 +08002230 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002231 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2232 BufferBegin = CurBufferPtr = 0;
2233
Zonr Chang932648d2010-10-13 22:23:56 +08002234 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002235 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2236 mpCurEmitFunction = NULL;
2237
2238 mRelocations.clear();
2239 mConstPoolAddresses.clear();
2240
Zonr Chang932648d2010-10-13 22:23:56 +08002241 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002242 mpMMI->EndFunction();
2243
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002244 updateFunctionStub(F.getFunction());
2245
Zonr Chang932648d2010-10-13 22:23:56 +08002246 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002247 mpMemMgr->setMemoryExecutable();
2248
2249 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2250
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002251 return false;
2252 }
2253
Zonr Chang932648d2010-10-13 22:23:56 +08002254 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002255 unsigned Alignment) {
2256 mpSavedBufferBegin = BufferBegin;
2257 mpSavedBufferEnd = BufferEnd;
2258 mpSavedCurBufferPtr = CurBufferPtr;
2259
2260 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2261 Alignment);
2262 BufferEnd = BufferBegin + StubSize + 1;
2263
2264 return;
2265 }
2266
Zonr Chang932648d2010-10-13 22:23:56 +08002267 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002268 mpSavedBufferBegin = BufferBegin;
2269 mpSavedBufferEnd = BufferEnd;
2270 mpSavedCurBufferPtr = CurBufferPtr;
2271
Zonr Chang932648d2010-10-13 22:23:56 +08002272 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002273 BufferEnd = BufferBegin + StubSize + 1;
2274
2275 return;
2276 }
2277
2278 void finishGVStub() {
2279 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2280
Zonr Chang932648d2010-10-13 22:23:56 +08002281 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002282 BufferBegin = mpSavedBufferBegin;
2283 BufferEnd = mpSavedBufferEnd;
2284 CurBufferPtr = mpSavedCurBufferPtr;
2285
2286 return;
2287 }
2288
Zonr Chang932648d2010-10-13 22:23:56 +08002289 // Allocates and fills storage for an indirect GlobalValue, and returns the
2290 // address.
2291 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002292 const uint8_t *Buffer, size_t Size,
2293 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002294 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002295 memcpy(IndGV, Buffer, Size);
2296 return IndGV;
2297 }
2298
Zonr Chang932648d2010-10-13 22:23:56 +08002299 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002300 void emitLabel(llvm::MCSymbol *Label) {
2301 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002302 return;
2303 }
2304
Zonr Chang932648d2010-10-13 22:23:56 +08002305 // Allocate memory for a global. Unlike allocateSpace, this method does not
2306 // allocate memory in the current output buffer, because a global may live
2307 // longer than the current function.
2308 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2309 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002310 return mpMemMgr->allocateGlobal(Size, Alignment);
2311 }
2312
Zonr Chang932648d2010-10-13 22:23:56 +08002313 // This should be called by the target when a new basic block is about to be
2314 // emitted. This way the MCE knows where the start of the block is, and can
2315 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002316 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002317 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002318 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2319 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2320 return;
2321 }
2322
Zonr Chang932648d2010-10-13 22:23:56 +08002323 // Whenever a relocatable address is needed, it should be noted with this
2324 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002325 void addRelocation(const llvm::MachineRelocation &MR) {
2326 mRelocations.push_back(MR);
2327 return;
2328 }
2329
Zonr Chang932648d2010-10-13 22:23:56 +08002330 // Return the address of the @Index entry in the constant pool that was
2331 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002332 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2333 assert(Index < mpConstantPool->getConstants().size() &&
2334 "Invalid constant pool index!");
2335 return mConstPoolAddresses[Index];
2336 }
2337
Zonr Chang932648d2010-10-13 22:23:56 +08002338 // Return the address of the jump table with index @Index in the function
2339 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002340 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002341 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002342 mpJumpTable->getJumpTables();
2343
Zonr Chang932648d2010-10-13 22:23:56 +08002344 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002345
2346 unsigned int Offset = 0;
2347 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2348
Zonr Chang932648d2010-10-13 22:23:56 +08002349 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002350 Offset += JT[i].MBBs.size();
2351 Offset *= EntrySize;
2352
Zonr Chang932648d2010-10-13 22:23:56 +08002353 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002354 }
2355
Zonr Chang932648d2010-10-13 22:23:56 +08002356 // Return the address of the specified MachineBasicBlock, only usable after
2357 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002358 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2359 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002360 mMBBLocations[MBB->getNumber()] &&
2361 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002362 return mMBBLocations[MBB->getNumber()];
2363 }
2364
Zonr Chang932648d2010-10-13 22:23:56 +08002365 // Return the address of the specified LabelID, only usable after the
2366 // LabelID has been emitted.
2367 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002368 assert(mLabelLocations.count(Label) && "Label not emitted!");
2369 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002370 }
2371
Zonr Chang932648d2010-10-13 22:23:56 +08002372 // Specifies the MachineModuleInfo object. This is used for exception
2373 // handling purposes.
2374 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002375 mpMMI = Info;
2376 return;
2377 }
2378
Zonr Chang932648d2010-10-13 22:23:56 +08002379 void updateFunctionStub(const llvm::Function *F) {
2380 // Get the empty stub we generated earlier.
2381 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002382 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002383 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002384 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002385 else
2386 return;
2387
Zonr Chang932648d2010-10-13 22:23:56 +08002388 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002389
2390 assert(Addr != Stub &&
2391 "Function must have non-stub address to be updated.");
2392
Zonr Chang932648d2010-10-13 22:23:56 +08002393 // Tell the target jit info to rewrite the stub at the specified address,
2394 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002395 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2396 startGVStub(Stub, SL.Size);
2397 mpTJI->emitFunctionStub(F, Addr, *this);
2398 finishGVStub();
2399
Zonr Chang932648d2010-10-13 22:23:56 +08002400 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2401 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002402
2403 PendingFunctions.erase(I);
2404
2405 return;
2406 }
2407
Zonr Chang932648d2010-10-13 22:23:56 +08002408 // Once you finish the compilation on a translation unit, you can call this
2409 // function to recycle the memory (which is used at compilation time and not
2410 // needed for runtime).
2411 //
2412 // NOTE: You should not call this funtion until the code-gen passes for a
2413 // given module is done. Otherwise, the results is undefined and may
2414 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002415 void releaseUnnecessary() {
2416 mMBBLocations.clear();
2417 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002418 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002419 mFunctionToLazyStubMap.clear();
2420 GlobalToIndirectSymMap.clear();
2421 ExternalFnToStubMap.clear();
2422 PendingFunctions.clear();
2423
2424 return;
2425 }
2426
2427 void reset() {
2428 releaseUnnecessary();
2429
2430 mpSymbolLookupFn = NULL;
2431 mpSymbolLookupContext = NULL;
2432
2433 mpTJI = NULL;
2434 mpTD = NULL;
2435
Zonr Chang932648d2010-10-13 22:23:56 +08002436 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2437 E = mEmittedFunctions.end();
2438 I != E;
2439 I++)
2440 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002441 delete I->second;
2442 mEmittedFunctions.clear();
2443
2444 mpMemMgr->reset();
2445
2446 return;
2447 }
2448
Zonr Chang932648d2010-10-13 22:23:56 +08002449 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002450 return lookup( llvm::StringRef(Name) );
2451 }
2452
Zonr Chang932648d2010-10-13 22:23:56 +08002453 void *lookup(const llvm::StringRef &Name) {
2454 EmittedFunctionsMapTy::const_iterator I =
2455 mEmittedFunctions.find(Name.str());
2456 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002457 return NULL;
2458 else
2459 return I->second->Code;
2460 }
2461
Zonr Chang932648d2010-10-13 22:23:56 +08002462 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002463 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002464 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002465 int functionCount = mEmittedFunctions.size();
2466
Zonr Chang932648d2010-10-13 22:23:56 +08002467 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002468 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002469 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002470 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002471 if (functions)
2472 for (EmittedFunctionsMapTy::const_iterator
2473 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2474 (I != E) && (functionCount > 0);
2475 I++, functionCount--)
2476 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002477
2478 return;
2479 }
2480
Zonr Chang932648d2010-10-13 22:23:56 +08002481 void getFunctionBinary(BCCchar *label,
2482 BCCvoid **base,
2483 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002484 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002485 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002486 *base = NULL;
2487 *length = 0;
2488 } else {
2489 *base = I->second->Code;
2490 *length = I->second->Size;
2491 }
2492 return;
2493 }
2494
2495 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002496 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002497#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002498 delete mpAsmInfo;
2499 delete mpDisassmbler;
2500 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002501#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002502 return;
2503 }
Zonr Chang932648d2010-10-13 22:23:56 +08002504 };
2505 // End of Class CodeEmitter
2506 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002507
Zonr Chang932648d2010-10-13 22:23:56 +08002508 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002509 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002510 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002511 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2512 return mCodeEmitter.get();
2513 }
2514
2515 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002516 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002517
Zonr Chang932648d2010-10-13 22:23:56 +08002518 llvm::LLVMContext *mContext;
2519 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002520
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002521 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002522
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002523 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002524 Compiler()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002525 : mNeverCache(true),
2526 mCacheNew(false),
2527 mCacheFd(-1),
2528 mCacheMapAddr(NULL),
2529 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002530 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002531 mCacheDiff(0),
2532 mCodeDataAddr(NULL),
2533 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002534 mpSymbolLookupContext(NULL),
2535 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002536 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002537 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002538 llvm::remove_fatal_error_handler();
2539 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002540 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002541 return;
2542 }
2543
Zonr Chang932648d2010-10-13 22:23:56 +08002544 // interface for BCCscript::registerSymbolCallback()
2545 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002546 mpSymbolLookupFn = pFn;
2547 mpSymbolLookupContext = pContext;
2548 return;
2549 }
2550
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002551 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002552 GlobalInitialization();
2553 mModule = module;
2554 return hasError();
2555 }
2556
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002557 int readBC(const char *bitcode,
2558 size_t bitcodeSize,
2559 const BCCchar *resName) {
2560 GlobalInitialization();
2561
2562 if (resName) {
2563 // Turn off the default NeverCaching mode
2564 mNeverCache = false;
2565
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002566 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2567 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2568 return -mCacheFd;
2569 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002570 }
2571
2572 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002573
Zonr Chang932648d2010-10-13 22:23:56 +08002574 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002575 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002576
Zonr Chang932648d2010-10-13 22:23:56 +08002577 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002578 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002579 llvm::StringRef(bitcode, bitcodeSize)));
2580
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002581 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002582 setError("Error reading input program bitcode into memory");
2583 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002584 }
2585
Zonr Chang932648d2010-10-13 22:23:56 +08002586 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002587 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2588 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002589 return hasError();
2590 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002591
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002592 int linkBC(const char *bitcode, size_t bitcodeSize) {
2593 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002594
2595 if (bitcode == NULL || bitcodeSize <= 0)
2596 return 0;
2597
2598 if (mModule == NULL) {
2599 setError("No module presents for linking");
2600 return hasError();
2601 }
2602
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002603 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002604 llvm::StringRef(bitcode, bitcodeSize)));
2605
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002606 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002607 setError("Error reading input library bitcode into memory");
2608 return hasError();
2609 }
2610
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002611 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002612 *mContext,
2613 &mError));
2614 if (Lib.get() == NULL)
2615 return hasError();
2616
2617 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2618 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002619
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002620 // Everything for linking should be settled down here with no error occurs
2621 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002622 return hasError();
2623 }
2624
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002625
2626 // interface for bccLoadBinary()
2627 int loader() {
2628 // Check File Descriptor
2629 if (mCacheFd < 0) {
2630 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2631 goto giveup;
2632 }
2633
2634
2635 // Check File Size
2636 struct stat statCacheFd;
2637 if (fstat(mCacheFd, &statCacheFd) < 0) {
2638 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2639 goto giveup;
2640 }
2641
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002642 mCacheSize = statCacheFd.st_size;
2643
2644 if (mCacheSize < sizeof(oBCCHeader) ||
2645 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002646 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2647 goto giveup;
2648 }
2649
2650
2651 // Read File Content
2652 {
2653#ifdef BCC_CODE_ADDR
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002654 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002655
2656 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2657 MaxCodeSize + MaxGlobalVarSize,
2658 PROT_READ | PROT_EXEC | PROT_WRITE,
2659 MAP_PRIVATE | MAP_FIXED,
2660 mCacheFd, heuristicCodeOffset);
2661
2662 if (mCodeDataAddr == MAP_FAILED) {
2663 LOGE("unable to mmap .oBBC cache code/data: %s\n", strerror(errno));
2664 flock(mCacheFd, LOCK_UN);
2665 goto giveup;
2666 }
2667
2668 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
2669
2670 if (!mCacheMapAddr) {
2671 flock(mCacheFd, LOCK_UN);
2672 LOGE("allocation failed.\n");
2673 // TODO(all)
2674 goto bail;
2675 }
2676
2677 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2678 heuristicCodeOffset));
2679
2680 flock(mCacheFd, LOCK_UN);
2681
2682 if (nread != (size_t)heuristicCodeOffset) {
2683 LOGE("read(mCacheFd) failed\n");
2684 free(mCacheMapAddr);
2685 goto bail;
2686 }
2687
2688 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
2689
2690 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2691 LOGE("assertion failed: heuristic code offset is not correct.\n");
2692 goto bail;
2693 }
2694#else
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002695 mCacheMapAddr = (char *) mmap(0, mCacheSize,
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002696 PROT_READ | PROT_EXEC | PROT_WRITE,
2697 MAP_PRIVATE, mCacheFd, 0);
2698
Logan798280d2010-11-20 04:06:16 +08002699 if (mCacheMapAddr == MAP_FAILED) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002700 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2701 flock(mCacheFd, LOCK_UN);
2702 goto giveup;
2703 }
2704
2705 flock(mCacheFd, LOCK_UN);
2706
2707 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
2708
2709 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2710#endif
2711 }
2712
2713
2714 // Verify the Cache File
2715 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2716 LOGE("bad magic word\n");
2717 goto bail;
2718 }
2719
2720 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2721 LOGE("bad oBCC version 0x%08x\n",
2722 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2723 goto bail;
2724 }
2725
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002726 if (mCacheSize < mCacheHdr->relocOffset +
Logan824dd0a2010-11-20 01:45:54 +08002727 mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002728 LOGE("relocate table overflow\n");
2729 goto bail;
2730 }
2731
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002732 if (mCacheSize < mCacheHdr->exportVarsOffset +
2733 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002734 LOGE("export variables table overflow\n");
2735 goto bail;
2736 }
2737
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002738 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2739 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002740 LOGE("export functions table overflow\n");
2741 goto bail;
2742 }
2743
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002744 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2745 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002746 LOGE("export pragmas table overflow\n");
2747 goto bail;
2748 }
2749
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002750 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002751 LOGE("code cache overflow\n");
2752 goto bail;
2753 }
2754
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002755 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002756 LOGE("data (global variable) cache overflow\n");
2757 goto bail;
2758 }
2759
2760
2761 // Relocate
2762 {
2763 mCacheDiff = mCodeDataAddr -
2764 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2765
2766#ifdef BCC_CODE_ADDR
2767 if (mCacheDiff != 0) {
2768 LOGE("mCacheDiff should be zero but mCacheDiff = %d\n", mCacheDiff);
2769 goto bail;
2770 }
2771#else
Logan7f00bef2010-11-20 02:01:48 +08002772 if (mCacheHdr->rootAddr) {
2773 mCacheHdr->rootAddr += mCacheDiff;
2774 }
2775
2776 if (mCacheHdr->initAddr) {
2777 mCacheHdr->initAddr += mCacheDiff;
2778 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002779
Logan824dd0a2010-11-20 01:45:54 +08002780 oBCCRelocEntry *cachedRelocTable =
2781 reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
2782 mCacheHdr->relocOffset);
2783
2784 std::vector<llvm::MachineRelocation> relocations;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002785
2786 // Read in the relocs
2787 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
Logan824dd0a2010-11-20 01:45:54 +08002788 oBCCRelocEntry *entry = &cachedRelocTable[i];
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002789
Logan824dd0a2010-11-20 01:45:54 +08002790 llvm::MachineRelocation reloc =
2791 llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
2792 (unsigned)entry->relocType, 0, 0);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002793
Logan824dd0a2010-11-20 01:45:54 +08002794 reloc.setResultPointer(
2795 reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
2796
2797 relocations.push_back(reloc);
2798 }
2799
2800 // Rewrite machine code using llvm::TargetJITInfo relocate
2801 {
2802 llvm::TargetMachine *TM = NULL;
2803 const llvm::Target *Target;
2804 std::string FeaturesStr;
2805
2806 // Create TargetMachine
2807 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2808 if (hasError())
2809 goto bail;
2810
2811 if (!CPU.empty() || !Features.empty()) {
2812 llvm::SubtargetFeatures F;
2813 F.setCPU(CPU);
2814 for (std::vector<std::string>::const_iterator I = Features.begin(),
2815 E = Features.end(); I != E; I++)
2816 F.AddFeature(*I);
2817 FeaturesStr = F.getString();
2818 }
2819
2820 TM = Target->createTargetMachine(Triple, FeaturesStr);
2821 if (TM == NULL) {
2822 setError("Failed to create target machine implementation for the"
2823 " specified triple '" + Triple + "'");
2824 goto bail;
2825 }
2826
2827 TM->getJITInfo()->relocate(mCodeDataAddr,
2828 &relocations[0], relocations.size(),
2829 (unsigned char *)mCodeDataAddr+MaxCodeSize);
2830
Shih-wei Liaofdc568d2010-11-19 15:51:13 -08002831 if (mCodeEmitter.get()) {
2832 mCodeEmitter->Disassemble(llvm::StringRef("cache"),
2833 reinterpret_cast<uint8_t*>(mCodeDataAddr),
2834 2 * 1024 /*MaxCodeSize*/,
2835 false);
2836 }
2837
Logan824dd0a2010-11-20 01:45:54 +08002838 delete TM;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002839 }
2840#endif
2841 }
2842
2843 return 0;
2844
2845 bail:
2846#ifdef BCC_CODE_ADDR
2847 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2848 LOGE("munmap failed: %s\n", strerror(errno));
2849 }
2850
2851 if (mCacheMapAddr) {
2852 free(mCacheMapAddr);
2853 }
2854#else
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002855 if (munmap(mCacheMapAddr, mCacheSize) != 0) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002856 LOGE("munmap failed: %s\n", strerror(errno));
2857 }
2858#endif
2859
2860 giveup:
2861 return 1;
2862 }
2863
2864 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002865 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002866 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002867
Zonr Chang932648d2010-10-13 22:23:56 +08002868 llvm::TargetMachine *TM = NULL;
2869 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002870 std::string FeaturesStr;
2871
Zonr Chang932648d2010-10-13 22:23:56 +08002872 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002873
Zonr Chang932648d2010-10-13 22:23:56 +08002874 const llvm::NamedMDNode *PragmaMetadata;
2875 const llvm::NamedMDNode *ExportVarMetadata;
2876 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002877
Zonr Chang932648d2010-10-13 22:23:56 +08002878 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002879 return 0;
2880
Zonr Chang932648d2010-10-13 22:23:56 +08002881 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002882 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002883 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002884 goto on_bcc_compile_error;
2885
Zonr Chang932648d2010-10-13 22:23:56 +08002886 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002887 llvm::SubtargetFeatures F;
2888 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002889 for (std::vector<std::string>::const_iterator I = Features.begin(),
2890 E = Features.end();
2891 I != E;
2892 I++)
2893 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002894 FeaturesStr = F.getString();
2895 }
2896
2897 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002898 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002899 setError("Failed to create target machine implementation for the"
2900 " specified triple '" + Triple + "'");
2901 goto on_bcc_compile_error;
2902 }
2903
Zonr Chang932648d2010-10-13 22:23:56 +08002904 // Create memory manager for creation of code emitter later.
2905 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002906 setError("Failed to startup memory management for further compilation");
2907 goto on_bcc_compile_error;
2908 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002909 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002910
Zonr Chang932648d2010-10-13 22:23:56 +08002911 // Create code emitter
2912 if (!mCodeEmitter.get()) {
2913 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002914 setError("Failed to create machine code emitter to complete"
2915 " the compilation");
2916 goto on_bcc_compile_error;
2917 }
2918 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002919 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002920 mCodeEmitter->reset();
2921 }
2922
2923 mCodeEmitter->setTargetMachine(*TM);
2924 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2925 mpSymbolLookupContext);
2926
Zonr Chang932648d2010-10-13 22:23:56 +08002927 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002928 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002929
Zonr Chang5d35b972010-10-23 14:36:47 +08002930 // Load named metadata
2931 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2932 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2933 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2934
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002935 // Create LTO passes and run them on the mModule
2936 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002937 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002938 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08002939 LTOPasses.add(new llvm::TargetData(*TD));
2940
2941 std::vector<const char*> ExportSymbols;
2942
2943 // A workaround for getting export variable and function name. Will refine
2944 // it soon.
2945 if (ExportVarMetadata) {
2946 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2947 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2948 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2949 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2950 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2951 llvm::StringRef ExportVarName =
2952 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2953 ExportSymbols.push_back(ExportVarName.data());
2954 }
2955 }
2956 }
2957 }
2958
2959 if (ExportFuncMetadata) {
2960 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2961 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2962 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2963 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2964 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2965 llvm::StringRef ExportFuncName =
2966 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2967 ExportSymbols.push_back(ExportFuncName.data());
2968 }
2969 }
2970 }
2971 }
2972 // root() and init() are born to be exported
2973 ExportSymbols.push_back("root");
2974 ExportSymbols.push_back("init");
2975
Zonr Change5c7a542010-10-24 01:07:27 +08002976 // We now create passes list performing LTO. These are copied from
2977 // (including comments) llvm::createStandardLTOPasses().
2978
2979 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08002980 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002981
Zonr Change5c7a542010-10-24 01:07:27 +08002982 // Propagate constants at call sites into the functions they call. This
2983 // opens opportunities for globalopt (and inlining) by substituting
2984 // function pointers passed as arguments to direct uses of functions.
2985 LTOPasses.add(llvm::createIPSCCPPass());
2986
2987 // Now that we internalized some globals, see if we can hack on them!
2988 LTOPasses.add(llvm::createGlobalOptimizerPass());
2989
2990 // Linking modules together can lead to duplicated global constants, only
2991 // keep one copy of each constant...
2992 LTOPasses.add(llvm::createConstantMergePass());
2993
2994 // Remove unused arguments from functions...
2995 LTOPasses.add(llvm::createDeadArgEliminationPass());
2996
2997 // Reduce the code after globalopt and ipsccp. Both can open up
2998 // significant simplification opportunities, and both can propagate
2999 // functions through function pointers. When this happens, we often have
3000 // to resolve varargs calls, etc, so let instcombine do this.
3001 LTOPasses.add(llvm::createInstructionCombiningPass());
3002
3003 // Inline small functions
3004 LTOPasses.add(llvm::createFunctionInliningPass());
3005
3006 // Remove dead EH info.
3007 LTOPasses.add(llvm::createPruneEHPass());
3008
3009 // Internalize the globals again after inlining
3010 LTOPasses.add(llvm::createGlobalOptimizerPass());
3011
3012 // Remove dead functions.
3013 LTOPasses.add(llvm::createGlobalDCEPass());
3014
3015 // If we didn't decide to inline a function, check to see if we can
3016 // transform it to pass arguments by value instead of by reference.
3017 LTOPasses.add(llvm::createArgumentPromotionPass());
3018
3019 // The IPO passes may leave cruft around. Clean up after them.
3020 LTOPasses.add(llvm::createInstructionCombiningPass());
3021 LTOPasses.add(llvm::createJumpThreadingPass());
3022
3023 // Break up allocas
3024 LTOPasses.add(llvm::createScalarReplAggregatesPass());
3025
3026 // Run a few AA driven optimizations here and now, to cleanup the code.
3027 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
3028 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
3029
3030 // Hoist loop invariants.
3031 LTOPasses.add(llvm::createLICMPass());
3032
3033 // Remove redundancies.
3034 LTOPasses.add(llvm::createGVNPass());
3035
3036 // Remove dead memcpys.
3037 LTOPasses.add(llvm::createMemCpyOptPass());
3038
3039 // Nuke dead stores.
3040 LTOPasses.add(llvm::createDeadStoreEliminationPass());
3041
3042 // Cleanup and simplify the code after the scalar optimizations.
3043 LTOPasses.add(llvm::createInstructionCombiningPass());
3044
3045 LTOPasses.add(llvm::createJumpThreadingPass());
3046
3047 // Delete basic blocks, which optimization passes may have killed.
3048 LTOPasses.add(llvm::createCFGSimplificationPass());
3049
3050 // Now that we have optimized the program, discard unreachable functions.
3051 LTOPasses.add(llvm::createGlobalDCEPass());
3052
Zonr Chang6e1d6c32010-10-23 11:57:16 +08003053 LTOPasses.run(*mModule);
3054 }
3055
Zonr Chang932648d2010-10-13 22:23:56 +08003056 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003057 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08003058 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003059
Zonr Chang932648d2010-10-13 22:23:56 +08003060 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
3061 *mCodeEmitter,
3062 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003063 setError("The machine code emission is not supported by BCC on target '"
3064 + Triple + "'");
3065 goto on_bcc_compile_error;
3066 }
3067
Zonr Chang932648d2010-10-13 22:23:56 +08003068 // Run the pass (the code emitter) on every non-declaration function in the
3069 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003070 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08003071 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
3072 I != E;
3073 I++)
3074 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003075 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003076
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003077 CodeGenPasses->doFinalization();
3078
Zonr Chang932648d2010-10-13 22:23:56 +08003079 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08003080 if (ExportVarMetadata) {
3081 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
3082 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
3083 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
3084 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
3085 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003086 llvm::StringRef ExportVarName =
3087 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08003088 CodeEmitter::global_addresses_const_iterator I, E;
3089 for (I = mCodeEmitter->global_address_begin(),
3090 E = mCodeEmitter->global_address_end();
3091 I != E;
3092 I++) {
3093 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003094 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08003095 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003096 mExportVars.push_back(I->second);
3097 break;
3098 }
3099 }
Zonr Chang932648d2010-10-13 22:23:56 +08003100 if (I != mCodeEmitter->global_address_end())
3101 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003102 }
3103 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003104 // if reaching here, we know the global variable record in metadata is
3105 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003106 mExportVars.push_back(NULL);
3107 }
3108 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3109 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003110 }
3111
Zonr Chang932648d2010-10-13 22:23:56 +08003112 if (ExportFuncMetadata) {
3113 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3114 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3115 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3116 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3117 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003118 llvm::StringRef ExportFuncName =
3119 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3120 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3121 }
3122 }
3123 }
3124 }
3125
Zonr Chang932648d2010-10-13 22:23:56 +08003126 // Tell code emitter now can release the memory using during the JIT since
3127 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003128 mCodeEmitter->releaseUnnecessary();
3129
Zonr Chang932648d2010-10-13 22:23:56 +08003130 // Finally, read pragma information from the metadata node of the @Module if
3131 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003132 if (PragmaMetadata)
3133 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3134 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3135 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003136 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003137 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3138 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003139
Zonr Chang932648d2010-10-13 22:23:56 +08003140 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003141 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3142 llvm::StringRef PragmaName =
3143 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3144 llvm::StringRef PragmaValue =
3145 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3146
Zonr Chang932648d2010-10-13 22:23:56 +08003147 mPragmas.push_back(
3148 std::make_pair(std::string(PragmaName.data(),
3149 PragmaName.size()),
3150 std::string(PragmaValue.data(),
3151 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003152 }
3153 }
3154 }
3155
3156 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003157 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003158 if (CodeGenPasses) {
3159 delete CodeGenPasses;
3160 } else if (TD) {
3161 delete TD;
3162 }
3163 if (TM)
3164 delete TM;
3165
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003166 if (mError.empty()) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003167 if (!mNeverCache && mCacheFd >= 0 && mCacheNew) {
3168 genCacheFile();
3169 flock(mCacheFd, LOCK_UN);
3170 }
3171
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003172 return false;
3173 }
3174
Zonr Chang932648d2010-10-13 22:23:56 +08003175 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003176 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003177 }
3178
Zonr Chang932648d2010-10-13 22:23:56 +08003179 // interface for bccGetScriptInfoLog()
3180 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003181 return const_cast<char*>(mError.c_str());
3182 }
3183
Zonr Chang932648d2010-10-13 22:23:56 +08003184 // interface for bccGetScriptLabel()
3185 void *lookup(const char *name) {
3186 void *addr = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003187 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3188 if (!strcmp(name, "root")) {
3189 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3190 } else if (!strcmp(name, "init")) {
3191 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3192 }
3193 return addr;
3194 }
3195
Zonr Chang932648d2010-10-13 22:23:56 +08003196 if (mCodeEmitter.get())
3197 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003198 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003199 return addr;
3200 }
3201
Zonr Chang932648d2010-10-13 22:23:56 +08003202 // Interface for bccGetExportVars()
3203 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003204 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003205 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003206 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003207
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003208 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3209 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3210 if (actualVarCount)
3211 *actualVarCount = varCount;
3212 if (varCount > maxVarCount)
3213 varCount = maxVarCount;
3214 if (vars) {
3215 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3216 mCacheHdr->exportVarsOffset);
3217
3218 for (int i = 0; i < varCount; i++) {
3219 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3220 mCacheDiff);
3221 cachedVars++;
3222 }
3223 }
3224 return;
3225 }
3226
3227 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003228 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003229 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003230 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003231 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003232 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003233 for (ExportVarList::const_iterator I = mExportVars.begin(),
3234 E = mExportVars.end();
3235 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003236 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003237 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003238 }
3239 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003240
3241 return;
3242 }
3243
Zonr Chang932648d2010-10-13 22:23:56 +08003244 // Interface for bccGetExportFuncs()
3245 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003246 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003247 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003248 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003249
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003250 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3251 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3252 if (actualFuncCount)
3253 *actualFuncCount = funcCount;
3254 if (funcCount > maxFuncCount)
3255 funcCount = maxFuncCount;
3256 if (funcs) {
3257 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3258 mCacheHdr->exportFuncsOffset);
3259
3260 for (int i = 0; i < funcCount; i++) {
3261 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3262 mCacheDiff);
3263 cachedFuncs++;
3264 }
3265 }
3266 return;
3267 }
3268
3269 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003270 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003271 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003272 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003273 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003274 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003275 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3276 E = mExportFuncs.end();
3277 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003278 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003279 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003280 }
3281 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003282
3283 return;
3284 }
3285
Zonr Chang932648d2010-10-13 22:23:56 +08003286 // Interface for bccGetPragmas()
3287 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003288 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003289 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003290 int stringCount;
3291 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3292 if (actualStringCount)
3293 *actualStringCount = 0; // XXX
3294 return;
3295 }
3296
3297 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003298
Zonr Chang932648d2010-10-13 22:23:56 +08003299 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003300 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003301 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003302 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003303 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003304 for (PragmaList::const_iterator it = mPragmas.begin();
3305 stringCount > 0;
3306 stringCount -= 2, it++) {
3307 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3308 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003309 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003310 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003311
3312 return;
3313 }
3314
Zonr Chang932648d2010-10-13 22:23:56 +08003315 // Interface for bccGetFunctions()
3316 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003317 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003318 BCCchar **functions) {
3319 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003320 mCodeEmitter->getFunctionNames(actualFunctionCount,
3321 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003322 functions);
3323 else
3324 *actualFunctionCount = 0;
3325
3326 return;
3327 }
3328
Zonr Chang932648d2010-10-13 22:23:56 +08003329 // Interface for bccGetFunctionBinary()
3330 void getFunctionBinary(BCCchar *function,
3331 BCCvoid **base,
3332 BCCsizei *length) {
3333 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003334 mCodeEmitter->getFunctionBinary(function, base, length);
3335 } else {
3336 *base = NULL;
3337 *length = 0;
3338 }
3339 return;
3340 }
3341
Zonr Chang932648d2010-10-13 22:23:56 +08003342 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003343 return mModule;
3344 }
3345
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003346 ~Compiler() {
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003347#ifdef BCC_CODE_ADDR
3348 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3349 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3350 LOGE("munmap failed while releasing mCodeDataAddr\n");
3351 }
3352 }
3353
3354 if (mCacheMapAddr) {
3355 free(mCacheMapAddr);
3356 }
3357#else
3358 if (mCacheMapAddr != 0 && mCacheMapAddr != MAP_FAILED) {
3359 if (munmap(mCacheMapAddr, mCacheSize) < 0) {
3360 LOGE("munmap failed while releasing mCacheMapAddr\n");
3361 }
3362 }
3363#endif
3364
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003365 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003366 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003367 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003368 return;
3369 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003370
3371 private:
3372 // Note: loader() and genCacheFile() go hand in hand
3373 void genCacheFile() {
3374 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3375 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3376 return;
3377 }
3378
3379 bool codeOffsetNeedPadding = false;
3380
3381 uint32_t offset = sizeof(oBCCHeader);
3382
3383 // BCC Cache File Header
3384 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3385
3386 if (!hdr) {
3387 LOGE("Unable to allocate oBCCHeader.\n");
3388 return;
3389 }
3390
3391 // Magic Words
3392 memcpy(hdr->magic, OBCC_MAGIC, 4);
3393 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3394
3395 // Timestamp
3396 hdr->sourceWhen = 0; // TODO(all)
3397 hdr->rslibWhen = 0; // TODO(all)
3398 hdr->libRSWhen = 0; // TODO(all)
3399 hdr->libbccWhen = 0; // TODO(all)
3400
3401 // Current Memory Address (Saved for Recalculation)
3402 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3403 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3404 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3405
3406 // Relocation Table Offset and Entry Count
3407 hdr->relocOffset = sizeof(oBCCHeader);
Logan824dd0a2010-11-20 01:45:54 +08003408 hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003409
Logan824dd0a2010-11-20 01:45:54 +08003410 offset += hdr->relocCount * (sizeof(oBCCRelocEntry));
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003411
3412 // Export Variable Table Offset and Entry Count
3413 hdr->exportVarsOffset = offset;
3414 hdr->exportVarsCount = mExportVars.size();
3415
3416 offset += hdr->exportVarsCount * sizeof(uint32_t);
3417
3418 // Export Function Table Offset and Entry Count
3419 hdr->exportFuncsOffset = offset;
3420 hdr->exportFuncsCount = mExportFuncs.size();
3421
3422 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3423
3424 // Export Pragmas Table Offset and Entry Count
3425 hdr->exportPragmasOffset = offset;
3426 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3427
3428 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3429
3430 // Code Offset and Size
3431
3432#ifdef BCC_CODE_ADDR
3433 {
3434 long pagesize = sysconf(_SC_PAGESIZE);
3435
3436 if (offset % pagesize > 0) {
3437 codeOffsetNeedPadding = true;
3438 offset += pagesize - (offset % pagesize);
3439 }
3440 }
3441#else
3442 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3443 codeOffsetNeedPadding = true;
3444 offset += 0x08 - (offset & 0x07);
3445 }
3446#endif
3447
3448 hdr->codeOffset = offset;
3449 hdr->codeSize = MaxCodeSize;
3450
3451 offset += hdr->codeSize;
3452
3453 // Data (Global Variable) Offset and Size
3454 hdr->dataOffset = offset;
3455 hdr->dataSize = MaxGlobalVarSize;
3456
3457 offset += hdr->dataSize;
3458
3459 // Checksum
3460 hdr->checksum = 0; // Set Field checksum. TODO(all)
3461
3462 // Write Header
3463 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3464 sizeof(oBCCHeader), "Write oBCC header");
3465
Logan824dd0a2010-11-20 01:45:54 +08003466 // Write Relocation Entry Table
3467 {
3468 size_t allocSize = hdr->relocCount * sizeof(oBCCRelocEntry);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003469
Logan824dd0a2010-11-20 01:45:54 +08003470 oBCCRelocEntry const*records = &mCodeEmitter->getCachingRelocations()[0];
3471
3472 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(records),
3473 allocSize, "Write Relocation Entries");
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003474 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003475
3476 // Write Export Variables Table
3477 {
3478 uint32_t *record, *ptr;
3479
3480 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3481 ptr = record;
3482
3483 if (!record) {
3484 goto bail;
3485 }
3486
3487 for (ExportVarList::const_iterator I = mExportVars.begin(),
3488 E = mExportVars.end(); I != E; I++) {
3489 *ptr++ = reinterpret_cast<uint32_t>(*I);
3490 }
3491
3492 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3493 hdr->exportVarsCount * sizeof(uint32_t),
3494 "Write ExportVars");
3495
3496 free(record);
3497 }
3498
3499 // Write Export Functions Table
3500 {
3501 uint32_t *record, *ptr;
3502
3503 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3504 ptr = record;
3505
3506 if (!record) {
3507 goto bail;
3508 }
3509
3510 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3511 E = mExportFuncs.end(); I != E; I++) {
3512 *ptr++ = reinterpret_cast<uint32_t>(*I);
3513 }
3514
3515 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3516 hdr->exportFuncsCount * sizeof(uint32_t),
3517 "Write ExportFuncs");
3518
3519 free(record);
3520 }
3521
3522
3523 // TODO(all): Write Export Pragmas Table
3524#if 0
3525#else
3526 // Note: As long as we have comment out export pragmas table code,
3527 // we have to seek the position to correct offset.
3528
3529 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3530#endif
3531
3532 if (codeOffsetNeedPadding) {
3533 // requires additional padding
3534 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3535 }
3536
3537 // Write Generated Code and Global Variable
3538 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3539 "Write code and global variable");
3540
3541 goto close_return;
3542
3543 bail:
3544 if (ftruncate(mCacheFd, 0) != 0) {
3545 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3546 }
3547
3548 close_return:
3549 free(hdr);
3550 close(mCacheFd);
3551 mCacheFd = -1;
3552 return;
3553 }
3554
3555 // OpenCacheFile() returns fd of the cache file.
3556 // Input:
3557 // BCCchar *resName: Used to genCacheFileName()
3558 // bool createIfMissing: If false, turn off caching
3559 // Output:
3560 // returns fd: If -1: Failed
3561 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3562 // cache file's file descriptor
3563 // Note: openCacheFile() will check the cache file's validity,
3564 // such as Magic number, sourceWhen... dependencies.
3565 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3566 int fd, cc;
3567 struct stat fdStat, fileStat;
3568 bool readOnly = false;
3569
3570 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3571
3572 mCacheNew = false;
3573
3574 retry:
3575 /*
3576 * Try to open the cache file. If we've been asked to,
3577 * create it if it doesn't exist.
3578 */
3579 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3580 if (fd < 0) {
3581 fd = open(cacheFileName, O_RDONLY, 0);
3582 if (fd < 0) {
3583 if (createIfMissing) {
3584 LOGE("Can't open bcc-cache '%s': %s\n",
3585 cacheFileName, strerror(errno));
3586 mCacheNew = true;
3587 }
3588 return fd;
3589 }
3590 readOnly = true;
3591 }
3592
3593 /*
3594 * Grab an exclusive lock on the cache file. If somebody else is
3595 * working on it, we'll block here until they complete.
3596 */
3597 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3598 cacheFileName, fd);
3599
3600 cc = flock(fd, LOCK_EX | LOCK_NB);
3601 if (cc != 0) {
3602 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3603 cc = flock(fd, LOCK_EX);
3604 }
3605
3606 if (cc != 0) {
3607 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3608 close(fd);
3609 return -1;
3610 }
3611 LOGV("bcc: locked cache file\n");
3612
3613 /*
3614 * Check to see if the fd we opened and locked matches the file in
3615 * the filesystem. If they don't, then somebody else unlinked ours
3616 * and created a new file, and we need to use that one instead. (If
3617 * we caught them between the unlink and the create, we'll get an
3618 * ENOENT from the file stat.)
3619 */
3620 cc = fstat(fd, &fdStat);
3621 if (cc != 0) {
3622 LOGE("Can't stat open file '%s'\n", cacheFileName);
3623 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3624 goto close_fail;
3625 }
3626 cc = stat(cacheFileName, &fileStat);
3627 if (cc != 0 ||
3628 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3629 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3630 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3631 flock(fd, LOCK_UN);
3632 close(fd);
3633 usleep(250 * 1000); // if something is hosed, don't peg machine
3634 goto retry;
3635 }
3636
3637 /*
3638 * We have the correct file open and locked. If the file size is zero,
3639 * then it was just created by us, and we want to fill in some fields
3640 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3641 * verify that the fields in the header match our expectations, and
3642 * reset the file if they don't.
3643 */
3644 if (fdStat.st_size == 0) {
3645 if (readOnly) { // The device is readOnly --> close_fail
3646 LOGW("bcc: file has zero length and isn't writable\n");
3647 goto close_fail;
3648 }
3649 /*cc = createEmptyHeader(fd);
3650 if (cc != 0)
3651 goto close_fail;
3652 */
3653 mCacheNew = true;
3654 LOGV("bcc: successfully initialized new cache file\n");
3655 } else {
3656 // Calculate sourceWhen
3657 // XXX
3658 uint32_t sourceWhen = 0;
3659 uint32_t rslibWhen = 0;
3660 uint32_t libRSWhen = 0;
3661 uint32_t libbccWhen = 0;
3662 if (!checkHeaderAndDependencies(fd,
3663 sourceWhen,
3664 rslibWhen,
3665 libRSWhen,
3666 libbccWhen)) {
3667 // If checkHeaderAndDependencies returns 0: FAILED
3668 // Will truncate the file and retry to createIfMissing the file
3669
3670 if (readOnly) { // Shouldn't be readonly.
3671 /*
3672 * We could unlink and rewrite the file if we own it or
3673 * the "sticky" bit isn't set on the directory. However,
3674 * we're not able to truncate it, which spoils things. So,
3675 * give up now.
3676 */
3677 if (createIfMissing) {
3678 LOGW("Cached file %s is stale and not writable\n",
3679 cacheFileName);
3680 }
3681 goto close_fail;
3682 }
3683
3684 /*
3685 * If we truncate the existing file before unlinking it, any
3686 * process that has it mapped will fail when it tries to touch
3687 * the pages? Probably OK because we use MAP_PRIVATE.
3688 */
3689 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3690 cacheFileName);
3691 if (ftruncate(fd, 0) != 0) {
3692 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3693 cacheFileName, strerror(errno));
3694 /* keep going */
3695 }
3696 if (unlink(cacheFileName) != 0) {
3697 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3698 cacheFileName, errno, strerror(errno));
3699 /* keep going; permission failure should probably be fatal */
3700 }
3701 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3702 flock(fd, LOCK_UN);
3703 close(fd);
3704 goto retry;
3705 } else {
3706 // Got cacheFile! Good to go.
3707 LOGV("Good cache file\n");
3708 }
3709 }
3710
3711 assert(fd >= 0);
3712 return fd;
3713
3714 close_fail:
3715 flock(fd, LOCK_UN);
3716 close(fd);
3717 return -1;
3718 } // End of openCacheFile()
3719
3720 char *genCacheFileName(const char *fileName, const char *subFileName) {
3721 char nameBuf[512];
3722 static const char kCachePath[] = "bcc-cache";
3723 char absoluteFile[sizeof(nameBuf)];
3724 const size_t kBufLen = sizeof(nameBuf) - 1;
3725 const char *dataRoot;
3726 char *cp;
3727
3728 // Get the absolute path of the raw/***.bc file.
3729 absoluteFile[0] = '\0';
3730 if (fileName[0] != '/') {
3731 /*
3732 * Generate the absolute path. This doesn't do everything it
3733 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3734 * the leading "./" out, but it'll do.
3735 */
3736 if (getcwd(absoluteFile, kBufLen) == NULL) {
3737 LOGE("Can't get CWD while opening raw/***.bc file\n");
3738 return NULL;
3739 }
3740 // TODO(srhines): strncat() is a bit dangerous
3741 strncat(absoluteFile, "/", kBufLen);
3742 }
3743 strncat(absoluteFile, fileName, kBufLen);
3744
3745 if (subFileName != NULL) {
3746 strncat(absoluteFile, "/", kBufLen);
3747 strncat(absoluteFile, subFileName, kBufLen);
3748 }
3749
3750 /* Turn the path into a flat filename by replacing
3751 * any slashes after the first one with '@' characters.
3752 */
3753 cp = absoluteFile + 1;
3754 while (*cp != '\0') {
3755 if (*cp == '/') {
3756 *cp = '@';
3757 }
3758 cp++;
3759 }
3760
3761 /* Build the name of the cache directory.
3762 */
3763 dataRoot = getenv("ANDROID_DATA");
3764 if (dataRoot == NULL)
3765 dataRoot = "/data";
3766 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3767
3768 /* Tack on the file name for the actual cache file path.
3769 */
3770 strncat(nameBuf, absoluteFile, kBufLen);
3771
3772 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3773 return strdup(nameBuf);
3774 }
3775
3776 /*
3777 * Read the oBCC header, verify it, then read the dependent section
3778 * and verify that data as well.
3779 *
3780 * On successful return, the file will be seeked immediately past the
3781 * oBCC header.
3782 */
3783 bool checkHeaderAndDependencies(int fd,
3784 uint32_t sourceWhen,
3785 uint32_t rslibWhen,
3786 uint32_t libRSWhen,
3787 uint32_t libbccWhen) {
3788 ssize_t actual;
3789 oBCCHeader optHdr;
3790 uint32_t val;
3791 uint8_t const *magic, *magicVer;
3792
3793 /*
3794 * Start at the start. The "bcc" header, when present, will always be
3795 * the first thing in the file.
3796 */
3797 if (lseek(fd, 0, SEEK_SET) != 0) {
3798 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3799 goto bail;
3800 }
3801
3802 /*
3803 * Read and do trivial verification on the bcc header. The header is
3804 * always in host byte order.
3805 */
3806 actual = read(fd, &optHdr, sizeof(optHdr));
3807 if (actual < 0) {
3808 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3809 goto bail;
3810 } else if (actual != sizeof(optHdr)) {
3811 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3812 (int) actual, sizeof(optHdr));
3813 goto bail;
3814 }
3815
3816 magic = optHdr.magic;
3817 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3818 /* not an oBCC file, or previous attempt was interrupted */
3819 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3820 magic[0], magic[1], magic[2], magic[3]);
3821 goto bail;
3822 }
3823
3824 magicVer = optHdr.magicVersion;
3825 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3826 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3827 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3828 goto bail;
3829 }
3830
3831 /*
3832 * Do the header flags match up with what we want?
3833 *
3834 * This is useful because it allows us to automatically regenerate
3835 * a file when settings change (e.g. verification is now mandatory),
3836 * but can cause difficulties if the thing we depend upon
3837 * were handled differently than the current options specify.
3838 *
3839 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3840 * by limiting the match mask.
3841 *
3842 * The only thing we really can't handle is incorrect byte-ordering.
3843 */
3844
3845 val = optHdr.sourceWhen;
3846 if (val && (val != sourceWhen)) {
3847 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3848 val, sourceWhen);
3849 goto bail;
3850 }
3851 val = optHdr.rslibWhen;
3852 if (val && (val != rslibWhen)) {
3853 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3854 val, rslibWhen);
3855 goto bail;
3856 }
3857 val = optHdr.libRSWhen;
3858 if (val && (val != libRSWhen)) {
3859 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3860 val, libRSWhen);
3861 goto bail;
3862 }
3863 val = optHdr.libbccWhen;
3864 if (val && (val != libbccWhen)) {
3865 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3866 val, libbccWhen);
3867 goto bail;
3868 }
3869
3870 return true;
3871
3872 bail:
3873 return false;
3874 }
3875
Zonr Chang932648d2010-10-13 22:23:56 +08003876};
3877// End of Class Compiler
3878////////////////////////////////////////////////////////////////////////////////
3879
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003880
3881bool Compiler::GlobalInitialized = false;
3882
Zonr Chang932648d2010-10-13 22:23:56 +08003883// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003884llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3885
3886std::string Compiler::Triple;
3887
3888std::string Compiler::CPU;
3889
3890std::vector<std::string> Compiler::Features;
3891
Zonr Chang932648d2010-10-13 22:23:56 +08003892// The named of metadata node that pragma resides (should be synced with
3893// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003894const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3895
Zonr Chang932648d2010-10-13 22:23:56 +08003896// The named of metadata node that export variable name resides (should be
3897// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003898const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3899
Zonr Chang932648d2010-10-13 22:23:56 +08003900// The named of metadata node that export function name resides (should be
3901// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003902const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3903
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003904struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003905 //////////////////////////////////////////////////////////////////////////////
3906 // Part I. Compiler
3907 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003908 Compiler compiler;
3909
Zonr Chang932648d2010-10-13 22:23:56 +08003910 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003911 compiler.registerSymbolCallback(pFn, pContext);
3912 }
3913
Zonr Chang932648d2010-10-13 22:23:56 +08003914 //////////////////////////////////////////////////////////////////////////////
3915 // Part II. Logistics & Error handling
3916 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003917 BCCscript() {
3918 bccError = BCC_NO_ERROR;
3919 }
3920
3921 ~BCCscript() {
3922 }
3923
3924 void setError(BCCenum error) {
3925 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3926 bccError = error;
3927 }
3928 }
3929
3930 BCCenum getError() {
3931 BCCenum result = bccError;
3932 bccError = BCC_NO_ERROR;
3933 return result;
3934 }
3935
3936 BCCenum bccError;
3937};
3938
3939
3940extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003941BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003942 return new BCCscript();
3943}
3944
3945extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003946BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003947 return script->getError();
3948}
3949
3950extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003951void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003952 delete script;
3953}
3954
3955extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003956void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003957 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08003958 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003959 script->registerSymbolCallback(pFn, pContext);
3960}
3961
3962extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003963int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08003964 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003965 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08003966}
3967
3968extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003969int bccReadBC(BCCscript *script,
3970 const BCCchar *bitcode,
3971 BCCint size,
3972 const BCCchar *resName) {
3973 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003974}
3975
3976extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003977void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08003978 const BCCchar *bitcode,
3979 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003980 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08003981}
3982
3983extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003984void bccLoadBinary(BCCscript *script) {
3985 int result = script->compiler.loader();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003986 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003987 script->setError(BCC_INVALID_OPERATION);
3988}
3989
3990extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003991void bccCompileBC(BCCscript *script) {
3992 {
3993#if defined(__arm__)
3994 android::StopWatch compileTimer("RenderScript compile time");
3995#endif
3996 int result = script->compiler.compile();
3997 if (result)
3998 script->setError(BCC_INVALID_OPERATION);
3999 }
4000}
4001
4002extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004003void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004004 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08004005 BCCsizei *length,
4006 BCCchar *infoLog) {
4007 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004008 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004009 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004010 *length = messageLength;
4011
4012 if (infoLog && maxLength > 0) {
4013 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
4014 memcpy(infoLog, message, trimmedLength);
4015 infoLog[trimmedLength] = 0;
4016 }
4017}
4018
4019extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004020void bccGetScriptLabel(BCCscript *script,
4021 const BCCchar *name,
4022 BCCvoid **address) {
4023 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004024 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004025 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004026 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004027 script->setError(BCC_INVALID_VALUE);
4028}
4029
4030extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004031void bccGetExportVars(BCCscript *script,
4032 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004033 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004034 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07004035 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
4036}
4037
4038extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004039void bccGetExportFuncs(BCCscript *script,
4040 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004041 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004042 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07004043 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
4044}
4045
4046extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004047void bccGetPragmas(BCCscript *script,
4048 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004049 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004050 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004051 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
4052}
4053
4054extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004055void bccGetFunctions(BCCscript *script,
4056 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004057 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08004058 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07004059 script->compiler.getFunctions(actualFunctionCount,
4060 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004061 functions);
4062}
4063
4064extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08004065void bccGetFunctionBinary(BCCscript *script,
4066 BCCchar *function,
4067 BCCvoid **base,
4068 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004069 script->compiler.getFunctionBinary(function, base, length);
4070}
4071
4072struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08004073 const Compiler *compiler;
4074 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07004075};
4076
Zonr Chang932648d2010-10-13 22:23:56 +08004077} // namespace bcc