blob: 9f708e47ecf23a08ce63644fb693d58930ddd1d1 [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
218/* oBCCHeader Offset Table */
219#define k_magic offsetof(oBCCHeader, magic)
220#define k_magicVersion offsetof(oBCCHeader, magicVersion)
221#define k_sourceWhen offsetof(oBCCHeader, sourceWhen)
222#define k_rslibWhen offsetof(oBCCHeader, rslibWhen)
223#define k_libRSWhen offsetof(oBCCHeader, libRSWhen)
224#define k_libbccWhen offsetof(oBCCHeader, libbccWhen)
225#define k_cachedCodeDataAddr offsetof(oBCCHeader, cachedCodeDataAddr)
226#define k_rootAddr offsetof(oBCCHeader, rootAddr)
227#define k_initAddr offsetof(oBCCHeader, initAddr)
228#define k_relocOffset offsetof(oBCCHeader, relocOffset)
229#define k_relocCount offsetof(oBCCHeader, relocCount)
230#define k_exportVarsOffset offsetof(oBCCHeader, exportVarsOffset)
231#define k_exportVarsCount offsetof(oBCCHeader, exportVarsCount)
232#define k_exportFuncsOffset offsetof(oBCCHeader, exportFuncsOffset)
233#define k_exportFuncsCount offsetof(oBCCHeader, exportFuncsCount)
234#define k_exportPragmasOffset offsetof(oBCCHeader, exportPragmasOffset)
235#define k_exportPragmasCount offsetof(oBCCHeader, exportPragmasCount)
236#define k_codeOffset offsetof(oBCCHeader, codeOffset)
237#define k_codeSize offsetof(oBCCHeader, codeSize)
238#define k_dataOffset offsetof(oBCCHeader, dataOffset)
239#define k_dataSize offsetof(oBCCHeader, dataSize)
240#define k_checksum offsetof(oBCCHeader, checksum)
241
242/* oBCC file magic number */
243#define OBCC_MAGIC "bcc\n"
244/* version, encoded in 4 bytes of ASCII */
245#define OBCC_MAGIC_VERS "001\0"
246
247#define TEMP_FAILURE_RETRY1(exp) ({ \
248 typeof (exp) _rc; \
249 do { \
250 _rc = (exp); \
251 } while (_rc == -1 && errno == EINTR); \
252 _rc; })
253
254static int sysWriteFully(int fd, const void* buf, size_t count, const char* logMsg)
255{
256 while (count != 0) {
257 ssize_t actual = TEMP_FAILURE_RETRY1(write(fd, buf, count));
258 if (actual < 0) {
259 int err = errno;
260 LOGE("%s: write failed: %s\n", logMsg, strerror(err));
261 return err;
262 } else if (actual != (ssize_t) count) {
263 LOGD("%s: partial write (will retry): (%d of %zd)\n",
264 logMsg, (int) actual, count);
265 buf = (const void*) (((const uint8_t*) buf) + actual);
266 }
267 count -= actual;
268 }
269
270 return 0;
271}
272
Zonr Chang932648d2010-10-13 22:23:56 +0800273//
274// Compilation class that suits Android's needs.
275// (Support: no argument passed, ...)
276//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700277namespace bcc {
278
279class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800280 // This part is designed to be orthogonal to those exported bcc*() functions
281 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700282
Zonr Chang932648d2010-10-13 22:23:56 +0800283 //////////////////////////////////////////////////////////////////////////////
284 // The variable section below (e.g., Triple, CodeGenOptLevel)
285 // is initialized in GlobalInitialization()
286 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700287 static bool GlobalInitialized;
288
Zonr Chang932648d2010-10-13 22:23:56 +0800289 // If given, this will be the name of the target triple to compile for.
290 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700291 static std::string Triple;
292
293 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700294
Zonr Chang932648d2010-10-13 22:23:56 +0800295 // End of section of GlobalInitializing variables
296 //////////////////////////////////////////////////////////////////////////////
297
298 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700299 static std::string CPU;
300
Zonr Chang932648d2010-10-13 22:23:56 +0800301 // The list of target specific features to enable or disable -- this should
302 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700303 static std::vector<std::string> Features;
304
305 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800306 const char *mName;
307 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700308 };
309 static struct Runtime Runtimes[];
310
311 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800312 if (GlobalInitialized)
313 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700314
Zonr Chang932648d2010-10-13 22:23:56 +0800315 // if (!llvm::llvm_is_multithreaded())
316 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700317
Zonr Chang932648d2010-10-13 22:23:56 +0800318 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700319 Triple = TARGET_TRIPLE_STRING;
320
Zonr Chang932648d2010-10-13 22:23:56 +0800321 // TODO(zonr): NEON for JIT
322 // Features.push_back("+neon");
323 // Features.push_back("+vmlx");
324 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700325 Features.push_back("+vfp3");
Shih-wei Liao21ef3072010-10-23 22:33:12 -0700326 Features.push_back("+d16");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700327
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700328#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
329 LLVMInitializeARMTargetInfo();
330 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700331#if defined(USE_DISASSEMBLER)
332 LLVMInitializeARMDisassembler();
333 LLVMInitializeARMAsmPrinter();
334#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700335#endif
336
337#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
338 LLVMInitializeX86TargetInfo();
339 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700340#if defined(USE_DISASSEMBLER)
341 LLVMInitializeX86Disassembler();
342 LLVMInitializeX86AsmPrinter();
343#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700344#endif
345
346#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
347 LLVMInitializeX86TargetInfo();
348 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700349#if defined(USE_DISASSEMBLER)
350 LLVMInitializeX86Disassembler();
351 LLVMInitializeX86AsmPrinter();
352#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700353#endif
354
Zonr Chang932648d2010-10-13 22:23:56 +0800355 // -O0: llvm::CodeGenOpt::None
356 // -O1: llvm::CodeGenOpt::Less
357 // -O2: llvm::CodeGenOpt::Default
358 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liaobfda6c92010-10-24 02:43:04 -0700359 CodeGenOptLevel = llvm::CodeGenOpt::None;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700360
Zonr Chang932648d2010-10-13 22:23:56 +0800361 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700362
Zonr Chang932648d2010-10-13 22:23:56 +0800363 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700364 llvm::NoFramePointerElim = false;
365
Zonr Chang932648d2010-10-13 22:23:56 +0800366 // Use hardfloat ABI
367 //
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800368 // TODO(all): Need to detect the CPU capability and decide whether to use
Zonr Chang932648d2010-10-13 22:23:56 +0800369 // softfp. To use softfp, change following 2 lines to
370 //
371 // llvm::FloatABIType = llvm::FloatABI::Soft;
372 // llvm::UseSoftFloat = true;
373 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700374 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700375 llvm::UseSoftFloat = false;
376
Zonr Chang932648d2010-10-13 22:23:56 +0800377 // BCC needs all unknown symbols resolved at JIT/compilation time.
378 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700379 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
380
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700381#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800382 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700383 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
384#else
Zonr Chang932648d2010-10-13 22:23:56 +0800385 // This is set for the linker (specify how large of the virtual addresses
386 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700387 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
388#endif
389
Zonr Chang932648d2010-10-13 22:23:56 +0800390 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700391 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
392
Zonr Chang932648d2010-10-13 22:23:56 +0800393 // Register allocation policy:
394 // createFastRegisterAllocator: fast but bad quality
395 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700396 llvm::RegisterRegAlloc::setDefault
397 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700398 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700399 llvm::createLinearScanRegisterAllocator);
400
401 GlobalInitialized = true;
402 return;
403 }
404
405 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800406 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700407 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700408 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800409 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700410 }
411
412 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700413 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700414 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700415
416 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700417 std::string mError;
418
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700419 inline bool hasError() const {
420 return !mError.empty();
421 }
Zonr Chang932648d2010-10-13 22:23:56 +0800422 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700423 mError.assign(Error); // Copying
424 return;
425 }
Zonr Chang932648d2010-10-13 22:23:56 +0800426 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700427 mError = Error;
428 return;
429 }
430
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800431 bool mNeverCache; // Set by readBC()
432 bool mCacheNew; // Set by readBC()
433 int mCacheFd; // Set by readBC()
434 char *mCacheMapAddr; // Set by loader() if mCacheNew is false
435 oBCCHeader *mCacheHdr; // Set by loader()
436 ptrdiff_t mCacheDiff; // Set by loader()
437 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
438 // Used by genCacheFile() for dumping
439
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700440 typedef std::list< std::pair<std::string, std::string> > PragmaList;
441 PragmaList mPragmas;
442
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700443 typedef std::list<void*> ExportVarList;
444 ExportVarList mExportVars;
445
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700446 typedef std::list<void*> ExportFuncList;
447 ExportFuncList mExportFuncs;
448
Zonr Chang932648d2010-10-13 22:23:56 +0800449 //////////////////////////////////////////////////////////////////////////////
450 // Memory manager for the code reside in memory
451 //
452 // The memory for our code emitter is very simple and is conforming to the
453 // design decisions of Android RenderScript's Exection Environment:
454 // The code, data, and symbol sizes are limited (currently 100KB.)
455 //
456 // It's very different from typical compiler, which has no limitation
457 // on the code size. How does code emitter know the size of the code
458 // it is about to emit? It does not know beforehand. We want to solve
459 // this without complicating the code emitter too much.
460 //
461 // We solve this by pre-allocating a certain amount of memory,
462 // and then start the code emission. Once the buffer overflows, the emitter
463 // simply discards all the subsequent emission but still has a counter
464 // on how many bytes have been emitted.
465 //
466 // So once the whole emission is done, if there's a buffer overflow,
467 // it re-allocates the buffer with enough size (based on the
468 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800469
470 // 128 KiB for code
471 static const unsigned int MaxCodeSize = 128 * 1024;
472 // 1 KiB for global offset table (GOT)
473 static const unsigned int MaxGOTSize = 1 * 1024;
474 // 128 KiB for global variable
475 static const unsigned int MaxGlobalVarSize = 128 * 1024;
476
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700477 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700478 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800479 //
480 // Our memory layout is as follows:
481 //
482 // The direction of arrows (-> and <-) shows memory's growth direction
483 // when more space is needed.
484 //
485 // @mpCodeMem:
486 // +--------------------------------------------------------------+
487 // | Function Memory ... -> <- ... Stub/GOT |
488 // +--------------------------------------------------------------+
489 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
490 //
491 // Where size of GOT is @MaxGOTSize KiB.
492 //
493 // @mpGVMem:
494 // +--------------------------------------------------------------+
495 // | Global variable ... -> |
496 // +--------------------------------------------------------------+
497 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
498 //
499 //
500 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
501 // of function code's memory usage
502 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
503 // of stub/GOT's memory usage
504 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
505 // of global variable's memory usage
506 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700507 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700508 uintptr_t mCurSGMemIdx;
509 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800510 void *mpCodeMem;
511 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700512
Zonr Chang932648d2010-10-13 22:23:56 +0800513 // GOT Base
514 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700515
516 typedef std::map<const llvm::Function*, pair<void* /* start address */,
517 void* /* end address */>
518 > FunctionMapTy;
519 FunctionMapTy mFunctionMap;
520
Zonr Chang932648d2010-10-13 22:23:56 +0800521 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700522 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700523 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700524
Zonr Chang932648d2010-10-13 22:23:56 +0800525 uint8_t *allocateSGMemory(uintptr_t Size,
526 unsigned Alignment = 1 /* no alignment */) {
527 intptr_t FreeMemSize = getFreeCodeMemSize();
528 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
529 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700530 return NULL;
531
Zonr Chang932648d2010-10-13 22:23:56 +0800532 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700533 Alignment = 1;
534
Zonr Chang932648d2010-10-13 22:23:56 +0800535 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700536 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
537
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700538 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700539
540 return result;
541 }
542
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700543 inline uintptr_t getFreeGVMemSize() const {
544 return MaxGlobalVarSize - mCurGVMemIdx;
545 }
Zonr Chang932648d2010-10-13 22:23:56 +0800546 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700547 return reinterpret_cast<uint8_t*>(mpGVMem);
548 }
549
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700550 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700551 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700552 reset();
553 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700554
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800555#ifdef BCC_CODE_ADDR
556 mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
557 MaxCodeSize + MaxGlobalVarSize,
558 PROT_READ | PROT_EXEC | PROT_WRITE,
559 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
560 -1,
561 0);
562#else
563 mpCodeMem = mmap(NULL,
564 MaxCodeSize + MaxGlobalVarSize,
565 PROT_READ | PROT_EXEC | PROT_WRITE,
566 MAP_PRIVATE | MAP_ANON,
567 -1,
568 0);
569#endif
570
571 if (mpCodeMem == MAP_FAILED) {
572 llvm::report_fatal_error("Failed to allocate memory for emitting "
573 "codes\n" + ErrMsg);
574 }
575 mpGVMem = (void *) ((int) mpCodeMem + MaxCodeSize);
576
577 /* mpCodeMem = mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700578 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700579 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800580 llvm::report_fatal_error("Failed to allocate memory for emitting "
581 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700582
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800583 mpGVMem = mmap(mpCodeMem, MaxGlobalVarSize,
584 PROT_READ | PROT_WRITE,
585 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700586 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800587 llvm::report_fatal_error("Failed to allocate memory for emitting "
588 "global variables\n" + ErrMsg);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800589 */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700590 return;
591 }
592
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800593 inline uint8_t *getCodeMemBase() const {
594 return reinterpret_cast<uint8_t*>(mpCodeMem);
595 }
596
Zonr Chang932648d2010-10-13 22:23:56 +0800597 // setMemoryWritable - When code generation is in progress, the code pages
598 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700599 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700600 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700601 return;
602 }
603
Zonr Chang932648d2010-10-13 22:23:56 +0800604 // When code generation is done and we're ready to start execution, the
605 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700606 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700607 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700608 return;
609 }
610
Zonr Chang932648d2010-10-13 22:23:56 +0800611 // Setting this flag to true makes the memory manager garbage values over
612 // freed memory. This is useful for testing and debugging, and is to be
613 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700614 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800615 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700616 return;
617 }
618
Zonr Chang932648d2010-10-13 22:23:56 +0800619 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700620
Zonr Chang932648d2010-10-13 22:23:56 +0800621 // If the current table requires a Global Offset Table, this method is
622 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700623 void AllocateGOT() {
624 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700625 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700626 HasGOT = true;
627 return;
628 }
629
Zonr Chang932648d2010-10-13 22:23:56 +0800630 // If this is managing a Global Offset Table, this method should return a
631 // pointer to its base.
632 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700633 return mpGOTBase;
634 }
635
Zonr Chang932648d2010-10-13 22:23:56 +0800636 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700637
Zonr Chang932648d2010-10-13 22:23:56 +0800638 // When we start JITing a function, the JIT calls this method to allocate a
639 // block of free RWX memory, which returns a pointer to it. If the JIT wants
640 // to request a block of memory of at least a certain size, it passes that
641 // value as ActualSize, and this method returns a block with at least that
642 // much space. If the JIT doesn't know ahead of time how much space it will
643 // need to emit the function, it passes 0 for the ActualSize. In either
644 // case, this method is required to pass back the size of the allocated
645 // block through ActualSize. The JIT will be careful to not write more than
646 // the returned ActualSize bytes of memory.
647 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
648 intptr_t FreeMemSize = getFreeCodeMemSize();
649 if ((FreeMemSize < 0) ||
650 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
651 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700652 return NULL;
653
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700654 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700655 return (getCodeMemBase() + mCurFuncMemIdx);
656 }
657
Zonr Chang932648d2010-10-13 22:23:56 +0800658 // This method is called by the JIT to allocate space for a function stub
659 // (used to handle limited branch displacements) while it is JIT compiling a
660 // function. For example, if foo calls bar, and if bar either needs to be
661 // lazily compiled or is a native function that exists too far away from the
662 // call site to work, this method will be used to make a thunk for it. The
663 // stub should be "close" to the current function body, but should not be
664 // included in the 'actualsize' returned by startFunctionBody.
665 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700666 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700667 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700668 }
669
Zonr Chang932648d2010-10-13 22:23:56 +0800670 // This method is called when the JIT is done codegen'ing the specified
671 // function. At this point we know the size of the JIT compiled function.
672 // This passes in FunctionStart (which was returned by the startFunctionBody
673 // method) and FunctionEnd which is a pointer to the actual end of the
674 // function. This method should mark the space allocated and remember where
675 // it is in case the client wants to deallocate it.
676 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
677 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700678 assert(FunctionEnd > FunctionStart);
679 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
680 "Mismatched function start/end!");
681
Zonr Chang932648d2010-10-13 22:23:56 +0800682 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700683 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700684 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700685 "Code size excess the limitation!");
686 mCurFuncMemIdx += FunctionCodeSize;
687
Zonr Chang932648d2010-10-13 22:23:56 +0800688 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700689 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
690 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800691 mFunctionMap.insert(
692 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
693 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700694
695 return;
696 }
697
Zonr Chang932648d2010-10-13 22:23:56 +0800698 // Allocate a (function code) memory block of the given size. This method
699 // cannot be called between calls to startFunctionBody and endFunctionBody.
700 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
701 if (getFreeCodeMemSize() < Size)
702 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700703 return NULL;
704
Zonr Chang932648d2010-10-13 22:23:56 +0800705 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700706 Alignment = 1;
707
Zonr Chang932648d2010-10-13 22:23:56 +0800708 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700709 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800710 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700711
712 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
713
714 return result;
715 }
716
Zonr Chang932648d2010-10-13 22:23:56 +0800717 // Allocate memory for a global variable.
718 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700719 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800720 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700721 LOGE("No Global Memory");
722 return NULL;
723 }
724
Zonr Chang932648d2010-10-13 22:23:56 +0800725 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700726 Alignment = 1;
727
Zonr Chang932648d2010-10-13 22:23:56 +0800728 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700729 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800730 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700731
732 mCurGVMemIdx = (result + Size) - getGVMemBase();
733
734 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700735 }
736
Zonr Chang932648d2010-10-13 22:23:56 +0800737 // Free the specified function body. The argument must be the return value
738 // from a call to startFunctionBody() that hasn't been deallocated yet. This
739 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700740 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800741 // linear search
742 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
743 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
744 E = mFunctionMap.end();
745 I != E;
746 I++)
747 if (I->second.first == Body) {
748 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
749 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700750 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800751 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700752
Zonr Chang932648d2010-10-13 22:23:56 +0800753 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700754
Zonr Chang932648d2010-10-13 22:23:56 +0800755 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700756 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
757
758 assert(SizeNeedMove >= 0 &&
759 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
760 " be correctly calculated!");
761
Zonr Chang932648d2010-10-13 22:23:56 +0800762 if (SizeNeedMove > 0)
763 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700764 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
765 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
766
767 return;
768 }
769
Zonr Chang932648d2010-10-13 22:23:56 +0800770 // When we finished JITing the function, if exception handling is set, we
771 // emit the exception table.
772 uint8_t *startExceptionTable(const llvm::Function *F,
773 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700774 assert(false && "Exception is not allowed in our language specification");
775 return NULL;
776 }
777
Zonr Chang932648d2010-10-13 22:23:56 +0800778 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700779 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800780 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700781 assert(false && "Exception is not allowed in our language specification");
782 return;
783 }
784
Zonr Chang932648d2010-10-13 22:23:56 +0800785 // Free the specified exception table's memory. The argument must be the
786 // return value from a call to startExceptionTable() that hasn't been
787 // deallocated yet. This is never called when the JIT is currently emitting
788 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700789 void deallocateExceptionTable(void *ET) {
790 assert(false && "Exception is not allowed in our language specification");
791 return;
792 }
793
Zonr Chang932648d2010-10-13 22:23:56 +0800794 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700795 void reset() {
796 mpGOTBase = NULL;
797 HasGOT = false;
798
799 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700800 mCurSGMemIdx = MaxCodeSize - 1;
801 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700802
803 mFunctionMap.clear();
804
805 return;
806 }
807
808 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800809 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700810 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800811 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700812 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700813 return;
814 }
Zonr Chang932648d2010-10-13 22:23:56 +0800815 };
816 // End of class CodeMemoryManager
817 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700818
Zonr Chang932648d2010-10-13 22:23:56 +0800819 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700820 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800821 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700822 mCodeMemMgr.reset(new CodeMemoryManager());
823 return mCodeMemMgr.get();
824 }
825
Zonr Chang932648d2010-10-13 22:23:56 +0800826 //////////////////////////////////////////////////////////////////////////////
827 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700828 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700829 public:
830 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
831 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
832
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800833 GlobalAddressMapTy mGlobalAddressMap;
834
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700835 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800836 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700837
Zonr Chang932648d2010-10-13 22:23:56 +0800838 // The JITInfo for the target we are compiling to
839 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700840
Zonr Chang932648d2010-10-13 22:23:56 +0800841 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700842
Zonr Chang932648d2010-10-13 22:23:56 +0800843 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700844
845 class EmittedFunctionCode {
846 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800847 // Beginning of the function's allocation.
848 void *FunctionBody;
849
850 // The address the function's code actually starts at.
851 void *Code;
852
853 // The size of the function code
854 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700855
856 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
857 };
Zonr Chang932648d2010-10-13 22:23:56 +0800858 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700859
Zonr Chang932648d2010-10-13 22:23:56 +0800860 typedef std::map<const std::string,
861 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700862 EmittedFunctionsMapTy mEmittedFunctions;
863
Zonr Chang932648d2010-10-13 22:23:56 +0800864 // This vector is a mapping from MBB ID's to their address. It is filled in
865 // by the StartMachineBasicBlock callback and queried by the
866 // getMachineBasicBlockAddress callback.
867 std::vector<uintptr_t> mMBBLocations;
868
869 // The constant pool for the current function.
870 llvm::MachineConstantPool *mpConstantPool;
871
872 // A pointer to the first entry in the constant pool.
873 void *mpConstantPoolBase;
874
875 // Addresses of individual constant pool entries.
876 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
877
878 // The jump tables for the current function.
879 llvm::MachineJumpTableInfo *mpJumpTable;
880
881 // A pointer to the first entry in the jump table.
882 void *mpJumpTableBase;
883
884 // When outputting a function stub in the context of some other function, we
885 // save BufferBegin/BufferEnd/CurBufferPtr here.
886 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
887
888 // These are the relocations that the function needs, as emitted.
889 std::vector<llvm::MachineRelocation> mRelocations;
890
891 // This vector is a mapping from Label ID's to their address.
892 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
893
894 // Machine module info for exception informations
895 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700896
Zonr Chang932648d2010-10-13 22:23:56 +0800897 // Replace an existing mapping for GV with a new address. This updates both
898 // maps as required. If Addr is null, the entry for the global is removed
899 // from the mappings.
900 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
901 if (Addr == NULL) {
902 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700903 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
904 void *OldVal;
905
Zonr Chang932648d2010-10-13 22:23:56 +0800906 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700907 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800908 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700909 OldVal = I->second;
910 mGlobalAddressMap.erase(I);
911 }
912
913 return OldVal;
914 }
915
Zonr Chang932648d2010-10-13 22:23:56 +0800916 void *&CurVal = mGlobalAddressMap[GV];
917 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700918
919 CurVal = Addr;
920
921 return OldVal;
922 }
923
Zonr Chang932648d2010-10-13 22:23:56 +0800924 // Tell the execution engine that the specified global is at the specified
925 // location. This is used internally as functions are JIT'd and as global
926 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700927 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800928 void *&CurVal = mGlobalAddressMap[GV];
929 assert((CurVal == 0 || Addr == 0) &&
930 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700931 CurVal = Addr;
932 return;
933 }
934
Zonr Chang932648d2010-10-13 22:23:56 +0800935 // This returns the address of the specified global value if it is has
936 // already been codegen'd, otherwise it returns null.
937 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700938 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700939 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
940 }
941
Zonr Chang932648d2010-10-13 22:23:56 +0800942 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
943 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700944 MCP->getConstants();
945
Zonr Chang932648d2010-10-13 22:23:56 +0800946 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700947 return 0;
948
949 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800950 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700951 llvm::MachineConstantPoolEntry CPE = Constants[i];
952 unsigned int AlignMask = CPE.getAlignment() - 1;
953 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800954 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700955 Size += mpTD->getTypeAllocSize(Ty);
956 }
957
958 return Size;
959 }
960
Zonr Chang932648d2010-10-13 22:23:56 +0800961 // This function converts a Constant* into a GenericValue. The interesting
962 // part is if C is a ConstantExpr.
963 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
964 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700965 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800966 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
967 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
968 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700969
Zonr Chang932648d2010-10-13 22:23:56 +0800970 switch (CE->getOpcode()) {
971 case llvm::Instruction::GetElementPtr: {
972 // Compute the index
973 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
974 CE->op_end());
975 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
976 &Indices[0],
977 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700978
Zonr Chang932648d2010-10-13 22:23:56 +0800979 GetConstantValue(Op0, Result);
980 Result.PointerVal =
981 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700982
Zonr Chang932648d2010-10-13 22:23:56 +0800983 return;
984 }
985 case llvm::Instruction::Trunc: {
986 uint32_t BitWidth =
987 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
988
989 GetConstantValue(Op0, Result);
990 Result.IntVal = Result.IntVal.trunc(BitWidth);
991
992 return;
993 }
994 case llvm::Instruction::ZExt: {
995 uint32_t BitWidth =
996 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
997
998 GetConstantValue(Op0, Result);
999 Result.IntVal = Result.IntVal.zext(BitWidth);
1000
1001 return;
1002 }
1003 case llvm::Instruction::SExt: {
1004 uint32_t BitWidth =
1005 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1006
1007 GetConstantValue(Op0, Result);
1008 Result.IntVal = Result.IntVal.sext(BitWidth);
1009
1010 return;
1011 }
1012 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001013 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001014 GetConstantValue(Op0, Result);
1015 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1016 return;
1017 }
1018 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001019 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001020 GetConstantValue(Op0, Result);
1021 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1022 return;
1023 }
1024 case llvm::Instruction::UIToFP: {
1025 GetConstantValue(Op0, Result);
1026 if (CE->getType()->isFloatTy())
1027 Result.FloatVal =
1028 static_cast<float>(Result.IntVal.roundToDouble());
1029 else if (CE->getType()->isDoubleTy())
1030 Result.DoubleVal = Result.IntVal.roundToDouble();
1031 else if (CE->getType()->isX86_FP80Ty()) {
1032 const uint64_t zero[] = { 0, 0 };
1033 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1034 apf.convertFromAPInt(Result.IntVal,
1035 false,
1036 llvm::APFloat::rmNearestTiesToEven);
1037 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001038 }
Zonr Chang932648d2010-10-13 22:23:56 +08001039 return;
1040 }
1041 case llvm::Instruction::SIToFP: {
1042 GetConstantValue(Op0, Result);
1043 if (CE->getType()->isFloatTy())
1044 Result.FloatVal =
1045 static_cast<float>(Result.IntVal.signedRoundToDouble());
1046 else if (CE->getType()->isDoubleTy())
1047 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1048 else if (CE->getType()->isX86_FP80Ty()) {
1049 const uint64_t zero[] = { 0, 0 };
1050 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1051 apf.convertFromAPInt(Result.IntVal,
1052 true,
1053 llvm::APFloat::rmNearestTiesToEven);
1054 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001055 }
Zonr Chang932648d2010-10-13 22:23:56 +08001056 return;
1057 }
1058 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001059 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001060 case llvm::Instruction::FPToSI: {
1061 uint32_t BitWidth =
1062 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001063
Zonr Chang932648d2010-10-13 22:23:56 +08001064 GetConstantValue(Op0, Result);
1065 if (Op0->getType()->isFloatTy())
1066 Result.IntVal =
1067 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1068 else if (Op0->getType()->isDoubleTy())
1069 Result.IntVal =
1070 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1071 BitWidth);
1072 else if (Op0->getType()->isX86_FP80Ty()) {
1073 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1074 uint64_t V;
1075 bool Ignored;
1076 apf.convertToInteger(&V,
1077 BitWidth,
1078 CE->getOpcode() == llvm::Instruction::FPToSI,
1079 llvm::APFloat::rmTowardZero,
1080 &Ignored);
1081 Result.IntVal = V; // endian?
1082 }
1083 return;
1084 }
1085 case llvm::Instruction::PtrToInt: {
1086 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1087
1088 GetConstantValue(Op0, Result);
1089 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1090 (Result.PointerVal));
1091
1092 return;
1093 }
1094 case llvm::Instruction::IntToPtr: {
1095 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1096
1097 GetConstantValue(Op0, Result);
1098 if (PtrWidth != Result.IntVal.getBitWidth())
1099 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1100 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1101
1102 Result.PointerVal =
1103 llvm::PointerTy(
1104 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1105
1106 return;
1107 }
1108 case llvm::Instruction::BitCast: {
1109 GetConstantValue(Op0, Result);
1110 const llvm::Type *DestTy = CE->getType();
1111
1112 switch (Op0->getType()->getTypeID()) {
1113 case llvm::Type::IntegerTyID: {
1114 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1115 if (DestTy->isFloatTy())
1116 Result.FloatVal = Result.IntVal.bitsToFloat();
1117 else if (DestTy->isDoubleTy())
1118 Result.DoubleVal = Result.IntVal.bitsToDouble();
1119 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001120 }
Zonr Chang932648d2010-10-13 22:23:56 +08001121 case llvm::Type::FloatTyID: {
1122 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1123 Result.IntVal.floatToBits(Result.FloatVal);
1124 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001125 }
Zonr Chang932648d2010-10-13 22:23:56 +08001126 case llvm::Type::DoubleTyID: {
1127 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1128 Result.IntVal.doubleToBits(Result.DoubleVal);
1129 break;
1130 }
1131 case llvm::Type::PointerTyID: {
1132 assert(DestTy->isPointerTy() && "Invalid bitcast");
1133 break; // getConstantValue(Op0) above already converted it
1134 }
1135 default: {
1136 llvm_unreachable("Invalid bitcast operand");
1137 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001138 }
Zonr Chang932648d2010-10-13 22:23:56 +08001139 return;
1140 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001141 case llvm::Instruction::Add:
1142 case llvm::Instruction::FAdd:
1143 case llvm::Instruction::Sub:
1144 case llvm::Instruction::FSub:
1145 case llvm::Instruction::Mul:
1146 case llvm::Instruction::FMul:
1147 case llvm::Instruction::UDiv:
1148 case llvm::Instruction::SDiv:
1149 case llvm::Instruction::URem:
1150 case llvm::Instruction::SRem:
1151 case llvm::Instruction::And:
1152 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001153 case llvm::Instruction::Xor: {
1154 llvm::GenericValue LHS, RHS;
1155 GetConstantValue(Op0, LHS);
1156 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001157
Zonr Chang932648d2010-10-13 22:23:56 +08001158 switch (Op0->getType()->getTypeID()) {
1159 case llvm::Type::IntegerTyID: {
1160 switch (CE->getOpcode()) {
1161 case llvm::Instruction::Add: {
1162 Result.IntVal = LHS.IntVal + RHS.IntVal;
1163 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001164 }
Zonr Chang932648d2010-10-13 22:23:56 +08001165 case llvm::Instruction::Sub: {
1166 Result.IntVal = LHS.IntVal - RHS.IntVal;
1167 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001168 }
Zonr Chang932648d2010-10-13 22:23:56 +08001169 case llvm::Instruction::Mul: {
1170 Result.IntVal = LHS.IntVal * RHS.IntVal;
1171 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001172 }
Zonr Chang932648d2010-10-13 22:23:56 +08001173 case llvm::Instruction::UDiv: {
1174 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1175 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001176 }
Zonr Chang932648d2010-10-13 22:23:56 +08001177 case llvm::Instruction::SDiv: {
1178 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1179 break;
1180 }
1181 case llvm::Instruction::URem: {
1182 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1183 break;
1184 }
1185 case llvm::Instruction::SRem: {
1186 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1187 break;
1188 }
1189 case llvm::Instruction::And: {
1190 Result.IntVal = LHS.IntVal & RHS.IntVal;
1191 break;
1192 }
1193 case llvm::Instruction::Or: {
1194 Result.IntVal = LHS.IntVal | RHS.IntVal;
1195 break;
1196 }
1197 case llvm::Instruction::Xor: {
1198 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1199 break;
1200 }
1201 default: {
1202 llvm_unreachable("Invalid integer opcode");
1203 }
1204 }
1205 break;
1206 }
1207 case llvm::Type::FloatTyID: {
1208 switch (CE->getOpcode()) {
1209 case llvm::Instruction::FAdd: {
1210 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1211 break;
1212 }
1213 case llvm::Instruction::FSub: {
1214 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1215 break;
1216 }
1217 case llvm::Instruction::FMul: {
1218 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1219 break;
1220 }
1221 case llvm::Instruction::FDiv: {
1222 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1223 break;
1224 }
1225 case llvm::Instruction::FRem: {
1226 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1227 break;
1228 }
1229 default: {
1230 llvm_unreachable("Invalid float opcode");
1231 }
1232 }
1233 break;
1234 }
1235 case llvm::Type::DoubleTyID: {
1236 switch (CE->getOpcode()) {
1237 case llvm::Instruction::FAdd: {
1238 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1239 break;
1240 }
1241 case llvm::Instruction::FSub: {
1242 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1243 break;
1244 }
1245 case llvm::Instruction::FMul: {
1246 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1247 break;
1248 }
1249 case llvm::Instruction::FDiv: {
1250 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1251 break;
1252 }
1253 case llvm::Instruction::FRem: {
1254 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1255 break;
1256 }
1257 default: {
1258 llvm_unreachable("Invalid double opcode");
1259 }
1260 }
1261 break;
1262 }
1263 case llvm::Type::X86_FP80TyID:
1264 case llvm::Type::PPC_FP128TyID:
1265 case llvm::Type::FP128TyID: {
1266 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1267 switch (CE->getOpcode()) {
1268 case llvm::Instruction::FAdd: {
1269 apfLHS.add(llvm::APFloat(RHS.IntVal),
1270 llvm::APFloat::rmNearestTiesToEven);
1271 break;
1272 }
1273 case llvm::Instruction::FSub: {
1274 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1275 llvm::APFloat::rmNearestTiesToEven);
1276 break;
1277 }
1278 case llvm::Instruction::FMul: {
1279 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1280 llvm::APFloat::rmNearestTiesToEven);
1281 break;
1282 }
1283 case llvm::Instruction::FDiv: {
1284 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1285 llvm::APFloat::rmNearestTiesToEven);
1286 break;
1287 }
1288 case llvm::Instruction::FRem: {
1289 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1290 llvm::APFloat::rmNearestTiesToEven);
1291 break;
1292 }
1293 default: {
1294 llvm_unreachable("Invalid long double opcode");
1295 }
1296 }
1297 Result.IntVal = apfLHS.bitcastToAPInt();
1298 break;
1299 }
1300 default: {
1301 llvm_unreachable("Bad add type!");
1302 }
1303 } // End switch (Op0->getType()->getTypeID())
1304 return;
1305 }
1306 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001307 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001308 }
1309 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001310
1311 std::string msg;
1312 llvm::raw_string_ostream Msg(msg);
1313 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001314 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001315 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001316
1317 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001318 case llvm::Type::FloatTyID: {
1319 Result.FloatVal =
1320 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001321 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001322 }
1323 case llvm::Type::DoubleTyID: {
1324 Result.DoubleVal =
1325 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001326 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001327 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001328 case llvm::Type::X86_FP80TyID:
1329 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001330 case llvm::Type::PPC_FP128TyID: {
1331 Result.IntVal =
1332 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001333 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001334 }
1335 case llvm::Type::IntegerTyID: {
1336 Result.IntVal =
1337 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001338 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001339 }
1340 case llvm::Type::PointerTyID: {
1341 switch (C->getValueID()) {
1342 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001343 Result.PointerVal = NULL;
1344 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001345 }
1346 case llvm::Value::FunctionVal: {
1347 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1348 Result.PointerVal =
1349 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001350 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001351 }
1352 case llvm::Value::GlobalVariableVal: {
1353 const llvm::GlobalVariable *GV =
1354 static_cast<const llvm::GlobalVariable*>(C);
1355 Result.PointerVal =
1356 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001357 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001358 }
1359 case llvm::Value::BlockAddressVal: {
1360 assert(false && "JIT does not support address-of-label yet!");
1361 }
1362 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001363 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001364 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001365 }
1366 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001367 }
1368 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001369 std::string msg;
1370 llvm::raw_string_ostream Msg(msg);
1371 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001372 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001373 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001374 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001375 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001376 return;
1377 }
1378
Zonr Chang932648d2010-10-13 22:23:56 +08001379 // Stores the data in @Val of type @Ty at address @Addr.
1380 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001381 const llvm::Type *Ty) {
1382 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1383
Zonr Chang932648d2010-10-13 22:23:56 +08001384 switch (Ty->getTypeID()) {
1385 case llvm::Type::IntegerTyID: {
1386 const llvm::APInt &IntVal = Val.IntVal;
1387 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1388 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001389
Zonr Chang932648d2010-10-13 22:23:56 +08001390 const uint8_t *Src =
1391 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001392
Zonr Chang932648d2010-10-13 22:23:56 +08001393 if (llvm::sys::isLittleEndianHost()) {
1394 // Little-endian host - the source is ordered from LSB to MSB.
1395 // Order the destination from LSB to MSB: Do a straight copy.
1396 memcpy(Addr, Src, StoreBytes);
1397 } else {
1398 // Big-endian host - the source is an array of 64 bit words
1399 // ordered from LSW to MSW.
1400 //
1401 // Each word is ordered from MSB to LSB.
1402 //
1403 // Order the destination from MSB to LSB:
1404 // Reverse the word order, but not the bytes in a word.
1405 unsigned int i = StoreBytes;
1406 while (i > sizeof(uint64_t)) {
1407 i -= sizeof(uint64_t);
1408 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1409 Src,
1410 sizeof(uint64_t));
1411 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001412 }
Zonr Chang932648d2010-10-13 22:23:56 +08001413 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001414 }
1415 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001416 }
1417 case llvm::Type::FloatTyID: {
1418 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001419 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001420 }
1421 case llvm::Type::DoubleTyID: {
1422 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001423 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001424 }
1425 case llvm::Type::X86_FP80TyID: {
1426 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001427 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001428 }
1429 case llvm::Type::PointerTyID: {
1430 // Ensure 64 bit target pointers are fully initialized on 32 bit
1431 // hosts.
1432 if (StoreBytes != sizeof(llvm::PointerTy))
1433 memset(Addr, 0, StoreBytes);
1434 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001435 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001436 }
1437 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001438 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001439 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001440 }
1441
Zonr Chang932648d2010-10-13 22:23:56 +08001442 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1443 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1444 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001445
1446 return;
1447 }
1448
Zonr Chang932648d2010-10-13 22:23:56 +08001449 // Recursive function to apply a @Constant value into the specified memory
1450 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001451 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001452 switch (C->getValueID()) {
1453 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001454 // Nothing to do
1455 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001456 }
1457 case llvm::Value::ConstantVectorVal: {
1458 // dynamic cast may hurt performance
1459 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001460
Zonr Chang932648d2010-10-13 22:23:56 +08001461 unsigned int ElementSize = mpTD->getTypeAllocSize
1462 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001463
Zonr Chang932648d2010-10-13 22:23:56 +08001464 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1465 InitializeConstantToMemory(
1466 CP->getOperand(i),
1467 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001468 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001469 }
1470 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001471 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1472 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001473 }
1474 case llvm::Value::ConstantArrayVal: {
1475 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1476 unsigned int ElementSize = mpTD->getTypeAllocSize
1477 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001478
Zonr Chang932648d2010-10-13 22:23:56 +08001479 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1480 InitializeConstantToMemory(
1481 CPA->getOperand(i),
1482 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1483 break;
1484 }
1485 case llvm::Value::ConstantStructVal: {
1486 const llvm::ConstantStruct *CPS =
1487 static_cast<const llvm::ConstantStruct*>(C);
1488 const llvm::StructLayout *SL = mpTD->getStructLayout
1489 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001490
Zonr Chang932648d2010-10-13 22:23:56 +08001491 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1492 InitializeConstantToMemory(
1493 CPS->getOperand(i),
1494 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1495 break;
1496 }
1497 default: {
1498 if (C->getType()->isFirstClassType()) {
1499 llvm::GenericValue Val;
1500 GetConstantValue(C, Val);
1501 StoreValueToMemory(Val, Addr, C->getType());
1502 } else {
1503 llvm_unreachable("Unknown constant type to initialize memory "
1504 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001505 }
1506 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001507 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001508 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001509 return;
1510 }
1511
1512 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001513 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001514 return;
1515
Zonr Chang932648d2010-10-13 22:23:56 +08001516 // Constant pool address resolution is handled by the target itself in ARM
1517 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001518#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001519 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1520 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001521
Zonr Chang932648d2010-10-13 22:23:56 +08001522 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001523 return;
1524
1525 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1526 unsigned Align = MCP->getConstantPoolAlignment();
1527
1528 mpConstantPoolBase = allocateSpace(Size, Align);
1529 mpConstantPool = MCP;
1530
Zonr Chang932648d2010-10-13 22:23:56 +08001531 if (mpConstantPoolBase == NULL)
1532 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001533
1534 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001535 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001536 llvm::MachineConstantPoolEntry CPE = Constants[i];
1537 unsigned AlignMask = CPE.getAlignment() - 1;
1538 Offset = (Offset + AlignMask) & ~AlignMask;
1539
1540 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1541 mConstPoolAddresses.push_back(CAddr);
1542
Zonr Chang932648d2010-10-13 22:23:56 +08001543 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001544 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001545 ("Initialize memory with machine specific constant pool"
1546 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001547
1548 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1549
1550 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1551 Offset += mpTD->getTypeAllocSize(Ty);
1552 }
1553#endif
1554 return;
1555 }
1556
1557 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001558 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001559 return;
1560
Zonr Chang932648d2010-10-13 22:23:56 +08001561 const std::vector<llvm::MachineJumpTableEntry> &JT =
1562 MJTI->getJumpTables();
1563 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001564 return;
1565
1566 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001567 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001568 NumEntries += JT[i].MBBs.size();
1569
1570 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1571
Zonr Chang932648d2010-10-13 22:23:56 +08001572 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001573 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001574 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001575
1576 return;
1577 }
1578
1579 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001580 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001581 return;
1582
Zonr Chang932648d2010-10-13 22:23:56 +08001583 const std::vector<llvm::MachineJumpTableEntry> &JT =
1584 MJTI->getJumpTables();
1585 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001586 return;
1587
Zonr Chang932648d2010-10-13 22:23:56 +08001588 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1589 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1590 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001591
Zonr Chang932648d2010-10-13 22:23:56 +08001592 // For each jump table, map each target in the jump table to the
1593 // address of an emitted MachineBasicBlock.
1594 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1595 for (int i = 0, ie = JT.size(); i != ie; i++) {
1596 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1597 // Store the address of the basic block for this jump table slot in the
1598 // memory we allocated for the jump table in 'initJumpTableInfo'
1599 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001600 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1601 }
1602 }
1603
Zonr Chang932648d2010-10-13 22:23:56 +08001604 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1605 bool MayNeedFarStub) {
1606 switch (V->getValueID()) {
1607 case llvm::Value::FunctionVal: {
1608 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001609
Zonr Chang932648d2010-10-13 22:23:56 +08001610 // If we have code, go ahead and return that.
1611 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1612 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001613
Zonr Chang932648d2010-10-13 22:23:56 +08001614 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1615 // Return the function stub if it's already created.
1616 // We do this first so that:
1617 // we're returning the same address for the function as any
1618 // previous call.
1619 //
1620 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1621 // guaranteed to be close enough to call.
1622 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001623
Zonr Chang932648d2010-10-13 22:23:56 +08001624 // If we know the target can handle arbitrary-distance calls, try to
1625 // return a direct pointer.
1626 if (!MayNeedFarStub) {
1627 //
1628 // x86_64 architecture may encounter the bug:
1629 // http://llvm.org/bugs/show_bug.cgi?id=5201
1630 // which generate instruction "call" instead of "callq".
1631 //
1632 // And once the real address of stub is greater than 64-bit
1633 // long, the replacement will truncate to 32-bit resulting a
1634 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001635#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001636 // If this is an external function pointer, we can force the JIT
1637 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001638 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1639 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1640 // Changing to false because wanting to allow later calls to
1641 // mpTJI->relocate() without aborting. For caching purpose
1642 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001643#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001644 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001645
Zonr Chang932648d2010-10-13 22:23:56 +08001646 // Otherwise, we may need a to emit a stub, and, conservatively, we
1647 // always do so.
1648 return GetLazyFunctionStub(F);
1649 break;
1650 }
1651 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001652 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1653 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001654 }
1655 case llvm::Value::GlobalAliasVal: {
1656 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1657 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001658
Zonr Chang932648d2010-10-13 22:23:56 +08001659 switch (GV->getValueID()) {
1660 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001661 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001662 // code-gen'd?
1663 return GetPointerToFunction(
1664 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001665 /* AbortOnFailure = */false);
1666 // Changing to false because wanting to allow later calls to
1667 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001668 break;
1669 }
1670 case llvm::Value::GlobalVariableVal: {
1671 if (void *P = mGlobalAddressMap[GV])
1672 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001673
Zonr Chang932648d2010-10-13 22:23:56 +08001674 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1675 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001676
Zonr Chang932648d2010-10-13 22:23:56 +08001677 return mGlobalAddressMap[GV];
1678 break;
1679 }
1680 case llvm::Value::GlobalAliasVal: {
1681 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001682 }
1683 }
1684 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001685 }
1686 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001687 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001688 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001689 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001690 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001691 }
1692
Zonr Chang932648d2010-10-13 22:23:56 +08001693 // If the specified function has been code-gen'd, return a pointer to the
1694 // function. If not, compile it, or use a stub to implement lazy compilation
1695 // if available.
1696 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1697 // If we have already code generated the function, just return the
1698 // address.
1699 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001700 return Addr;
1701
Zonr Chang932648d2010-10-13 22:23:56 +08001702 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001703 return GetLazyFunctionStub(F);
1704 }
1705
Zonr Chang932648d2010-10-13 22:23:56 +08001706 typedef llvm::DenseMap<const llvm::Function*,
1707 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001708 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1709
Zonr Chang932648d2010-10-13 22:23:56 +08001710 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001711 return mFunctionToLazyStubMap.lookup(F);
1712 }
1713
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001714 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001715 void *GetLazyFunctionStub(llvm::Function *F) {
1716 // If we already have a lazy stub for this function, recycle it.
1717 void *&Stub = mFunctionToLazyStubMap[F];
1718 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001719 return Stub;
1720
Zonr Chang932648d2010-10-13 22:23:56 +08001721 // In any cases, we should NOT resolve function at runtime (though we are
1722 // able to). We resolve this right now.
1723 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001724 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1725 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1726 // Changing to false because wanting to allow later calls to
1727 // mpTJI->relocate() without aborting. For caching purpose
1728 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001729
Zonr Chang932648d2010-10-13 22:23:56 +08001730 // Codegen a new stub, calling the actual address of the external
1731 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001732 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1733 startGVStub(F, SL.Size, SL.Alignment);
1734 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1735 finishGVStub();
1736
Zonr Chang932648d2010-10-13 22:23:56 +08001737 // We really want the address of the stub in the GlobalAddressMap for the
1738 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001739 UpdateGlobalMapping(F, Stub);
1740
Zonr Chang932648d2010-10-13 22:23:56 +08001741 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001742 PendingFunctions.insert(F);
1743 else
Zonr Chang932648d2010-10-13 22:23:56 +08001744 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1745 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001746
1747 return Stub;
1748 }
1749
Zonr Chang932648d2010-10-13 22:23:56 +08001750 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1751 void *Addr = GetPointerToGlobalIfAvailable(F);
1752 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001753 return Addr;
1754
1755 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1756 "Internal error: only external defined function routes here!");
1757
Zonr Chang932648d2010-10-13 22:23:56 +08001758 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001759 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001760 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001761
Zonr Chang932648d2010-10-13 22:23:56 +08001762 // If we resolved the symbol to a null address (eg. a weak external)
1763 // return a null pointer let the application handle it.
1764 if (Addr == NULL) {
1765 if (AbortOnFailure)
1766 llvm::report_fatal_error("Could not resolve external function "
1767 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001768 else
1769 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001770 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001771
1772 AddGlobalMapping(F, Addr);
1773
1774 return Addr;
1775 }
1776
Zonr Chang932648d2010-10-13 22:23:56 +08001777 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001778 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001779 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001780 return Addr;
1781
Zonr Chang932648d2010-10-13 22:23:56 +08001782 if (mpSymbolLookupFn)
1783 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001784 return Addr;
1785
Zonr Chang932648d2010-10-13 22:23:56 +08001786 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001787 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001788 "' which could not be resolved!");
1789
1790 return NULL;
1791 }
1792
Zonr Chang932648d2010-10-13 22:23:56 +08001793 // Return the address of the specified global variable, possibly emitting it
1794 // to memory if needed. This is used by the Emitter.
1795 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1796 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1797 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001798 return Ptr;
1799
Zonr Chang932648d2010-10-13 22:23:56 +08001800 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1801 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001802 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1803 AddGlobalMapping(GV, Ptr);
1804 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001805 // If the global hasn't been emitted to memory yet, allocate space and
1806 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001807 Ptr = GetMemoryForGV(GV);
1808 AddGlobalMapping(GV, Ptr);
1809 EmitGlobalVariable(GV);
1810 }
1811
1812 return Ptr;
1813 }
1814
Zonr Chang932648d2010-10-13 22:23:56 +08001815 // This method abstracts memory allocation of global variable so that the
1816 // JIT can allocate thread local variables depending on the target.
1817 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1818 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001819
Zonr Chang932648d2010-10-13 22:23:56 +08001820 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001821 size_t S = mpTD->getTypeAllocSize(GlobalType);
1822 size_t A = mpTD->getPreferredAlignment(GV);
1823
Zonr Chang932648d2010-10-13 22:23:56 +08001824 if (GV->isThreadLocal()) {
1825 // We can support TLS by
1826 //
1827 // Ptr = TJI.allocateThreadLocalMemory(S);
1828 //
1829 // But I tend not to.
1830 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001831 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001832 ("Compilation of Thread Local Storage (TLS) is disabled!");
1833
Zonr Chang932648d2010-10-13 22:23:56 +08001834 } else if (mpTJI->allocateSeparateGVMemory()) {
1835 if (A <= 8) {
1836 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001837 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001838 // Allocate (S + A) bytes of memory, then use an aligned pointer
1839 // within that space.
1840 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001841 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001842 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1843 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001844 }
1845 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001846 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001847 }
1848
1849 return Ptr;
1850 }
1851
1852 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001853 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001854
Zonr Chang932648d2010-10-13 22:23:56 +08001855 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001856 llvm::report_fatal_error
1857 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001858
Zonr Chang932648d2010-10-13 22:23:56 +08001859 if (GA == NULL) {
1860 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001861 GA = GetMemoryForGV(GV);
1862 AddGlobalMapping(GV, GA);
1863 }
1864
1865 InitializeConstantToMemory(GV->getInitializer(), GA);
1866
Zonr Chang932648d2010-10-13 22:23:56 +08001867 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001868 return;
1869 }
1870
1871 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1872 > GlobalToIndirectSymMapTy;
1873 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1874
Zonr Chang932648d2010-10-13 22:23:56 +08001875 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1876 // Make sure GV is emitted first, and create a stub containing the fully
1877 // resolved address.
1878 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001879
Zonr Chang932648d2010-10-13 22:23:56 +08001880 // If we already have a stub for this global variable, recycle it.
1881 void *&IndirectSym = GlobalToIndirectSymMap[V];
1882 // Otherwise, codegen a new indirect symbol.
1883 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001884 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1885
1886 return IndirectSym;
1887 }
1888
Zonr Chang932648d2010-10-13 22:23:56 +08001889 // This is the equivalent of FunctionToLazyStubMap for external functions.
1890 //
1891 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1892 // It's actually here to make it more likely that far calls
1893 // succeed, but no single stub can guarantee that. I'll
1894 // remove this in a subsequent checkin when I actually fix
1895 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001896 std::map<void*, void*> ExternalFnToStubMap;
1897
Zonr Chang932648d2010-10-13 22:23:56 +08001898 // Return a stub for the function at the specified address.
1899 void *GetExternalFunctionStub(void *FnAddr) {
1900 void *&Stub = ExternalFnToStubMap[FnAddr];
1901 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001902 return Stub;
1903
1904 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1905 startGVStub(0, SL.Size, SL.Alignment);
1906 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1907 finishGVStub();
1908
1909 return Stub;
1910 }
1911
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001912#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001913 const llvm::MCAsmInfo *mpAsmInfo;
1914 const llvm::MCDisassembler *mpDisassmbler;
1915 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001916
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001917 class BufferMemoryObject : public llvm::MemoryObject {
1918 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001919 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001920 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001921
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001922 public:
1923 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1924 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001925
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001926 uint64_t getBase() const { return 0; }
1927 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001928
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001929 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001930 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001931 return -1;
1932 *Byte = mBytes[Addr];
1933 return 0;
1934 }
1935 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001936
Zonr Chang932648d2010-10-13 22:23:56 +08001937 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001938 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001939 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001940#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001941 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001942 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1943 ErrorInfo,
1944 llvm::raw_fd_ostream::F_Append);
1945 if (!ErrorInfo.empty()) { // some errors occurred
1946 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001947 delete OS;
1948 return;
1949 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001950#else
1951 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001952#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001953 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1954 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001955
Zonr Chang932648d2010-10-13 22:23:56 +08001956 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001957 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001958 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001959 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001960 if (mpIP == NULL)
1961 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1962 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001963
Zonr Chang932648d2010-10-13 22:23:56 +08001964 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1965 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001966 uint64_t Size;
1967 uint64_t Index;
1968
Zonr Chang932648d2010-10-13 22:23:56 +08001969 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001970 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001971
Zonr Chang932648d2010-10-13 22:23:56 +08001972 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1973 /* REMOVED */ llvm::nulls())) {
1974 (*OS).indent(4)
1975 .write("0x", 2)
1976 .write_hex((uint32_t) Start + Index)
1977 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001978 mpIP->printInst(&Inst, *OS);
1979 *OS << "\n";
1980 } else {
1981 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08001982 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001983 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001984 }
1985
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001986 *OS << "\n";
1987 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001988
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001989#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08001990 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001991 OS->close();
1992 delete OS;
1993#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001994 return;
1995 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001996#else
Zonr Chang932648d2010-10-13 22:23:56 +08001997 inline void Disassemble(const std::string &Name, uint8_t *Start,
1998 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001999 return;
2000 }
Zonr Chang932648d2010-10-13 22:23:56 +08002001#endif // defined(USE_DISASSEMBLER)
2002
2003 // Resolver to undefined symbol in CodeEmitter
2004 BCCSymbolLookupFn mpSymbolLookupFn;
2005 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002006
2007 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002008 // Will take the ownership of @MemMgr
2009 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2010 : mpMemMgr(pMemMgr),
2011 mpTarget(NULL),
2012 mpTJI(NULL),
2013 mpTD(NULL),
2014 mpCurEmitFunction(NULL),
2015 mpConstantPool(NULL),
2016 mpJumpTable(NULL),
2017 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002018#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002019 mpAsmInfo(NULL),
2020 mpDisassmbler(NULL),
2021 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002022#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002023 mpSymbolLookupFn(NULL),
2024 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002025 return;
2026 }
2027
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002028 inline global_addresses_const_iterator global_address_begin() const {
2029 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002030 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002031 inline global_addresses_const_iterator global_address_end() const {
2032 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002033 }
2034
Zonr Chang932648d2010-10-13 22:23:56 +08002035 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002036 mpSymbolLookupFn = pFn;
2037 mpSymbolLookupContext = pContext;
2038 return;
2039 }
2040
Zonr Chang932648d2010-10-13 22:23:56 +08002041 void setTargetMachine(llvm::TargetMachine &TM) {
2042 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002043 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002044 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002045 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002046 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002047 mpTD = TM.getTargetData();
2048
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002049 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2050
2051 return;
2052 }
2053
Zonr Chang932648d2010-10-13 22:23:56 +08002054 // This callback is invoked when the specified function is about to be code
2055 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002056 void startFunction(llvm::MachineFunction &F) {
2057 uintptr_t ActualSize = 0;
2058
2059 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002060
2061 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2062 // MachineCodeEmitter, which is the super class of the class
2063 // JITCodeEmitter.
2064 //
2065 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2066 // allocated for this code buffer.
2067 //
2068 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2069 // code. This is guranteed to be in the range
2070 // [BufferBegin, BufferEnd]. If this pointer is at
2071 // BufferEnd, it will never move due to code emission, and
2072 // all code emission requests will be ignored (this is the
2073 // buffer overflow condition).
2074 BufferBegin = CurBufferPtr =
2075 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002076 BufferEnd = BufferBegin + ActualSize;
2077
Zonr Chang932648d2010-10-13 22:23:56 +08002078 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002079 mpCurEmitFunction = new EmittedFunctionCode();
2080 mpCurEmitFunction->FunctionBody = BufferBegin;
2081
Zonr Chang932648d2010-10-13 22:23:56 +08002082 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002083 emitAlignment(16);
2084
2085 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002086 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002087 initJumpTableInfo(MJTI);
2088
Zonr Chang932648d2010-10-13 22:23:56 +08002089 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002090 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2091
2092 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2093
2094 mpCurEmitFunction->Code = CurBufferPtr;
2095
2096 mMBBLocations.clear();
2097
2098 return;
2099 }
2100
Zonr Chang932648d2010-10-13 22:23:56 +08002101 // This callback is invoked when the specified function has finished code
2102 // generation. If a buffer overflow has occurred, this method returns true
2103 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002104 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002105 if (CurBufferPtr == BufferEnd) {
2106 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002107 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2108 return false;
2109 }
2110
Zonr Chang932648d2010-10-13 22:23:56 +08002111 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002112 emitJumpTableInfo(MJTI);
2113
Zonr Chang932648d2010-10-13 22:23:56 +08002114 // FnStart is the start of the text, not the start of the constant pool
2115 // and other per-function data.
2116 uint8_t *FnStart =
2117 reinterpret_cast<uint8_t*>(
2118 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002119
Zonr Chang932648d2010-10-13 22:23:56 +08002120 // FnEnd is the end of the function's machine code.
2121 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002122
Zonr Chang932648d2010-10-13 22:23:56 +08002123 if (!mRelocations.empty()) {
2124 // Resolve the relocations to concrete pointers.
2125 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2126 llvm::MachineRelocation &MR = mRelocations[i];
2127 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002128
Zonr Chang932648d2010-10-13 22:23:56 +08002129 if (!MR.letTargetResolve()) {
2130 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002131 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Zonr Chang932648d2010-10-13 22:23:56 +08002132 if (MR.mayNeedFarStub())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002133 ResultPtr = GetExternalFunctionStub(ResultPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002134 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002135 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2136 BufferBegin
2137 + MR.getMachineCodeOffset(),
2138 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002139 } else if (MR.isIndirectSymbol()) {
2140 ResultPtr =
2141 GetPointerToGVIndirectSym(
2142 MR.getGlobalValue(),
2143 BufferBegin + MR.getMachineCodeOffset());
2144 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002145 ResultPtr =
2146 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002147 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002148 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002149 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002150 } else {
2151 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2152 ResultPtr =
2153 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2154 }
2155
2156 MR.setResultPointer(ResultPtr);
2157 }
2158 }
2159
2160 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2161 mpMemMgr->getGOTBase());
2162 }
2163
2164 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002165 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2166 // global variables that were referenced in the relocations.
2167 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002168 return false;
2169
Zonr Chang932648d2010-10-13 22:23:56 +08002170 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002171 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2172 BufferBegin = CurBufferPtr = 0;
2173
Zonr Chang932648d2010-10-13 22:23:56 +08002174 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002175 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2176 mpCurEmitFunction = NULL;
2177
2178 mRelocations.clear();
2179 mConstPoolAddresses.clear();
2180
Zonr Chang932648d2010-10-13 22:23:56 +08002181 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002182 mpMMI->EndFunction();
2183
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002184 updateFunctionStub(F.getFunction());
2185
Zonr Chang932648d2010-10-13 22:23:56 +08002186 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002187 mpMemMgr->setMemoryExecutable();
2188
2189 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2190
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002191 return false;
2192 }
2193
Zonr Chang932648d2010-10-13 22:23:56 +08002194 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002195 unsigned Alignment) {
2196 mpSavedBufferBegin = BufferBegin;
2197 mpSavedBufferEnd = BufferEnd;
2198 mpSavedCurBufferPtr = CurBufferPtr;
2199
2200 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2201 Alignment);
2202 BufferEnd = BufferBegin + StubSize + 1;
2203
2204 return;
2205 }
2206
Zonr Chang932648d2010-10-13 22:23:56 +08002207 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002208 mpSavedBufferBegin = BufferBegin;
2209 mpSavedBufferEnd = BufferEnd;
2210 mpSavedCurBufferPtr = CurBufferPtr;
2211
Zonr Chang932648d2010-10-13 22:23:56 +08002212 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002213 BufferEnd = BufferBegin + StubSize + 1;
2214
2215 return;
2216 }
2217
2218 void finishGVStub() {
2219 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2220
Zonr Chang932648d2010-10-13 22:23:56 +08002221 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002222 BufferBegin = mpSavedBufferBegin;
2223 BufferEnd = mpSavedBufferEnd;
2224 CurBufferPtr = mpSavedCurBufferPtr;
2225
2226 return;
2227 }
2228
Zonr Chang932648d2010-10-13 22:23:56 +08002229 // Allocates and fills storage for an indirect GlobalValue, and returns the
2230 // address.
2231 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002232 const uint8_t *Buffer, size_t Size,
2233 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002234 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002235 memcpy(IndGV, Buffer, Size);
2236 return IndGV;
2237 }
2238
Zonr Chang932648d2010-10-13 22:23:56 +08002239 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002240 void emitLabel(llvm::MCSymbol *Label) {
2241 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002242 return;
2243 }
2244
Zonr Chang932648d2010-10-13 22:23:56 +08002245 // Allocate memory for a global. Unlike allocateSpace, this method does not
2246 // allocate memory in the current output buffer, because a global may live
2247 // longer than the current function.
2248 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2249 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002250 return mpMemMgr->allocateGlobal(Size, Alignment);
2251 }
2252
Zonr Chang932648d2010-10-13 22:23:56 +08002253 // This should be called by the target when a new basic block is about to be
2254 // emitted. This way the MCE knows where the start of the block is, and can
2255 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002256 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002257 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002258 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2259 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2260 return;
2261 }
2262
Zonr Chang932648d2010-10-13 22:23:56 +08002263 // Whenever a relocatable address is needed, it should be noted with this
2264 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002265 void addRelocation(const llvm::MachineRelocation &MR) {
2266 mRelocations.push_back(MR);
2267 return;
2268 }
2269
Zonr Chang932648d2010-10-13 22:23:56 +08002270 // Return the address of the @Index entry in the constant pool that was
2271 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002272 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2273 assert(Index < mpConstantPool->getConstants().size() &&
2274 "Invalid constant pool index!");
2275 return mConstPoolAddresses[Index];
2276 }
2277
Zonr Chang932648d2010-10-13 22:23:56 +08002278 // Return the address of the jump table with index @Index in the function
2279 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002280 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002281 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002282 mpJumpTable->getJumpTables();
2283
Zonr Chang932648d2010-10-13 22:23:56 +08002284 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002285
2286 unsigned int Offset = 0;
2287 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2288
Zonr Chang932648d2010-10-13 22:23:56 +08002289 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002290 Offset += JT[i].MBBs.size();
2291 Offset *= EntrySize;
2292
Zonr Chang932648d2010-10-13 22:23:56 +08002293 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002294 }
2295
Zonr Chang932648d2010-10-13 22:23:56 +08002296 // Return the address of the specified MachineBasicBlock, only usable after
2297 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002298 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2299 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002300 mMBBLocations[MBB->getNumber()] &&
2301 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002302 return mMBBLocations[MBB->getNumber()];
2303 }
2304
Zonr Chang932648d2010-10-13 22:23:56 +08002305 // Return the address of the specified LabelID, only usable after the
2306 // LabelID has been emitted.
2307 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002308 assert(mLabelLocations.count(Label) && "Label not emitted!");
2309 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002310 }
2311
Zonr Chang932648d2010-10-13 22:23:56 +08002312 // Specifies the MachineModuleInfo object. This is used for exception
2313 // handling purposes.
2314 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002315 mpMMI = Info;
2316 return;
2317 }
2318
Zonr Chang932648d2010-10-13 22:23:56 +08002319 void updateFunctionStub(const llvm::Function *F) {
2320 // Get the empty stub we generated earlier.
2321 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002322 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002323 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002324 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002325 else
2326 return;
2327
Zonr Chang932648d2010-10-13 22:23:56 +08002328 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002329
2330 assert(Addr != Stub &&
2331 "Function must have non-stub address to be updated.");
2332
Zonr Chang932648d2010-10-13 22:23:56 +08002333 // Tell the target jit info to rewrite the stub at the specified address,
2334 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002335 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2336 startGVStub(Stub, SL.Size);
2337 mpTJI->emitFunctionStub(F, Addr, *this);
2338 finishGVStub();
2339
Zonr Chang932648d2010-10-13 22:23:56 +08002340 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2341 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002342
2343 PendingFunctions.erase(I);
2344
2345 return;
2346 }
2347
Zonr Chang932648d2010-10-13 22:23:56 +08002348 // Once you finish the compilation on a translation unit, you can call this
2349 // function to recycle the memory (which is used at compilation time and not
2350 // needed for runtime).
2351 //
2352 // NOTE: You should not call this funtion until the code-gen passes for a
2353 // given module is done. Otherwise, the results is undefined and may
2354 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002355 void releaseUnnecessary() {
2356 mMBBLocations.clear();
2357 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002358 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002359 mFunctionToLazyStubMap.clear();
2360 GlobalToIndirectSymMap.clear();
2361 ExternalFnToStubMap.clear();
2362 PendingFunctions.clear();
2363
2364 return;
2365 }
2366
2367 void reset() {
2368 releaseUnnecessary();
2369
2370 mpSymbolLookupFn = NULL;
2371 mpSymbolLookupContext = NULL;
2372
2373 mpTJI = NULL;
2374 mpTD = NULL;
2375
Zonr Chang932648d2010-10-13 22:23:56 +08002376 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2377 E = mEmittedFunctions.end();
2378 I != E;
2379 I++)
2380 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002381 delete I->second;
2382 mEmittedFunctions.clear();
2383
2384 mpMemMgr->reset();
2385
2386 return;
2387 }
2388
Zonr Chang932648d2010-10-13 22:23:56 +08002389 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002390 return lookup( llvm::StringRef(Name) );
2391 }
2392
Zonr Chang932648d2010-10-13 22:23:56 +08002393 void *lookup(const llvm::StringRef &Name) {
2394 EmittedFunctionsMapTy::const_iterator I =
2395 mEmittedFunctions.find(Name.str());
2396 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002397 return NULL;
2398 else
2399 return I->second->Code;
2400 }
2401
Zonr Chang932648d2010-10-13 22:23:56 +08002402 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002403 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002404 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002405 int functionCount = mEmittedFunctions.size();
2406
Zonr Chang932648d2010-10-13 22:23:56 +08002407 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002408 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002409 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002410 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002411 if (functions)
2412 for (EmittedFunctionsMapTy::const_iterator
2413 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2414 (I != E) && (functionCount > 0);
2415 I++, functionCount--)
2416 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002417
2418 return;
2419 }
2420
Zonr Chang932648d2010-10-13 22:23:56 +08002421 void getFunctionBinary(BCCchar *label,
2422 BCCvoid **base,
2423 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002424 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002425 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002426 *base = NULL;
2427 *length = 0;
2428 } else {
2429 *base = I->second->Code;
2430 *length = I->second->Size;
2431 }
2432 return;
2433 }
2434
2435 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002436 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002437#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002438 delete mpAsmInfo;
2439 delete mpDisassmbler;
2440 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002441#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002442 return;
2443 }
Zonr Chang932648d2010-10-13 22:23:56 +08002444 };
2445 // End of Class CodeEmitter
2446 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002447
Zonr Chang932648d2010-10-13 22:23:56 +08002448 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002449 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002450 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002451 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2452 return mCodeEmitter.get();
2453 }
2454
2455 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002456 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002457
Zonr Chang932648d2010-10-13 22:23:56 +08002458 llvm::LLVMContext *mContext;
2459 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002460
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002461 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002462
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002463 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002464 Compiler()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002465 : mNeverCache(true),
2466 mCacheNew(false),
2467 mCacheFd(-1),
2468 mCacheMapAddr(NULL),
2469 mCacheHdr(NULL),
2470 mCacheDiff(0),
2471 mCodeDataAddr(NULL),
2472 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002473 mpSymbolLookupContext(NULL),
2474 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002475 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002476 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002477 llvm::remove_fatal_error_handler();
2478 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002479 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002480 return;
2481 }
2482
Zonr Chang932648d2010-10-13 22:23:56 +08002483 // interface for BCCscript::registerSymbolCallback()
2484 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002485 mpSymbolLookupFn = pFn;
2486 mpSymbolLookupContext = pContext;
2487 return;
2488 }
2489
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002490 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002491 GlobalInitialization();
2492 mModule = module;
2493 return hasError();
2494 }
2495
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002496 int readBC(const char *bitcode,
2497 size_t bitcodeSize,
2498 const BCCchar *resName) {
2499 GlobalInitialization();
2500
2501 if (resName) {
2502 // Turn off the default NeverCaching mode
2503 mNeverCache = false;
2504
2505 // TODO(sliao):
2506 mNeverCache = true;
2507#if 0
2508
2509 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2510 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2511 return -mCacheFd;
2512 }
2513#endif
2514 }
2515
2516 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002517
Zonr Chang932648d2010-10-13 22:23:56 +08002518 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002519 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002520
Zonr Chang932648d2010-10-13 22:23:56 +08002521 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002522 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002523 llvm::StringRef(bitcode, bitcodeSize)));
2524
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002525 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002526 setError("Error reading input program bitcode into memory");
2527 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002528 }
2529
Zonr Chang932648d2010-10-13 22:23:56 +08002530 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002531 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2532 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002533 return hasError();
2534 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002535
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002536 int linkBC(const char *bitcode, size_t bitcodeSize) {
2537 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002538
2539 if (bitcode == NULL || bitcodeSize <= 0)
2540 return 0;
2541
2542 if (mModule == NULL) {
2543 setError("No module presents for linking");
2544 return hasError();
2545 }
2546
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002547 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002548 llvm::StringRef(bitcode, bitcodeSize)));
2549
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002550 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002551 setError("Error reading input library bitcode into memory");
2552 return hasError();
2553 }
2554
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002555 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002556 *mContext,
2557 &mError));
2558 if (Lib.get() == NULL)
2559 return hasError();
2560
2561 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2562 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002563
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002564 // Everything for linking should be settled down here with no error occurs
2565 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002566 return hasError();
2567 }
2568
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002569
2570 // interface for bccLoadBinary()
2571 int loader() {
2572 // Check File Descriptor
2573 if (mCacheFd < 0) {
2574 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2575 goto giveup;
2576 }
2577
2578
2579 // Check File Size
2580 struct stat statCacheFd;
2581 if (fstat(mCacheFd, &statCacheFd) < 0) {
2582 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2583 goto giveup;
2584 }
2585
2586 if (statCacheFd.st_size < sizeof(oBCCHeader) ||
2587 statCacheFd.st_size <= MaxCodeSize + MaxGlobalVarSize) {
2588 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2589 goto giveup;
2590 }
2591
2592
2593 // Read File Content
2594 {
2595#ifdef BCC_CODE_ADDR
2596 off_t heuristicCodeOffset =
2597 statCacheFd.st_size - MaxCodeSize - MaxGlobalVarSize;
2598
2599 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2600 MaxCodeSize + MaxGlobalVarSize,
2601 PROT_READ | PROT_EXEC | PROT_WRITE,
2602 MAP_PRIVATE | MAP_FIXED,
2603 mCacheFd, heuristicCodeOffset);
2604
2605 if (mCodeDataAddr == MAP_FAILED) {
2606 LOGE("unable to mmap .oBBC cache code/data: %s\n", strerror(errno));
2607 flock(mCacheFd, LOCK_UN);
2608 goto giveup;
2609 }
2610
2611 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
2612
2613 if (!mCacheMapAddr) {
2614 flock(mCacheFd, LOCK_UN);
2615 LOGE("allocation failed.\n");
2616 // TODO(all)
2617 goto bail;
2618 }
2619
2620 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2621 heuristicCodeOffset));
2622
2623 flock(mCacheFd, LOCK_UN);
2624
2625 if (nread != (size_t)heuristicCodeOffset) {
2626 LOGE("read(mCacheFd) failed\n");
2627 free(mCacheMapAddr);
2628 goto bail;
2629 }
2630
2631 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
2632
2633 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2634 LOGE("assertion failed: heuristic code offset is not correct.\n");
2635 goto bail;
2636 }
2637#else
2638 mCacheMapAddr = (char *) mmap(0, statCacheFd.st_size,
2639 PROT_READ | PROT_EXEC | PROT_WRITE,
2640 MAP_PRIVATE, mCacheFd, 0);
2641
2642 if (mCodeDataAddr == MAP_FAILED) {
2643 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2644 flock(mCacheFd, LOCK_UN);
2645 goto giveup;
2646 }
2647
2648 flock(mCacheFd, LOCK_UN);
2649
2650 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
2651
2652 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2653#endif
2654 }
2655
2656
2657 // Verify the Cache File
2658 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2659 LOGE("bad magic word\n");
2660 goto bail;
2661 }
2662
2663 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2664 LOGE("bad oBCC version 0x%08x\n",
2665 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2666 goto bail;
2667 }
2668
2669 if (statCacheFd.st_size < mCacheHdr->relocOffset +
2670 mCacheHdr->relocCount * sizeof(uint32_t) * 2) {
2671 LOGE("relocate table overflow\n");
2672 goto bail;
2673 }
2674
2675 if (statCacheFd.st_size < mCacheHdr->exportVarsOffset +
2676 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
2677 LOGE("export variables table overflow\n");
2678 goto bail;
2679 }
2680
2681 if (statCacheFd.st_size < mCacheHdr->exportFuncsOffset +
2682 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
2683 LOGE("export functions table overflow\n");
2684 goto bail;
2685 }
2686
2687 if (statCacheFd.st_size <
2688 mCacheHdr->exportPragmasOffset +
2689 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
2690 LOGE("export pragmas table overflow\n");
2691 goto bail;
2692 }
2693
2694 if (statCacheFd.st_size < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
2695 LOGE("code cache overflow\n");
2696 goto bail;
2697 }
2698
2699 if (statCacheFd.st_size < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
2700 LOGE("data (global variable) cache overflow\n");
2701 goto bail;
2702 }
2703
2704
2705 // Relocate
2706 {
2707 mCacheDiff = mCodeDataAddr -
2708 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2709
2710#ifdef BCC_CODE_ADDR
2711 if (mCacheDiff != 0) {
2712 LOGE("mCacheDiff should be zero but mCacheDiff = %d\n", mCacheDiff);
2713 goto bail;
2714 }
2715#else
2716 mCacheHdr->rootAddr += mCacheDiff;
2717 mCacheHdr->initAddr += mCacheDiff;
2718
2719 uint32_t *relocTable =
2720 reinterpret_cast<uint32_t *>(mCacheMapAddr + mCacheHdr->relocOffset);
2721
2722 // Read in the relocs
2723 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2724 // TODO(all): Patch the hole
2725
2726 //char *holeAddr = reinterpret_cast<char *>(*relocTable++) + mCacheDiff;
2727 //uint32_t holeTy = *relocTable++;
2728
2729 //patch(...); I.e., holeAddr += mCacheDiff
2730 }
2731#endif
2732 }
2733
2734 return 0;
2735
2736 bail:
2737#ifdef BCC_CODE_ADDR
2738 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2739 LOGE("munmap failed: %s\n", strerror(errno));
2740 }
2741
2742 if (mCacheMapAddr) {
2743 free(mCacheMapAddr);
2744 }
2745#else
2746 if (munmap(mCacheMapAddr, statCacheFd.st_size) != 0) {
2747 LOGE("munmap failed: %s\n", strerror(errno));
2748 }
2749#endif
2750
2751 giveup:
2752 return 1;
2753 }
2754
2755 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002756 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002757 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002758
Zonr Chang932648d2010-10-13 22:23:56 +08002759 llvm::TargetMachine *TM = NULL;
2760 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002761 std::string FeaturesStr;
2762
Zonr Chang932648d2010-10-13 22:23:56 +08002763 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002764
Zonr Chang932648d2010-10-13 22:23:56 +08002765 const llvm::NamedMDNode *PragmaMetadata;
2766 const llvm::NamedMDNode *ExportVarMetadata;
2767 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002768
Zonr Chang932648d2010-10-13 22:23:56 +08002769 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002770 return 0;
2771
Zonr Chang932648d2010-10-13 22:23:56 +08002772 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002773 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002774 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002775 goto on_bcc_compile_error;
2776
Zonr Chang932648d2010-10-13 22:23:56 +08002777 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002778 llvm::SubtargetFeatures F;
2779 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002780 for (std::vector<std::string>::const_iterator I = Features.begin(),
2781 E = Features.end();
2782 I != E;
2783 I++)
2784 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002785 FeaturesStr = F.getString();
2786 }
2787
2788 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002789 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002790 setError("Failed to create target machine implementation for the"
2791 " specified triple '" + Triple + "'");
2792 goto on_bcc_compile_error;
2793 }
2794
Zonr Chang932648d2010-10-13 22:23:56 +08002795 // Create memory manager for creation of code emitter later.
2796 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002797 setError("Failed to startup memory management for further compilation");
2798 goto on_bcc_compile_error;
2799 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002800 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002801
Zonr Chang932648d2010-10-13 22:23:56 +08002802 // Create code emitter
2803 if (!mCodeEmitter.get()) {
2804 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002805 setError("Failed to create machine code emitter to complete"
2806 " the compilation");
2807 goto on_bcc_compile_error;
2808 }
2809 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002810 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002811 mCodeEmitter->reset();
2812 }
2813
2814 mCodeEmitter->setTargetMachine(*TM);
2815 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2816 mpSymbolLookupContext);
2817
Zonr Chang932648d2010-10-13 22:23:56 +08002818 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002819 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002820
Zonr Chang5d35b972010-10-23 14:36:47 +08002821 // Load named metadata
2822 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2823 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2824 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2825
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002826 // Create LTO passes and run them on the mModule
2827 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002828 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002829 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08002830 LTOPasses.add(new llvm::TargetData(*TD));
2831
2832 std::vector<const char*> ExportSymbols;
2833
2834 // A workaround for getting export variable and function name. Will refine
2835 // it soon.
2836 if (ExportVarMetadata) {
2837 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2838 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2839 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2840 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2841 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2842 llvm::StringRef ExportVarName =
2843 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2844 ExportSymbols.push_back(ExportVarName.data());
2845 }
2846 }
2847 }
2848 }
2849
2850 if (ExportFuncMetadata) {
2851 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2852 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2853 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2854 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2855 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2856 llvm::StringRef ExportFuncName =
2857 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2858 ExportSymbols.push_back(ExportFuncName.data());
2859 }
2860 }
2861 }
2862 }
2863 // root() and init() are born to be exported
2864 ExportSymbols.push_back("root");
2865 ExportSymbols.push_back("init");
2866
Zonr Change5c7a542010-10-24 01:07:27 +08002867 // We now create passes list performing LTO. These are copied from
2868 // (including comments) llvm::createStandardLTOPasses().
2869
2870 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08002871 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002872
Zonr Change5c7a542010-10-24 01:07:27 +08002873 // Propagate constants at call sites into the functions they call. This
2874 // opens opportunities for globalopt (and inlining) by substituting
2875 // function pointers passed as arguments to direct uses of functions.
2876 LTOPasses.add(llvm::createIPSCCPPass());
2877
2878 // Now that we internalized some globals, see if we can hack on them!
2879 LTOPasses.add(llvm::createGlobalOptimizerPass());
2880
2881 // Linking modules together can lead to duplicated global constants, only
2882 // keep one copy of each constant...
2883 LTOPasses.add(llvm::createConstantMergePass());
2884
2885 // Remove unused arguments from functions...
2886 LTOPasses.add(llvm::createDeadArgEliminationPass());
2887
2888 // Reduce the code after globalopt and ipsccp. Both can open up
2889 // significant simplification opportunities, and both can propagate
2890 // functions through function pointers. When this happens, we often have
2891 // to resolve varargs calls, etc, so let instcombine do this.
2892 LTOPasses.add(llvm::createInstructionCombiningPass());
2893
2894 // Inline small functions
2895 LTOPasses.add(llvm::createFunctionInliningPass());
2896
2897 // Remove dead EH info.
2898 LTOPasses.add(llvm::createPruneEHPass());
2899
2900 // Internalize the globals again after inlining
2901 LTOPasses.add(llvm::createGlobalOptimizerPass());
2902
2903 // Remove dead functions.
2904 LTOPasses.add(llvm::createGlobalDCEPass());
2905
2906 // If we didn't decide to inline a function, check to see if we can
2907 // transform it to pass arguments by value instead of by reference.
2908 LTOPasses.add(llvm::createArgumentPromotionPass());
2909
2910 // The IPO passes may leave cruft around. Clean up after them.
2911 LTOPasses.add(llvm::createInstructionCombiningPass());
2912 LTOPasses.add(llvm::createJumpThreadingPass());
2913
2914 // Break up allocas
2915 LTOPasses.add(llvm::createScalarReplAggregatesPass());
2916
2917 // Run a few AA driven optimizations here and now, to cleanup the code.
2918 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
2919 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
2920
2921 // Hoist loop invariants.
2922 LTOPasses.add(llvm::createLICMPass());
2923
2924 // Remove redundancies.
2925 LTOPasses.add(llvm::createGVNPass());
2926
2927 // Remove dead memcpys.
2928 LTOPasses.add(llvm::createMemCpyOptPass());
2929
2930 // Nuke dead stores.
2931 LTOPasses.add(llvm::createDeadStoreEliminationPass());
2932
2933 // Cleanup and simplify the code after the scalar optimizations.
2934 LTOPasses.add(llvm::createInstructionCombiningPass());
2935
2936 LTOPasses.add(llvm::createJumpThreadingPass());
2937
2938 // Delete basic blocks, which optimization passes may have killed.
2939 LTOPasses.add(llvm::createCFGSimplificationPass());
2940
2941 // Now that we have optimized the program, discard unreachable functions.
2942 LTOPasses.add(llvm::createGlobalDCEPass());
2943
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002944 LTOPasses.run(*mModule);
2945 }
2946
Zonr Chang932648d2010-10-13 22:23:56 +08002947 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002948 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08002949 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002950
Zonr Chang932648d2010-10-13 22:23:56 +08002951 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
2952 *mCodeEmitter,
2953 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002954 setError("The machine code emission is not supported by BCC on target '"
2955 + Triple + "'");
2956 goto on_bcc_compile_error;
2957 }
2958
Zonr Chang932648d2010-10-13 22:23:56 +08002959 // Run the pass (the code emitter) on every non-declaration function in the
2960 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002961 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08002962 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
2963 I != E;
2964 I++)
2965 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002966 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002967
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002968 CodeGenPasses->doFinalization();
2969
Zonr Chang932648d2010-10-13 22:23:56 +08002970 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08002971 if (ExportVarMetadata) {
2972 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2973 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2974 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2975 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2976 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002977 llvm::StringRef ExportVarName =
2978 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08002979 CodeEmitter::global_addresses_const_iterator I, E;
2980 for (I = mCodeEmitter->global_address_begin(),
2981 E = mCodeEmitter->global_address_end();
2982 I != E;
2983 I++) {
2984 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002985 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08002986 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002987 mExportVars.push_back(I->second);
2988 break;
2989 }
2990 }
Zonr Chang932648d2010-10-13 22:23:56 +08002991 if (I != mCodeEmitter->global_address_end())
2992 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002993 }
2994 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002995 // if reaching here, we know the global variable record in metadata is
2996 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002997 mExportVars.push_back(NULL);
2998 }
2999 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3000 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003001 }
3002
Zonr Chang932648d2010-10-13 22:23:56 +08003003 if (ExportFuncMetadata) {
3004 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3005 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3006 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3007 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3008 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003009 llvm::StringRef ExportFuncName =
3010 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3011 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3012 }
3013 }
3014 }
3015 }
3016
Zonr Chang932648d2010-10-13 22:23:56 +08003017 // Tell code emitter now can release the memory using during the JIT since
3018 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003019 mCodeEmitter->releaseUnnecessary();
3020
Zonr Chang932648d2010-10-13 22:23:56 +08003021 // Finally, read pragma information from the metadata node of the @Module if
3022 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003023 if (PragmaMetadata)
3024 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3025 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3026 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003027 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003028 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3029 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003030
Zonr Chang932648d2010-10-13 22:23:56 +08003031 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003032 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3033 llvm::StringRef PragmaName =
3034 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3035 llvm::StringRef PragmaValue =
3036 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3037
Zonr Chang932648d2010-10-13 22:23:56 +08003038 mPragmas.push_back(
3039 std::make_pair(std::string(PragmaName.data(),
3040 PragmaName.size()),
3041 std::string(PragmaValue.data(),
3042 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003043 }
3044 }
3045 }
3046
3047 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003048 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003049 if (CodeGenPasses) {
3050 delete CodeGenPasses;
3051 } else if (TD) {
3052 delete TD;
3053 }
3054 if (TM)
3055 delete TM;
3056
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003057 if (mError.empty()) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003058 if (!mNeverCache && mCacheFd >= 0 && mCacheNew) {
3059 genCacheFile();
3060 flock(mCacheFd, LOCK_UN);
3061 }
3062
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003063 return false;
3064 }
3065
Zonr Chang932648d2010-10-13 22:23:56 +08003066 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003067 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003068 }
3069
Zonr Chang932648d2010-10-13 22:23:56 +08003070 // interface for bccGetScriptInfoLog()
3071 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003072 return const_cast<char*>(mError.c_str());
3073 }
3074
Zonr Chang932648d2010-10-13 22:23:56 +08003075 // interface for bccGetScriptLabel()
3076 void *lookup(const char *name) {
3077 void *addr = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003078 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3079 if (!strcmp(name, "root")) {
3080 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3081 } else if (!strcmp(name, "init")) {
3082 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3083 }
3084 return addr;
3085 }
3086
Zonr Chang932648d2010-10-13 22:23:56 +08003087 if (mCodeEmitter.get())
3088 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003089 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003090 return addr;
3091 }
3092
Zonr Chang932648d2010-10-13 22:23:56 +08003093 // Interface for bccGetExportVars()
3094 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003095 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003096 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003097 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003098
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003099 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3100 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3101 if (actualVarCount)
3102 *actualVarCount = varCount;
3103 if (varCount > maxVarCount)
3104 varCount = maxVarCount;
3105 if (vars) {
3106 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3107 mCacheHdr->exportVarsOffset);
3108
3109 for (int i = 0; i < varCount; i++) {
3110 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3111 mCacheDiff);
3112 cachedVars++;
3113 }
3114 }
3115 return;
3116 }
3117
3118 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003119 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003120 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003121 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003122 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003123 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003124 for (ExportVarList::const_iterator I = mExportVars.begin(),
3125 E = mExportVars.end();
3126 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003127 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003128 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003129 }
3130 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003131
3132 return;
3133 }
3134
Zonr Chang932648d2010-10-13 22:23:56 +08003135 // Interface for bccGetExportFuncs()
3136 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003137 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003138 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003139 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003140
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003141 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3142 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3143 if (actualFuncCount)
3144 *actualFuncCount = funcCount;
3145 if (funcCount > maxFuncCount)
3146 funcCount = maxFuncCount;
3147 if (funcs) {
3148 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3149 mCacheHdr->exportFuncsOffset);
3150
3151 for (int i = 0; i < funcCount; i++) {
3152 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3153 mCacheDiff);
3154 cachedFuncs++;
3155 }
3156 }
3157 return;
3158 }
3159
3160 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003161 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003162 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003163 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003164 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003165 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003166 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3167 E = mExportFuncs.end();
3168 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003169 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003170 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003171 }
3172 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003173
3174 return;
3175 }
3176
Zonr Chang932648d2010-10-13 22:23:56 +08003177 // Interface for bccGetPragmas()
3178 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003179 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003180 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003181 int stringCount;
3182 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3183 if (actualStringCount)
3184 *actualStringCount = 0; // XXX
3185 return;
3186 }
3187
3188 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003189
Zonr Chang932648d2010-10-13 22:23:56 +08003190 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003191 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003192 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003193 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003194 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003195 for (PragmaList::const_iterator it = mPragmas.begin();
3196 stringCount > 0;
3197 stringCount -= 2, it++) {
3198 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3199 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003200 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003201 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003202
3203 return;
3204 }
3205
Zonr Chang932648d2010-10-13 22:23:56 +08003206 // Interface for bccGetFunctions()
3207 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003208 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003209 BCCchar **functions) {
3210 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003211 mCodeEmitter->getFunctionNames(actualFunctionCount,
3212 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003213 functions);
3214 else
3215 *actualFunctionCount = 0;
3216
3217 return;
3218 }
3219
Zonr Chang932648d2010-10-13 22:23:56 +08003220 // Interface for bccGetFunctionBinary()
3221 void getFunctionBinary(BCCchar *function,
3222 BCCvoid **base,
3223 BCCsizei *length) {
3224 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003225 mCodeEmitter->getFunctionBinary(function, base, length);
3226 } else {
3227 *base = NULL;
3228 *length = 0;
3229 }
3230 return;
3231 }
3232
Zonr Chang932648d2010-10-13 22:23:56 +08003233 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003234 return mModule;
3235 }
3236
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003237 ~Compiler() {
3238 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003239 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003240 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003241 return;
3242 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003243
3244 private:
3245 // Note: loader() and genCacheFile() go hand in hand
3246 void genCacheFile() {
3247 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3248 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3249 return;
3250 }
3251
3252 bool codeOffsetNeedPadding = false;
3253
3254 uint32_t offset = sizeof(oBCCHeader);
3255
3256 // BCC Cache File Header
3257 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3258
3259 if (!hdr) {
3260 LOGE("Unable to allocate oBCCHeader.\n");
3261 return;
3262 }
3263
3264 // Magic Words
3265 memcpy(hdr->magic, OBCC_MAGIC, 4);
3266 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3267
3268 // Timestamp
3269 hdr->sourceWhen = 0; // TODO(all)
3270 hdr->rslibWhen = 0; // TODO(all)
3271 hdr->libRSWhen = 0; // TODO(all)
3272 hdr->libbccWhen = 0; // TODO(all)
3273
3274 // Current Memory Address (Saved for Recalculation)
3275 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3276 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3277 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3278
3279 // Relocation Table Offset and Entry Count
3280 hdr->relocOffset = sizeof(oBCCHeader);
3281 hdr->relocCount = mCodeEmitter->mGlobalAddressMap.size();
3282
3283 offset += hdr->relocCount * (sizeof(uint32_t) * 2);
3284 // Note: each reloc has 2 entries: addr & relocTy
3285
3286 // Export Variable Table Offset and Entry Count
3287 hdr->exportVarsOffset = offset;
3288 hdr->exportVarsCount = mExportVars.size();
3289
3290 offset += hdr->exportVarsCount * sizeof(uint32_t);
3291
3292 // Export Function Table Offset and Entry Count
3293 hdr->exportFuncsOffset = offset;
3294 hdr->exportFuncsCount = mExportFuncs.size();
3295
3296 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3297
3298 // Export Pragmas Table Offset and Entry Count
3299 hdr->exportPragmasOffset = offset;
3300 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3301
3302 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3303
3304 // Code Offset and Size
3305
3306#ifdef BCC_CODE_ADDR
3307 {
3308 long pagesize = sysconf(_SC_PAGESIZE);
3309
3310 if (offset % pagesize > 0) {
3311 codeOffsetNeedPadding = true;
3312 offset += pagesize - (offset % pagesize);
3313 }
3314 }
3315#else
3316 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3317 codeOffsetNeedPadding = true;
3318 offset += 0x08 - (offset & 0x07);
3319 }
3320#endif
3321
3322 hdr->codeOffset = offset;
3323 hdr->codeSize = MaxCodeSize;
3324
3325 offset += hdr->codeSize;
3326
3327 // Data (Global Variable) Offset and Size
3328 hdr->dataOffset = offset;
3329 hdr->dataSize = MaxGlobalVarSize;
3330
3331 offset += hdr->dataSize;
3332
3333 // Checksum
3334 hdr->checksum = 0; // Set Field checksum. TODO(all)
3335
3336 // Write Header
3337 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3338 sizeof(oBCCHeader), "Write oBCC header");
3339
3340 // TODO(all): This Code is Not Working. Fix This ASAP.
3341#if 0
3342 int *itemList = (int *) calloc(buf[k_relocCount], sizeof(void *));
3343 int *tmp = itemList;
3344
3345 CodeEmitter::global_addresses_const_iterator I, E;
3346 for (I = mCodeEmitter->global_address_begin(),
3347 E = mCodeEmitter->global_address_end();
3348 I != E;
3349 I++) {
3350 // *tmp++ = (int) I->second;
3351 // *tmp++ = 0; //XXX Output fixup_type. Assume fixup type is 0 for now.
3352 }
3353 if (tmp - itemList != buf[k_relocCount] * 4) {
3354 LOGE("reloc corrupted");
3355 goto bail;
3356 }
3357 sysWriteFully(mCacheFd,
3358 itemList,
3359 buf[k_relocCount]*sizeof(void*),
3360 "Write relocs");
3361#else
3362
3363 // Note: As long as we have comment out relocation code, we have to
3364 // seek the position to correct offset.
3365
3366 lseek(mCacheFd, hdr->exportVarsOffset, SEEK_SET);
3367#endif
3368
3369 // Write Export Variables Table
3370 {
3371 uint32_t *record, *ptr;
3372
3373 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3374 ptr = record;
3375
3376 if (!record) {
3377 goto bail;
3378 }
3379
3380 for (ExportVarList::const_iterator I = mExportVars.begin(),
3381 E = mExportVars.end(); I != E; I++) {
3382 *ptr++ = reinterpret_cast<uint32_t>(*I);
3383 }
3384
3385 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3386 hdr->exportVarsCount * sizeof(uint32_t),
3387 "Write ExportVars");
3388
3389 free(record);
3390 }
3391
3392 // Write Export Functions Table
3393 {
3394 uint32_t *record, *ptr;
3395
3396 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3397 ptr = record;
3398
3399 if (!record) {
3400 goto bail;
3401 }
3402
3403 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3404 E = mExportFuncs.end(); I != E; I++) {
3405 *ptr++ = reinterpret_cast<uint32_t>(*I);
3406 }
3407
3408 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3409 hdr->exportFuncsCount * sizeof(uint32_t),
3410 "Write ExportFuncs");
3411
3412 free(record);
3413 }
3414
3415
3416 // TODO(all): Write Export Pragmas Table
3417#if 0
3418#else
3419 // Note: As long as we have comment out export pragmas table code,
3420 // we have to seek the position to correct offset.
3421
3422 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3423#endif
3424
3425 if (codeOffsetNeedPadding) {
3426 // requires additional padding
3427 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3428 }
3429
3430 // Write Generated Code and Global Variable
3431 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3432 "Write code and global variable");
3433
3434 goto close_return;
3435
3436 bail:
3437 if (ftruncate(mCacheFd, 0) != 0) {
3438 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3439 }
3440
3441 close_return:
3442 free(hdr);
3443 close(mCacheFd);
3444 mCacheFd = -1;
3445 return;
3446 }
3447
3448 // OpenCacheFile() returns fd of the cache file.
3449 // Input:
3450 // BCCchar *resName: Used to genCacheFileName()
3451 // bool createIfMissing: If false, turn off caching
3452 // Output:
3453 // returns fd: If -1: Failed
3454 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3455 // cache file's file descriptor
3456 // Note: openCacheFile() will check the cache file's validity,
3457 // such as Magic number, sourceWhen... dependencies.
3458 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3459 int fd, cc;
3460 struct stat fdStat, fileStat;
3461 bool readOnly = false;
3462
3463 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3464
3465 mCacheNew = false;
3466
3467 retry:
3468 /*
3469 * Try to open the cache file. If we've been asked to,
3470 * create it if it doesn't exist.
3471 */
3472 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3473 if (fd < 0) {
3474 fd = open(cacheFileName, O_RDONLY, 0);
3475 if (fd < 0) {
3476 if (createIfMissing) {
3477 LOGE("Can't open bcc-cache '%s': %s\n",
3478 cacheFileName, strerror(errno));
3479 mCacheNew = true;
3480 }
3481 return fd;
3482 }
3483 readOnly = true;
3484 }
3485
3486 /*
3487 * Grab an exclusive lock on the cache file. If somebody else is
3488 * working on it, we'll block here until they complete.
3489 */
3490 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3491 cacheFileName, fd);
3492
3493 cc = flock(fd, LOCK_EX | LOCK_NB);
3494 if (cc != 0) {
3495 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3496 cc = flock(fd, LOCK_EX);
3497 }
3498
3499 if (cc != 0) {
3500 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3501 close(fd);
3502 return -1;
3503 }
3504 LOGV("bcc: locked cache file\n");
3505
3506 /*
3507 * Check to see if the fd we opened and locked matches the file in
3508 * the filesystem. If they don't, then somebody else unlinked ours
3509 * and created a new file, and we need to use that one instead. (If
3510 * we caught them between the unlink and the create, we'll get an
3511 * ENOENT from the file stat.)
3512 */
3513 cc = fstat(fd, &fdStat);
3514 if (cc != 0) {
3515 LOGE("Can't stat open file '%s'\n", cacheFileName);
3516 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3517 goto close_fail;
3518 }
3519 cc = stat(cacheFileName, &fileStat);
3520 if (cc != 0 ||
3521 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3522 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3523 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3524 flock(fd, LOCK_UN);
3525 close(fd);
3526 usleep(250 * 1000); // if something is hosed, don't peg machine
3527 goto retry;
3528 }
3529
3530 /*
3531 * We have the correct file open and locked. If the file size is zero,
3532 * then it was just created by us, and we want to fill in some fields
3533 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3534 * verify that the fields in the header match our expectations, and
3535 * reset the file if they don't.
3536 */
3537 if (fdStat.st_size == 0) {
3538 if (readOnly) { // The device is readOnly --> close_fail
3539 LOGW("bcc: file has zero length and isn't writable\n");
3540 goto close_fail;
3541 }
3542 /*cc = createEmptyHeader(fd);
3543 if (cc != 0)
3544 goto close_fail;
3545 */
3546 mCacheNew = true;
3547 LOGV("bcc: successfully initialized new cache file\n");
3548 } else {
3549 // Calculate sourceWhen
3550 // XXX
3551 uint32_t sourceWhen = 0;
3552 uint32_t rslibWhen = 0;
3553 uint32_t libRSWhen = 0;
3554 uint32_t libbccWhen = 0;
3555 if (!checkHeaderAndDependencies(fd,
3556 sourceWhen,
3557 rslibWhen,
3558 libRSWhen,
3559 libbccWhen)) {
3560 // If checkHeaderAndDependencies returns 0: FAILED
3561 // Will truncate the file and retry to createIfMissing the file
3562
3563 if (readOnly) { // Shouldn't be readonly.
3564 /*
3565 * We could unlink and rewrite the file if we own it or
3566 * the "sticky" bit isn't set on the directory. However,
3567 * we're not able to truncate it, which spoils things. So,
3568 * give up now.
3569 */
3570 if (createIfMissing) {
3571 LOGW("Cached file %s is stale and not writable\n",
3572 cacheFileName);
3573 }
3574 goto close_fail;
3575 }
3576
3577 /*
3578 * If we truncate the existing file before unlinking it, any
3579 * process that has it mapped will fail when it tries to touch
3580 * the pages? Probably OK because we use MAP_PRIVATE.
3581 */
3582 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3583 cacheFileName);
3584 if (ftruncate(fd, 0) != 0) {
3585 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3586 cacheFileName, strerror(errno));
3587 /* keep going */
3588 }
3589 if (unlink(cacheFileName) != 0) {
3590 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3591 cacheFileName, errno, strerror(errno));
3592 /* keep going; permission failure should probably be fatal */
3593 }
3594 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3595 flock(fd, LOCK_UN);
3596 close(fd);
3597 goto retry;
3598 } else {
3599 // Got cacheFile! Good to go.
3600 LOGV("Good cache file\n");
3601 }
3602 }
3603
3604 assert(fd >= 0);
3605 return fd;
3606
3607 close_fail:
3608 flock(fd, LOCK_UN);
3609 close(fd);
3610 return -1;
3611 } // End of openCacheFile()
3612
3613 char *genCacheFileName(const char *fileName, const char *subFileName) {
3614 char nameBuf[512];
3615 static const char kCachePath[] = "bcc-cache";
3616 char absoluteFile[sizeof(nameBuf)];
3617 const size_t kBufLen = sizeof(nameBuf) - 1;
3618 const char *dataRoot;
3619 char *cp;
3620
3621 // Get the absolute path of the raw/***.bc file.
3622 absoluteFile[0] = '\0';
3623 if (fileName[0] != '/') {
3624 /*
3625 * Generate the absolute path. This doesn't do everything it
3626 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3627 * the leading "./" out, but it'll do.
3628 */
3629 if (getcwd(absoluteFile, kBufLen) == NULL) {
3630 LOGE("Can't get CWD while opening raw/***.bc file\n");
3631 return NULL;
3632 }
3633 // TODO(srhines): strncat() is a bit dangerous
3634 strncat(absoluteFile, "/", kBufLen);
3635 }
3636 strncat(absoluteFile, fileName, kBufLen);
3637
3638 if (subFileName != NULL) {
3639 strncat(absoluteFile, "/", kBufLen);
3640 strncat(absoluteFile, subFileName, kBufLen);
3641 }
3642
3643 /* Turn the path into a flat filename by replacing
3644 * any slashes after the first one with '@' characters.
3645 */
3646 cp = absoluteFile + 1;
3647 while (*cp != '\0') {
3648 if (*cp == '/') {
3649 *cp = '@';
3650 }
3651 cp++;
3652 }
3653
3654 /* Build the name of the cache directory.
3655 */
3656 dataRoot = getenv("ANDROID_DATA");
3657 if (dataRoot == NULL)
3658 dataRoot = "/data";
3659 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3660
3661 /* Tack on the file name for the actual cache file path.
3662 */
3663 strncat(nameBuf, absoluteFile, kBufLen);
3664
3665 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3666 return strdup(nameBuf);
3667 }
3668
3669 /*
3670 * Read the oBCC header, verify it, then read the dependent section
3671 * and verify that data as well.
3672 *
3673 * On successful return, the file will be seeked immediately past the
3674 * oBCC header.
3675 */
3676 bool checkHeaderAndDependencies(int fd,
3677 uint32_t sourceWhen,
3678 uint32_t rslibWhen,
3679 uint32_t libRSWhen,
3680 uint32_t libbccWhen) {
3681 ssize_t actual;
3682 oBCCHeader optHdr;
3683 uint32_t val;
3684 uint8_t const *magic, *magicVer;
3685
3686 /*
3687 * Start at the start. The "bcc" header, when present, will always be
3688 * the first thing in the file.
3689 */
3690 if (lseek(fd, 0, SEEK_SET) != 0) {
3691 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3692 goto bail;
3693 }
3694
3695 /*
3696 * Read and do trivial verification on the bcc header. The header is
3697 * always in host byte order.
3698 */
3699 actual = read(fd, &optHdr, sizeof(optHdr));
3700 if (actual < 0) {
3701 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3702 goto bail;
3703 } else if (actual != sizeof(optHdr)) {
3704 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3705 (int) actual, sizeof(optHdr));
3706 goto bail;
3707 }
3708
3709 magic = optHdr.magic;
3710 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3711 /* not an oBCC file, or previous attempt was interrupted */
3712 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3713 magic[0], magic[1], magic[2], magic[3]);
3714 goto bail;
3715 }
3716
3717 magicVer = optHdr.magicVersion;
3718 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3719 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3720 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3721 goto bail;
3722 }
3723
3724 /*
3725 * Do the header flags match up with what we want?
3726 *
3727 * This is useful because it allows us to automatically regenerate
3728 * a file when settings change (e.g. verification is now mandatory),
3729 * but can cause difficulties if the thing we depend upon
3730 * were handled differently than the current options specify.
3731 *
3732 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3733 * by limiting the match mask.
3734 *
3735 * The only thing we really can't handle is incorrect byte-ordering.
3736 */
3737
3738 val = optHdr.sourceWhen;
3739 if (val && (val != sourceWhen)) {
3740 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3741 val, sourceWhen);
3742 goto bail;
3743 }
3744 val = optHdr.rslibWhen;
3745 if (val && (val != rslibWhen)) {
3746 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3747 val, rslibWhen);
3748 goto bail;
3749 }
3750 val = optHdr.libRSWhen;
3751 if (val && (val != libRSWhen)) {
3752 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3753 val, libRSWhen);
3754 goto bail;
3755 }
3756 val = optHdr.libbccWhen;
3757 if (val && (val != libbccWhen)) {
3758 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3759 val, libbccWhen);
3760 goto bail;
3761 }
3762
3763 return true;
3764
3765 bail:
3766 return false;
3767 }
3768
Zonr Chang932648d2010-10-13 22:23:56 +08003769};
3770// End of Class Compiler
3771////////////////////////////////////////////////////////////////////////////////
3772
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003773
3774bool Compiler::GlobalInitialized = false;
3775
Zonr Chang932648d2010-10-13 22:23:56 +08003776// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003777llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3778
3779std::string Compiler::Triple;
3780
3781std::string Compiler::CPU;
3782
3783std::vector<std::string> Compiler::Features;
3784
Zonr Chang932648d2010-10-13 22:23:56 +08003785// The named of metadata node that pragma resides (should be synced with
3786// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003787const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3788
Zonr Chang932648d2010-10-13 22:23:56 +08003789// The named of metadata node that export variable name resides (should be
3790// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003791const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3792
Zonr Chang932648d2010-10-13 22:23:56 +08003793// The named of metadata node that export function name resides (should be
3794// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003795const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3796
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003797struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003798 //////////////////////////////////////////////////////////////////////////////
3799 // Part I. Compiler
3800 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003801 Compiler compiler;
3802
Zonr Chang932648d2010-10-13 22:23:56 +08003803 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003804 compiler.registerSymbolCallback(pFn, pContext);
3805 }
3806
Zonr Chang932648d2010-10-13 22:23:56 +08003807 //////////////////////////////////////////////////////////////////////////////
3808 // Part II. Logistics & Error handling
3809 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003810 BCCscript() {
3811 bccError = BCC_NO_ERROR;
3812 }
3813
3814 ~BCCscript() {
3815 }
3816
3817 void setError(BCCenum error) {
3818 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3819 bccError = error;
3820 }
3821 }
3822
3823 BCCenum getError() {
3824 BCCenum result = bccError;
3825 bccError = BCC_NO_ERROR;
3826 return result;
3827 }
3828
3829 BCCenum bccError;
3830};
3831
3832
3833extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003834BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003835 return new BCCscript();
3836}
3837
3838extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003839BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003840 return script->getError();
3841}
3842
3843extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003844void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003845 delete script;
3846}
3847
3848extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003849void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003850 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08003851 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003852 script->registerSymbolCallback(pFn, pContext);
3853}
3854
3855extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003856int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08003857 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003858 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08003859}
3860
3861extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003862int bccReadBC(BCCscript *script,
3863 const BCCchar *bitcode,
3864 BCCint size,
3865 const BCCchar *resName) {
3866 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003867}
3868
3869extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003870void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08003871 const BCCchar *bitcode,
3872 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003873 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08003874}
3875
3876extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003877void bccLoadBinary(BCCscript *script) {
3878 int result = script->compiler.loader();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003879 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003880 script->setError(BCC_INVALID_OPERATION);
3881}
3882
3883extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003884void bccCompileBC(BCCscript *script) {
3885 {
3886#if defined(__arm__)
3887 android::StopWatch compileTimer("RenderScript compile time");
3888#endif
3889 int result = script->compiler.compile();
3890 if (result)
3891 script->setError(BCC_INVALID_OPERATION);
3892 }
3893}
3894
3895extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003896void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003897 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08003898 BCCsizei *length,
3899 BCCchar *infoLog) {
3900 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003901 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003902 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003903 *length = messageLength;
3904
3905 if (infoLog && maxLength > 0) {
3906 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
3907 memcpy(infoLog, message, trimmedLength);
3908 infoLog[trimmedLength] = 0;
3909 }
3910}
3911
3912extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003913void bccGetScriptLabel(BCCscript *script,
3914 const BCCchar *name,
3915 BCCvoid **address) {
3916 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003917 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003918 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003919 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003920 script->setError(BCC_INVALID_VALUE);
3921}
3922
3923extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003924void bccGetExportVars(BCCscript *script,
3925 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003926 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003927 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003928 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
3929}
3930
3931extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003932void bccGetExportFuncs(BCCscript *script,
3933 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003934 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003935 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003936 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
3937}
3938
3939extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003940void bccGetPragmas(BCCscript *script,
3941 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003942 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003943 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003944 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
3945}
3946
3947extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003948void bccGetFunctions(BCCscript *script,
3949 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003950 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003951 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003952 script->compiler.getFunctions(actualFunctionCount,
3953 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003954 functions);
3955}
3956
3957extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003958void bccGetFunctionBinary(BCCscript *script,
3959 BCCchar *function,
3960 BCCvoid **base,
3961 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003962 script->compiler.getFunctionBinary(function, base, length);
3963}
3964
3965struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08003966 const Compiler *compiler;
3967 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003968};
3969
Zonr Chang932648d2010-10-13 22:23:56 +08003970} // namespace bcc