blob: 7ed7c682dbed9183a7ef12917648851eaa2c8071 [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()
Shih-wei Liao7f941bb2010-11-19 01:40:16 -0800436 size_t mCacheSize; // Set by loader()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800437 ptrdiff_t mCacheDiff; // Set by loader()
438 char *mCodeDataAddr; // Set by CodeMemoryManager if mCacheNew is true.
439 // Used by genCacheFile() for dumping
440
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700441 typedef std::list< std::pair<std::string, std::string> > PragmaList;
442 PragmaList mPragmas;
443
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700444 typedef std::list<void*> ExportVarList;
445 ExportVarList mExportVars;
446
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700447 typedef std::list<void*> ExportFuncList;
448 ExportFuncList mExportFuncs;
449
Zonr Chang932648d2010-10-13 22:23:56 +0800450 //////////////////////////////////////////////////////////////////////////////
451 // Memory manager for the code reside in memory
452 //
453 // The memory for our code emitter is very simple and is conforming to the
454 // design decisions of Android RenderScript's Exection Environment:
455 // The code, data, and symbol sizes are limited (currently 100KB.)
456 //
457 // It's very different from typical compiler, which has no limitation
458 // on the code size. How does code emitter know the size of the code
459 // it is about to emit? It does not know beforehand. We want to solve
460 // this without complicating the code emitter too much.
461 //
462 // We solve this by pre-allocating a certain amount of memory,
463 // and then start the code emission. Once the buffer overflows, the emitter
464 // simply discards all the subsequent emission but still has a counter
465 // on how many bytes have been emitted.
466 //
467 // So once the whole emission is done, if there's a buffer overflow,
468 // it re-allocates the buffer with enough size (based on the
469 // counter from previous emission) and re-emit again.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800470
471 // 128 KiB for code
472 static const unsigned int MaxCodeSize = 128 * 1024;
473 // 1 KiB for global offset table (GOT)
474 static const unsigned int MaxGOTSize = 1 * 1024;
475 // 128 KiB for global variable
476 static const unsigned int MaxGlobalVarSize = 128 * 1024;
477
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700478 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700479 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800480 //
481 // Our memory layout is as follows:
482 //
483 // The direction of arrows (-> and <-) shows memory's growth direction
484 // when more space is needed.
485 //
486 // @mpCodeMem:
487 // +--------------------------------------------------------------+
488 // | Function Memory ... -> <- ... Stub/GOT |
489 // +--------------------------------------------------------------+
490 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
491 //
492 // Where size of GOT is @MaxGOTSize KiB.
493 //
494 // @mpGVMem:
495 // +--------------------------------------------------------------+
496 // | Global variable ... -> |
497 // +--------------------------------------------------------------+
498 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
499 //
500 //
501 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
502 // of function code's memory usage
503 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
504 // of stub/GOT's memory usage
505 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
506 // of global variable's memory usage
507 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700508 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700509 uintptr_t mCurSGMemIdx;
510 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800511 void *mpCodeMem;
512 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700513
Zonr Chang932648d2010-10-13 22:23:56 +0800514 // GOT Base
515 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700516
517 typedef std::map<const llvm::Function*, pair<void* /* start address */,
518 void* /* end address */>
519 > FunctionMapTy;
520 FunctionMapTy mFunctionMap;
521
Zonr Chang932648d2010-10-13 22:23:56 +0800522 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700523 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700524 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700525
Zonr Chang932648d2010-10-13 22:23:56 +0800526 uint8_t *allocateSGMemory(uintptr_t Size,
527 unsigned Alignment = 1 /* no alignment */) {
528 intptr_t FreeMemSize = getFreeCodeMemSize();
529 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
530 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700531 return NULL;
532
Zonr Chang932648d2010-10-13 22:23:56 +0800533 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700534 Alignment = 1;
535
Zonr Chang932648d2010-10-13 22:23:56 +0800536 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700537 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
538
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700539 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700540
541 return result;
542 }
543
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700544 inline uintptr_t getFreeGVMemSize() const {
545 return MaxGlobalVarSize - mCurGVMemIdx;
546 }
Zonr Chang932648d2010-10-13 22:23:56 +0800547 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700548 return reinterpret_cast<uint8_t*>(mpGVMem);
549 }
550
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700551 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700552 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700553 reset();
554 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700555
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800556#ifdef BCC_CODE_ADDR
557 mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
558 MaxCodeSize + MaxGlobalVarSize,
559 PROT_READ | PROT_EXEC | PROT_WRITE,
560 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
561 -1,
562 0);
563#else
564 mpCodeMem = mmap(NULL,
565 MaxCodeSize + MaxGlobalVarSize,
566 PROT_READ | PROT_EXEC | PROT_WRITE,
567 MAP_PRIVATE | MAP_ANON,
568 -1,
569 0);
570#endif
571
572 if (mpCodeMem == MAP_FAILED) {
573 llvm::report_fatal_error("Failed to allocate memory for emitting "
574 "codes\n" + ErrMsg);
575 }
576 mpGVMem = (void *) ((int) mpCodeMem + MaxCodeSize);
577
578 /* mpCodeMem = mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700579 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700580 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800581 llvm::report_fatal_error("Failed to allocate memory for emitting "
582 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700583
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800584 mpGVMem = mmap(mpCodeMem, MaxGlobalVarSize,
585 PROT_READ | PROT_WRITE,
586 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700587 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800588 llvm::report_fatal_error("Failed to allocate memory for emitting "
589 "global variables\n" + ErrMsg);
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800590 */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700591 return;
592 }
593
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800594 inline uint8_t *getCodeMemBase() const {
595 return reinterpret_cast<uint8_t*>(mpCodeMem);
596 }
597
Zonr Chang932648d2010-10-13 22:23:56 +0800598 // setMemoryWritable - When code generation is in progress, the code pages
599 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700600 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700601 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700602 return;
603 }
604
Zonr Chang932648d2010-10-13 22:23:56 +0800605 // When code generation is done and we're ready to start execution, the
606 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700607 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700608 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700609 return;
610 }
611
Zonr Chang932648d2010-10-13 22:23:56 +0800612 // Setting this flag to true makes the memory manager garbage values over
613 // freed memory. This is useful for testing and debugging, and is to be
614 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700615 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800616 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700617 return;
618 }
619
Zonr Chang932648d2010-10-13 22:23:56 +0800620 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700621
Zonr Chang932648d2010-10-13 22:23:56 +0800622 // If the current table requires a Global Offset Table, this method is
623 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700624 void AllocateGOT() {
625 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700626 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700627 HasGOT = true;
628 return;
629 }
630
Zonr Chang932648d2010-10-13 22:23:56 +0800631 // If this is managing a Global Offset Table, this method should return a
632 // pointer to its base.
633 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700634 return mpGOTBase;
635 }
636
Zonr Chang932648d2010-10-13 22:23:56 +0800637 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700638
Zonr Chang932648d2010-10-13 22:23:56 +0800639 // When we start JITing a function, the JIT calls this method to allocate a
640 // block of free RWX memory, which returns a pointer to it. If the JIT wants
641 // to request a block of memory of at least a certain size, it passes that
642 // value as ActualSize, and this method returns a block with at least that
643 // much space. If the JIT doesn't know ahead of time how much space it will
644 // need to emit the function, it passes 0 for the ActualSize. In either
645 // case, this method is required to pass back the size of the allocated
646 // block through ActualSize. The JIT will be careful to not write more than
647 // the returned ActualSize bytes of memory.
648 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
649 intptr_t FreeMemSize = getFreeCodeMemSize();
650 if ((FreeMemSize < 0) ||
651 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
652 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700653 return NULL;
654
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700655 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700656 return (getCodeMemBase() + mCurFuncMemIdx);
657 }
658
Zonr Chang932648d2010-10-13 22:23:56 +0800659 // This method is called by the JIT to allocate space for a function stub
660 // (used to handle limited branch displacements) while it is JIT compiling a
661 // function. For example, if foo calls bar, and if bar either needs to be
662 // lazily compiled or is a native function that exists too far away from the
663 // call site to work, this method will be used to make a thunk for it. The
664 // stub should be "close" to the current function body, but should not be
665 // included in the 'actualsize' returned by startFunctionBody.
666 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700667 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700668 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700669 }
670
Zonr Chang932648d2010-10-13 22:23:56 +0800671 // This method is called when the JIT is done codegen'ing the specified
672 // function. At this point we know the size of the JIT compiled function.
673 // This passes in FunctionStart (which was returned by the startFunctionBody
674 // method) and FunctionEnd which is a pointer to the actual end of the
675 // function. This method should mark the space allocated and remember where
676 // it is in case the client wants to deallocate it.
677 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
678 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700679 assert(FunctionEnd > FunctionStart);
680 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
681 "Mismatched function start/end!");
682
Zonr Chang932648d2010-10-13 22:23:56 +0800683 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700684 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700685 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700686 "Code size excess the limitation!");
687 mCurFuncMemIdx += FunctionCodeSize;
688
Zonr Chang932648d2010-10-13 22:23:56 +0800689 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700690 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
691 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800692 mFunctionMap.insert(
693 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
694 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700695
696 return;
697 }
698
Zonr Chang932648d2010-10-13 22:23:56 +0800699 // Allocate a (function code) memory block of the given size. This method
700 // cannot be called between calls to startFunctionBody and endFunctionBody.
701 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
702 if (getFreeCodeMemSize() < Size)
703 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700704 return NULL;
705
Zonr Chang932648d2010-10-13 22:23:56 +0800706 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700707 Alignment = 1;
708
Zonr Chang932648d2010-10-13 22:23:56 +0800709 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700710 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800711 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700712
713 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
714
715 return result;
716 }
717
Zonr Chang932648d2010-10-13 22:23:56 +0800718 // Allocate memory for a global variable.
719 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700720 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800721 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700722 LOGE("No Global Memory");
723 return NULL;
724 }
725
Zonr Chang932648d2010-10-13 22:23:56 +0800726 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700727 Alignment = 1;
728
Zonr Chang932648d2010-10-13 22:23:56 +0800729 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700730 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800731 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700732
733 mCurGVMemIdx = (result + Size) - getGVMemBase();
734
735 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700736 }
737
Zonr Chang932648d2010-10-13 22:23:56 +0800738 // Free the specified function body. The argument must be the return value
739 // from a call to startFunctionBody() that hasn't been deallocated yet. This
740 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700741 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800742 // linear search
743 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
744 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
745 E = mFunctionMap.end();
746 I != E;
747 I++)
748 if (I->second.first == Body) {
749 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
750 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700751 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800752 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700753
Zonr Chang932648d2010-10-13 22:23:56 +0800754 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700755
Zonr Chang932648d2010-10-13 22:23:56 +0800756 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700757 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
758
759 assert(SizeNeedMove >= 0 &&
760 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
761 " be correctly calculated!");
762
Zonr Chang932648d2010-10-13 22:23:56 +0800763 if (SizeNeedMove > 0)
764 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700765 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
766 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
767
768 return;
769 }
770
Zonr Chang932648d2010-10-13 22:23:56 +0800771 // When we finished JITing the function, if exception handling is set, we
772 // emit the exception table.
773 uint8_t *startExceptionTable(const llvm::Function *F,
774 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700775 assert(false && "Exception is not allowed in our language specification");
776 return NULL;
777 }
778
Zonr Chang932648d2010-10-13 22:23:56 +0800779 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700780 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800781 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700782 assert(false && "Exception is not allowed in our language specification");
783 return;
784 }
785
Zonr Chang932648d2010-10-13 22:23:56 +0800786 // Free the specified exception table's memory. The argument must be the
787 // return value from a call to startExceptionTable() that hasn't been
788 // deallocated yet. This is never called when the JIT is currently emitting
789 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700790 void deallocateExceptionTable(void *ET) {
791 assert(false && "Exception is not allowed in our language specification");
792 return;
793 }
794
Zonr Chang932648d2010-10-13 22:23:56 +0800795 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700796 void reset() {
797 mpGOTBase = NULL;
798 HasGOT = false;
799
800 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700801 mCurSGMemIdx = MaxCodeSize - 1;
802 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700803
804 mFunctionMap.clear();
805
806 return;
807 }
808
809 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800810 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700811 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800812 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700813 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700814 return;
815 }
Zonr Chang932648d2010-10-13 22:23:56 +0800816 };
817 // End of class CodeMemoryManager
818 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700819
Zonr Chang932648d2010-10-13 22:23:56 +0800820 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700821 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800822 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700823 mCodeMemMgr.reset(new CodeMemoryManager());
824 return mCodeMemMgr.get();
825 }
826
Zonr Chang932648d2010-10-13 22:23:56 +0800827 //////////////////////////////////////////////////////////////////////////////
828 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700829 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700830 public:
831 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
832 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
833
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -0800834 GlobalAddressMapTy mGlobalAddressMap;
835
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700836 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800837 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700838
Zonr Chang932648d2010-10-13 22:23:56 +0800839 // The JITInfo for the target we are compiling to
840 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700841
Zonr Chang932648d2010-10-13 22:23:56 +0800842 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700843
Zonr Chang932648d2010-10-13 22:23:56 +0800844 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700845
846 class EmittedFunctionCode {
847 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800848 // Beginning of the function's allocation.
849 void *FunctionBody;
850
851 // The address the function's code actually starts at.
852 void *Code;
853
854 // The size of the function code
855 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700856
857 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
858 };
Zonr Chang932648d2010-10-13 22:23:56 +0800859 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700860
Zonr Chang932648d2010-10-13 22:23:56 +0800861 typedef std::map<const std::string,
862 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700863 EmittedFunctionsMapTy mEmittedFunctions;
864
Zonr Chang932648d2010-10-13 22:23:56 +0800865 // This vector is a mapping from MBB ID's to their address. It is filled in
866 // by the StartMachineBasicBlock callback and queried by the
867 // getMachineBasicBlockAddress callback.
868 std::vector<uintptr_t> mMBBLocations;
869
870 // The constant pool for the current function.
871 llvm::MachineConstantPool *mpConstantPool;
872
873 // A pointer to the first entry in the constant pool.
874 void *mpConstantPoolBase;
875
876 // Addresses of individual constant pool entries.
877 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
878
879 // The jump tables for the current function.
880 llvm::MachineJumpTableInfo *mpJumpTable;
881
882 // A pointer to the first entry in the jump table.
883 void *mpJumpTableBase;
884
885 // When outputting a function stub in the context of some other function, we
886 // save BufferBegin/BufferEnd/CurBufferPtr here.
887 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
888
889 // These are the relocations that the function needs, as emitted.
890 std::vector<llvm::MachineRelocation> mRelocations;
891
892 // This vector is a mapping from Label ID's to their address.
893 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
894
895 // Machine module info for exception informations
896 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700897
Zonr Chang932648d2010-10-13 22:23:56 +0800898 // Replace an existing mapping for GV with a new address. This updates both
899 // maps as required. If Addr is null, the entry for the global is removed
900 // from the mappings.
901 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
902 if (Addr == NULL) {
903 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700904 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
905 void *OldVal;
906
Zonr Chang932648d2010-10-13 22:23:56 +0800907 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700908 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800909 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700910 OldVal = I->second;
911 mGlobalAddressMap.erase(I);
912 }
913
914 return OldVal;
915 }
916
Zonr Chang932648d2010-10-13 22:23:56 +0800917 void *&CurVal = mGlobalAddressMap[GV];
918 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700919
920 CurVal = Addr;
921
922 return OldVal;
923 }
924
Zonr Chang932648d2010-10-13 22:23:56 +0800925 // Tell the execution engine that the specified global is at the specified
926 // location. This is used internally as functions are JIT'd and as global
927 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700928 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800929 void *&CurVal = mGlobalAddressMap[GV];
930 assert((CurVal == 0 || Addr == 0) &&
931 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700932 CurVal = Addr;
933 return;
934 }
935
Zonr Chang932648d2010-10-13 22:23:56 +0800936 // This returns the address of the specified global value if it is has
937 // already been codegen'd, otherwise it returns null.
938 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700939 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700940 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
941 }
942
Zonr Chang932648d2010-10-13 22:23:56 +0800943 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
944 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700945 MCP->getConstants();
946
Zonr Chang932648d2010-10-13 22:23:56 +0800947 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700948 return 0;
949
950 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800951 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700952 llvm::MachineConstantPoolEntry CPE = Constants[i];
953 unsigned int AlignMask = CPE.getAlignment() - 1;
954 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800955 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700956 Size += mpTD->getTypeAllocSize(Ty);
957 }
958
959 return Size;
960 }
961
Zonr Chang932648d2010-10-13 22:23:56 +0800962 // This function converts a Constant* into a GenericValue. The interesting
963 // part is if C is a ConstantExpr.
964 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
965 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700966 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800967 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
968 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
969 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700970
Zonr Chang932648d2010-10-13 22:23:56 +0800971 switch (CE->getOpcode()) {
972 case llvm::Instruction::GetElementPtr: {
973 // Compute the index
974 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
975 CE->op_end());
976 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
977 &Indices[0],
978 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700979
Zonr Chang932648d2010-10-13 22:23:56 +0800980 GetConstantValue(Op0, Result);
981 Result.PointerVal =
982 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700983
Zonr Chang932648d2010-10-13 22:23:56 +0800984 return;
985 }
986 case llvm::Instruction::Trunc: {
987 uint32_t BitWidth =
988 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
989
990 GetConstantValue(Op0, Result);
991 Result.IntVal = Result.IntVal.trunc(BitWidth);
992
993 return;
994 }
995 case llvm::Instruction::ZExt: {
996 uint32_t BitWidth =
997 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
998
999 GetConstantValue(Op0, Result);
1000 Result.IntVal = Result.IntVal.zext(BitWidth);
1001
1002 return;
1003 }
1004 case llvm::Instruction::SExt: {
1005 uint32_t BitWidth =
1006 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1007
1008 GetConstantValue(Op0, Result);
1009 Result.IntVal = Result.IntVal.sext(BitWidth);
1010
1011 return;
1012 }
1013 case llvm::Instruction::FPTrunc: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001014 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001015 GetConstantValue(Op0, Result);
1016 Result.FloatVal = static_cast<float>(Result.DoubleVal);
1017 return;
1018 }
1019 case llvm::Instruction::FPExt: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001020 // TODO(all): fixme: long double
Zonr Chang932648d2010-10-13 22:23:56 +08001021 GetConstantValue(Op0, Result);
1022 Result.DoubleVal = static_cast<double>(Result.FloatVal);
1023 return;
1024 }
1025 case llvm::Instruction::UIToFP: {
1026 GetConstantValue(Op0, Result);
1027 if (CE->getType()->isFloatTy())
1028 Result.FloatVal =
1029 static_cast<float>(Result.IntVal.roundToDouble());
1030 else if (CE->getType()->isDoubleTy())
1031 Result.DoubleVal = Result.IntVal.roundToDouble();
1032 else if (CE->getType()->isX86_FP80Ty()) {
1033 const uint64_t zero[] = { 0, 0 };
1034 llvm::APFloat apf(llvm::APInt(80, 2, zero));
1035 apf.convertFromAPInt(Result.IntVal,
1036 false,
1037 llvm::APFloat::rmNearestTiesToEven);
1038 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001039 }
Zonr Chang932648d2010-10-13 22:23:56 +08001040 return;
1041 }
1042 case llvm::Instruction::SIToFP: {
1043 GetConstantValue(Op0, Result);
1044 if (CE->getType()->isFloatTy())
1045 Result.FloatVal =
1046 static_cast<float>(Result.IntVal.signedRoundToDouble());
1047 else if (CE->getType()->isDoubleTy())
1048 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1049 else if (CE->getType()->isX86_FP80Ty()) {
1050 const uint64_t zero[] = { 0, 0 };
1051 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1052 apf.convertFromAPInt(Result.IntVal,
1053 true,
1054 llvm::APFloat::rmNearestTiesToEven);
1055 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001056 }
Zonr Chang932648d2010-10-13 22:23:56 +08001057 return;
1058 }
1059 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001060 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +08001061 case llvm::Instruction::FPToSI: {
1062 uint32_t BitWidth =
1063 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001064
Zonr Chang932648d2010-10-13 22:23:56 +08001065 GetConstantValue(Op0, Result);
1066 if (Op0->getType()->isFloatTy())
1067 Result.IntVal =
1068 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1069 else if (Op0->getType()->isDoubleTy())
1070 Result.IntVal =
1071 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
1072 BitWidth);
1073 else if (Op0->getType()->isX86_FP80Ty()) {
1074 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1075 uint64_t V;
1076 bool Ignored;
1077 apf.convertToInteger(&V,
1078 BitWidth,
1079 CE->getOpcode() == llvm::Instruction::FPToSI,
1080 llvm::APFloat::rmTowardZero,
1081 &Ignored);
1082 Result.IntVal = V; // endian?
1083 }
1084 return;
1085 }
1086 case llvm::Instruction::PtrToInt: {
1087 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1088
1089 GetConstantValue(Op0, Result);
1090 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1091 (Result.PointerVal));
1092
1093 return;
1094 }
1095 case llvm::Instruction::IntToPtr: {
1096 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1097
1098 GetConstantValue(Op0, Result);
1099 if (PtrWidth != Result.IntVal.getBitWidth())
1100 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1101 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1102
1103 Result.PointerVal =
1104 llvm::PointerTy(
1105 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
1106
1107 return;
1108 }
1109 case llvm::Instruction::BitCast: {
1110 GetConstantValue(Op0, Result);
1111 const llvm::Type *DestTy = CE->getType();
1112
1113 switch (Op0->getType()->getTypeID()) {
1114 case llvm::Type::IntegerTyID: {
1115 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1116 if (DestTy->isFloatTy())
1117 Result.FloatVal = Result.IntVal.bitsToFloat();
1118 else if (DestTy->isDoubleTy())
1119 Result.DoubleVal = Result.IntVal.bitsToDouble();
1120 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001121 }
Zonr Chang932648d2010-10-13 22:23:56 +08001122 case llvm::Type::FloatTyID: {
1123 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1124 Result.IntVal.floatToBits(Result.FloatVal);
1125 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001126 }
Zonr Chang932648d2010-10-13 22:23:56 +08001127 case llvm::Type::DoubleTyID: {
1128 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1129 Result.IntVal.doubleToBits(Result.DoubleVal);
1130 break;
1131 }
1132 case llvm::Type::PointerTyID: {
1133 assert(DestTy->isPointerTy() && "Invalid bitcast");
1134 break; // getConstantValue(Op0) above already converted it
1135 }
1136 default: {
1137 llvm_unreachable("Invalid bitcast operand");
1138 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001139 }
Zonr Chang932648d2010-10-13 22:23:56 +08001140 return;
1141 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001142 case llvm::Instruction::Add:
1143 case llvm::Instruction::FAdd:
1144 case llvm::Instruction::Sub:
1145 case llvm::Instruction::FSub:
1146 case llvm::Instruction::Mul:
1147 case llvm::Instruction::FMul:
1148 case llvm::Instruction::UDiv:
1149 case llvm::Instruction::SDiv:
1150 case llvm::Instruction::URem:
1151 case llvm::Instruction::SRem:
1152 case llvm::Instruction::And:
1153 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001154 case llvm::Instruction::Xor: {
1155 llvm::GenericValue LHS, RHS;
1156 GetConstantValue(Op0, LHS);
1157 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001158
Zonr Chang932648d2010-10-13 22:23:56 +08001159 switch (Op0->getType()->getTypeID()) {
1160 case llvm::Type::IntegerTyID: {
1161 switch (CE->getOpcode()) {
1162 case llvm::Instruction::Add: {
1163 Result.IntVal = LHS.IntVal + RHS.IntVal;
1164 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001165 }
Zonr Chang932648d2010-10-13 22:23:56 +08001166 case llvm::Instruction::Sub: {
1167 Result.IntVal = LHS.IntVal - RHS.IntVal;
1168 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001169 }
Zonr Chang932648d2010-10-13 22:23:56 +08001170 case llvm::Instruction::Mul: {
1171 Result.IntVal = LHS.IntVal * RHS.IntVal;
1172 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001173 }
Zonr Chang932648d2010-10-13 22:23:56 +08001174 case llvm::Instruction::UDiv: {
1175 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1176 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001177 }
Zonr Chang932648d2010-10-13 22:23:56 +08001178 case llvm::Instruction::SDiv: {
1179 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1180 break;
1181 }
1182 case llvm::Instruction::URem: {
1183 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1184 break;
1185 }
1186 case llvm::Instruction::SRem: {
1187 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1188 break;
1189 }
1190 case llvm::Instruction::And: {
1191 Result.IntVal = LHS.IntVal & RHS.IntVal;
1192 break;
1193 }
1194 case llvm::Instruction::Or: {
1195 Result.IntVal = LHS.IntVal | RHS.IntVal;
1196 break;
1197 }
1198 case llvm::Instruction::Xor: {
1199 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1200 break;
1201 }
1202 default: {
1203 llvm_unreachable("Invalid integer opcode");
1204 }
1205 }
1206 break;
1207 }
1208 case llvm::Type::FloatTyID: {
1209 switch (CE->getOpcode()) {
1210 case llvm::Instruction::FAdd: {
1211 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1212 break;
1213 }
1214 case llvm::Instruction::FSub: {
1215 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1216 break;
1217 }
1218 case llvm::Instruction::FMul: {
1219 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1220 break;
1221 }
1222 case llvm::Instruction::FDiv: {
1223 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1224 break;
1225 }
1226 case llvm::Instruction::FRem: {
1227 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1228 break;
1229 }
1230 default: {
1231 llvm_unreachable("Invalid float opcode");
1232 }
1233 }
1234 break;
1235 }
1236 case llvm::Type::DoubleTyID: {
1237 switch (CE->getOpcode()) {
1238 case llvm::Instruction::FAdd: {
1239 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1240 break;
1241 }
1242 case llvm::Instruction::FSub: {
1243 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1244 break;
1245 }
1246 case llvm::Instruction::FMul: {
1247 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1248 break;
1249 }
1250 case llvm::Instruction::FDiv: {
1251 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1252 break;
1253 }
1254 case llvm::Instruction::FRem: {
1255 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1256 break;
1257 }
1258 default: {
1259 llvm_unreachable("Invalid double opcode");
1260 }
1261 }
1262 break;
1263 }
1264 case llvm::Type::X86_FP80TyID:
1265 case llvm::Type::PPC_FP128TyID:
1266 case llvm::Type::FP128TyID: {
1267 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1268 switch (CE->getOpcode()) {
1269 case llvm::Instruction::FAdd: {
1270 apfLHS.add(llvm::APFloat(RHS.IntVal),
1271 llvm::APFloat::rmNearestTiesToEven);
1272 break;
1273 }
1274 case llvm::Instruction::FSub: {
1275 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1276 llvm::APFloat::rmNearestTiesToEven);
1277 break;
1278 }
1279 case llvm::Instruction::FMul: {
1280 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1281 llvm::APFloat::rmNearestTiesToEven);
1282 break;
1283 }
1284 case llvm::Instruction::FDiv: {
1285 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1286 llvm::APFloat::rmNearestTiesToEven);
1287 break;
1288 }
1289 case llvm::Instruction::FRem: {
1290 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1291 llvm::APFloat::rmNearestTiesToEven);
1292 break;
1293 }
1294 default: {
1295 llvm_unreachable("Invalid long double opcode");
1296 }
1297 }
1298 Result.IntVal = apfLHS.bitcastToAPInt();
1299 break;
1300 }
1301 default: {
1302 llvm_unreachable("Bad add type!");
1303 }
1304 } // End switch (Op0->getType()->getTypeID())
1305 return;
1306 }
1307 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001308 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001309 }
1310 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001311
1312 std::string msg;
1313 llvm::raw_string_ostream Msg(msg);
1314 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001315 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001316 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001317
1318 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001319 case llvm::Type::FloatTyID: {
1320 Result.FloatVal =
1321 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001322 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001323 }
1324 case llvm::Type::DoubleTyID: {
1325 Result.DoubleVal =
1326 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001327 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001328 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001329 case llvm::Type::X86_FP80TyID:
1330 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001331 case llvm::Type::PPC_FP128TyID: {
1332 Result.IntVal =
1333 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001334 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001335 }
1336 case llvm::Type::IntegerTyID: {
1337 Result.IntVal =
1338 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001339 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001340 }
1341 case llvm::Type::PointerTyID: {
1342 switch (C->getValueID()) {
1343 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001344 Result.PointerVal = NULL;
1345 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001346 }
1347 case llvm::Value::FunctionVal: {
1348 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1349 Result.PointerVal =
1350 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001351 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001352 }
1353 case llvm::Value::GlobalVariableVal: {
1354 const llvm::GlobalVariable *GV =
1355 static_cast<const llvm::GlobalVariable*>(C);
1356 Result.PointerVal =
1357 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001358 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001359 }
1360 case llvm::Value::BlockAddressVal: {
1361 assert(false && "JIT does not support address-of-label yet!");
1362 }
1363 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001364 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001365 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001366 }
1367 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001368 }
1369 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001370 std::string msg;
1371 llvm::raw_string_ostream Msg(msg);
1372 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001373 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001374 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001375 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001376 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001377 return;
1378 }
1379
Zonr Chang932648d2010-10-13 22:23:56 +08001380 // Stores the data in @Val of type @Ty at address @Addr.
1381 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001382 const llvm::Type *Ty) {
1383 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1384
Zonr Chang932648d2010-10-13 22:23:56 +08001385 switch (Ty->getTypeID()) {
1386 case llvm::Type::IntegerTyID: {
1387 const llvm::APInt &IntVal = Val.IntVal;
1388 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1389 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001390
Zonr Chang932648d2010-10-13 22:23:56 +08001391 const uint8_t *Src =
1392 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001393
Zonr Chang932648d2010-10-13 22:23:56 +08001394 if (llvm::sys::isLittleEndianHost()) {
1395 // Little-endian host - the source is ordered from LSB to MSB.
1396 // Order the destination from LSB to MSB: Do a straight copy.
1397 memcpy(Addr, Src, StoreBytes);
1398 } else {
1399 // Big-endian host - the source is an array of 64 bit words
1400 // ordered from LSW to MSW.
1401 //
1402 // Each word is ordered from MSB to LSB.
1403 //
1404 // Order the destination from MSB to LSB:
1405 // Reverse the word order, but not the bytes in a word.
1406 unsigned int i = StoreBytes;
1407 while (i > sizeof(uint64_t)) {
1408 i -= sizeof(uint64_t);
1409 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1410 Src,
1411 sizeof(uint64_t));
1412 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001413 }
Zonr Chang932648d2010-10-13 22:23:56 +08001414 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001415 }
1416 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001417 }
1418 case llvm::Type::FloatTyID: {
1419 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001420 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001421 }
1422 case llvm::Type::DoubleTyID: {
1423 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001424 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001425 }
1426 case llvm::Type::X86_FP80TyID: {
1427 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001428 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001429 }
1430 case llvm::Type::PointerTyID: {
1431 // Ensure 64 bit target pointers are fully initialized on 32 bit
1432 // hosts.
1433 if (StoreBytes != sizeof(llvm::PointerTy))
1434 memset(Addr, 0, StoreBytes);
1435 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001436 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001437 }
1438 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001439 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001440 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001441 }
1442
Zonr Chang932648d2010-10-13 22:23:56 +08001443 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1444 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1445 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001446
1447 return;
1448 }
1449
Zonr Chang932648d2010-10-13 22:23:56 +08001450 // Recursive function to apply a @Constant value into the specified memory
1451 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001452 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001453 switch (C->getValueID()) {
1454 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001455 // Nothing to do
1456 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001457 }
1458 case llvm::Value::ConstantVectorVal: {
1459 // dynamic cast may hurt performance
1460 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001461
Zonr Chang932648d2010-10-13 22:23:56 +08001462 unsigned int ElementSize = mpTD->getTypeAllocSize
1463 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001464
Zonr Chang932648d2010-10-13 22:23:56 +08001465 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1466 InitializeConstantToMemory(
1467 CP->getOperand(i),
1468 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001469 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001470 }
1471 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001472 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1473 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001474 }
1475 case llvm::Value::ConstantArrayVal: {
1476 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1477 unsigned int ElementSize = mpTD->getTypeAllocSize
1478 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001479
Zonr Chang932648d2010-10-13 22:23:56 +08001480 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1481 InitializeConstantToMemory(
1482 CPA->getOperand(i),
1483 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1484 break;
1485 }
1486 case llvm::Value::ConstantStructVal: {
1487 const llvm::ConstantStruct *CPS =
1488 static_cast<const llvm::ConstantStruct*>(C);
1489 const llvm::StructLayout *SL = mpTD->getStructLayout
1490 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001491
Zonr Chang932648d2010-10-13 22:23:56 +08001492 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1493 InitializeConstantToMemory(
1494 CPS->getOperand(i),
1495 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1496 break;
1497 }
1498 default: {
1499 if (C->getType()->isFirstClassType()) {
1500 llvm::GenericValue Val;
1501 GetConstantValue(C, Val);
1502 StoreValueToMemory(Val, Addr, C->getType());
1503 } else {
1504 llvm_unreachable("Unknown constant type to initialize memory "
1505 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001506 }
1507 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001508 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001509 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001510 return;
1511 }
1512
1513 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001514 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001515 return;
1516
Zonr Chang932648d2010-10-13 22:23:56 +08001517 // Constant pool address resolution is handled by the target itself in ARM
1518 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001519#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001520 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1521 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001522
Zonr Chang932648d2010-10-13 22:23:56 +08001523 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001524 return;
1525
1526 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1527 unsigned Align = MCP->getConstantPoolAlignment();
1528
1529 mpConstantPoolBase = allocateSpace(Size, Align);
1530 mpConstantPool = MCP;
1531
Zonr Chang932648d2010-10-13 22:23:56 +08001532 if (mpConstantPoolBase == NULL)
1533 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001534
1535 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001536 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001537 llvm::MachineConstantPoolEntry CPE = Constants[i];
1538 unsigned AlignMask = CPE.getAlignment() - 1;
1539 Offset = (Offset + AlignMask) & ~AlignMask;
1540
1541 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1542 mConstPoolAddresses.push_back(CAddr);
1543
Zonr Chang932648d2010-10-13 22:23:56 +08001544 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001545 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001546 ("Initialize memory with machine specific constant pool"
1547 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001548
1549 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1550
1551 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1552 Offset += mpTD->getTypeAllocSize(Ty);
1553 }
1554#endif
1555 return;
1556 }
1557
1558 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001559 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001560 return;
1561
Zonr Chang932648d2010-10-13 22:23:56 +08001562 const std::vector<llvm::MachineJumpTableEntry> &JT =
1563 MJTI->getJumpTables();
1564 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001565 return;
1566
1567 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001568 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001569 NumEntries += JT[i].MBBs.size();
1570
1571 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1572
Zonr Chang932648d2010-10-13 22:23:56 +08001573 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001574 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001575 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001576
1577 return;
1578 }
1579
1580 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001581 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001582 return;
1583
Zonr Chang932648d2010-10-13 22:23:56 +08001584 const std::vector<llvm::MachineJumpTableEntry> &JT =
1585 MJTI->getJumpTables();
1586 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001587 return;
1588
Zonr Chang932648d2010-10-13 22:23:56 +08001589 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1590 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1591 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001592
Zonr Chang932648d2010-10-13 22:23:56 +08001593 // For each jump table, map each target in the jump table to the
1594 // address of an emitted MachineBasicBlock.
1595 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1596 for (int i = 0, ie = JT.size(); i != ie; i++) {
1597 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1598 // Store the address of the basic block for this jump table slot in the
1599 // memory we allocated for the jump table in 'initJumpTableInfo'
1600 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001601 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1602 }
1603 }
1604
Zonr Chang932648d2010-10-13 22:23:56 +08001605 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1606 bool MayNeedFarStub) {
1607 switch (V->getValueID()) {
1608 case llvm::Value::FunctionVal: {
1609 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001610
Zonr Chang932648d2010-10-13 22:23:56 +08001611 // If we have code, go ahead and return that.
1612 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1613 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001614
Zonr Chang932648d2010-10-13 22:23:56 +08001615 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1616 // Return the function stub if it's already created.
1617 // We do this first so that:
1618 // we're returning the same address for the function as any
1619 // previous call.
1620 //
1621 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1622 // guaranteed to be close enough to call.
1623 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001624
Zonr Chang932648d2010-10-13 22:23:56 +08001625 // If we know the target can handle arbitrary-distance calls, try to
1626 // return a direct pointer.
1627 if (!MayNeedFarStub) {
1628 //
1629 // x86_64 architecture may encounter the bug:
1630 // http://llvm.org/bugs/show_bug.cgi?id=5201
1631 // which generate instruction "call" instead of "callq".
1632 //
1633 // And once the real address of stub is greater than 64-bit
1634 // long, the replacement will truncate to 32-bit resulting a
1635 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001636#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001637 // If this is an external function pointer, we can force the JIT
1638 // to 'compile' it, which really just adds it to the map.
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001639 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1640 return GetPointerToFunction(F, /* AbortOnFailure = */false);
1641 // Changing to false because wanting to allow later calls to
1642 // mpTJI->relocate() without aborting. For caching purpose
1643 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001644#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001645 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001646
Zonr Chang932648d2010-10-13 22:23:56 +08001647 // Otherwise, we may need a to emit a stub, and, conservatively, we
1648 // always do so.
1649 return GetLazyFunctionStub(F);
1650 break;
1651 }
1652 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001653 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1654 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001655 }
1656 case llvm::Value::GlobalAliasVal: {
1657 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1658 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001659
Zonr Chang932648d2010-10-13 22:23:56 +08001660 switch (GV->getValueID()) {
1661 case llvm::Value::FunctionVal: {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001662 // TODO(all): is there's any possibility that the function is not
Zonr Chang932648d2010-10-13 22:23:56 +08001663 // code-gen'd?
1664 return GetPointerToFunction(
1665 static_cast<const llvm::Function*>(GV),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001666 /* AbortOnFailure = */false);
1667 // Changing to false because wanting to allow later calls to
1668 // mpTJI->relocate() without aborting. For caching purpose
Zonr Chang932648d2010-10-13 22:23:56 +08001669 break;
1670 }
1671 case llvm::Value::GlobalVariableVal: {
1672 if (void *P = mGlobalAddressMap[GV])
1673 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001674
Zonr Chang932648d2010-10-13 22:23:56 +08001675 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1676 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001677
Zonr Chang932648d2010-10-13 22:23:56 +08001678 return mGlobalAddressMap[GV];
1679 break;
1680 }
1681 case llvm::Value::GlobalAliasVal: {
1682 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001683 }
1684 }
1685 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001686 }
1687 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001688 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001689 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001690 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001691 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001692 }
1693
Zonr Chang932648d2010-10-13 22:23:56 +08001694 // If the specified function has been code-gen'd, return a pointer to the
1695 // function. If not, compile it, or use a stub to implement lazy compilation
1696 // if available.
1697 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1698 // If we have already code generated the function, just return the
1699 // address.
1700 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001701 return Addr;
1702
Zonr Chang932648d2010-10-13 22:23:56 +08001703 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001704 return GetLazyFunctionStub(F);
1705 }
1706
Zonr Chang932648d2010-10-13 22:23:56 +08001707 typedef llvm::DenseMap<const llvm::Function*,
1708 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001709 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1710
Zonr Chang932648d2010-10-13 22:23:56 +08001711 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001712 return mFunctionToLazyStubMap.lookup(F);
1713 }
1714
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001715 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001716 void *GetLazyFunctionStub(llvm::Function *F) {
1717 // If we already have a lazy stub for this function, recycle it.
1718 void *&Stub = mFunctionToLazyStubMap[F];
1719 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001720 return Stub;
1721
Zonr Chang932648d2010-10-13 22:23:56 +08001722 // In any cases, we should NOT resolve function at runtime (though we are
1723 // able to). We resolve this right now.
1724 void *Actual = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08001725 if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
1726 Actual = GetPointerToFunction(F, /* AbortOnFailure = */false);
1727 // Changing to false because wanting to allow later calls to
1728 // mpTJI->relocate() without aborting. For caching purpose
1729 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001730
Zonr Chang932648d2010-10-13 22:23:56 +08001731 // Codegen a new stub, calling the actual address of the external
1732 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001733 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1734 startGVStub(F, SL.Size, SL.Alignment);
1735 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1736 finishGVStub();
1737
Zonr Chang932648d2010-10-13 22:23:56 +08001738 // We really want the address of the stub in the GlobalAddressMap for the
1739 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001740 UpdateGlobalMapping(F, Stub);
1741
Zonr Chang932648d2010-10-13 22:23:56 +08001742 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001743 PendingFunctions.insert(F);
1744 else
Zonr Chang932648d2010-10-13 22:23:56 +08001745 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1746 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001747
1748 return Stub;
1749 }
1750
Zonr Chang932648d2010-10-13 22:23:56 +08001751 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1752 void *Addr = GetPointerToGlobalIfAvailable(F);
1753 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001754 return Addr;
1755
1756 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1757 "Internal error: only external defined function routes here!");
1758
Zonr Chang932648d2010-10-13 22:23:56 +08001759 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001760 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001761 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001762
Zonr Chang932648d2010-10-13 22:23:56 +08001763 // If we resolved the symbol to a null address (eg. a weak external)
1764 // return a null pointer let the application handle it.
1765 if (Addr == NULL) {
1766 if (AbortOnFailure)
1767 llvm::report_fatal_error("Could not resolve external function "
1768 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001769 else
1770 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001771 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001772
1773 AddGlobalMapping(F, Addr);
1774
1775 return Addr;
1776 }
1777
Zonr Chang932648d2010-10-13 22:23:56 +08001778 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001779 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001780 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001781 return Addr;
1782
Zonr Chang932648d2010-10-13 22:23:56 +08001783 if (mpSymbolLookupFn)
1784 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001785 return Addr;
1786
Zonr Chang932648d2010-10-13 22:23:56 +08001787 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001788 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001789 "' which could not be resolved!");
1790
1791 return NULL;
1792 }
1793
Zonr Chang932648d2010-10-13 22:23:56 +08001794 // Return the address of the specified global variable, possibly emitting it
1795 // to memory if needed. This is used by the Emitter.
1796 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1797 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1798 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001799 return Ptr;
1800
Zonr Chang932648d2010-10-13 22:23:56 +08001801 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1802 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001803 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1804 AddGlobalMapping(GV, Ptr);
1805 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001806 // If the global hasn't been emitted to memory yet, allocate space and
1807 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001808 Ptr = GetMemoryForGV(GV);
1809 AddGlobalMapping(GV, Ptr);
1810 EmitGlobalVariable(GV);
1811 }
1812
1813 return Ptr;
1814 }
1815
Zonr Chang932648d2010-10-13 22:23:56 +08001816 // This method abstracts memory allocation of global variable so that the
1817 // JIT can allocate thread local variables depending on the target.
1818 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1819 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001820
Zonr Chang932648d2010-10-13 22:23:56 +08001821 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001822 size_t S = mpTD->getTypeAllocSize(GlobalType);
1823 size_t A = mpTD->getPreferredAlignment(GV);
1824
Zonr Chang932648d2010-10-13 22:23:56 +08001825 if (GV->isThreadLocal()) {
1826 // We can support TLS by
1827 //
1828 // Ptr = TJI.allocateThreadLocalMemory(S);
1829 //
1830 // But I tend not to.
1831 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001832 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001833 ("Compilation of Thread Local Storage (TLS) is disabled!");
1834
Zonr Chang932648d2010-10-13 22:23:56 +08001835 } else if (mpTJI->allocateSeparateGVMemory()) {
1836 if (A <= 8) {
1837 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001838 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001839 // Allocate (S + A) bytes of memory, then use an aligned pointer
1840 // within that space.
1841 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001842 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001843 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1844 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001845 }
1846 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001847 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001848 }
1849
1850 return Ptr;
1851 }
1852
1853 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001854 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001855
Zonr Chang932648d2010-10-13 22:23:56 +08001856 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001857 llvm::report_fatal_error
1858 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001859
Zonr Chang932648d2010-10-13 22:23:56 +08001860 if (GA == NULL) {
1861 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001862 GA = GetMemoryForGV(GV);
1863 AddGlobalMapping(GV, GA);
1864 }
1865
1866 InitializeConstantToMemory(GV->getInitializer(), GA);
1867
Zonr Chang932648d2010-10-13 22:23:56 +08001868 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001869 return;
1870 }
1871
1872 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1873 > GlobalToIndirectSymMapTy;
1874 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1875
Zonr Chang932648d2010-10-13 22:23:56 +08001876 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1877 // Make sure GV is emitted first, and create a stub containing the fully
1878 // resolved address.
1879 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001880
Zonr Chang932648d2010-10-13 22:23:56 +08001881 // If we already have a stub for this global variable, recycle it.
1882 void *&IndirectSym = GlobalToIndirectSymMap[V];
1883 // Otherwise, codegen a new indirect symbol.
1884 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001885 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1886
1887 return IndirectSym;
1888 }
1889
Zonr Chang932648d2010-10-13 22:23:56 +08001890 // This is the equivalent of FunctionToLazyStubMap for external functions.
1891 //
1892 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1893 // It's actually here to make it more likely that far calls
1894 // succeed, but no single stub can guarantee that. I'll
1895 // remove this in a subsequent checkin when I actually fix
1896 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001897 std::map<void*, void*> ExternalFnToStubMap;
1898
Zonr Chang932648d2010-10-13 22:23:56 +08001899 // Return a stub for the function at the specified address.
1900 void *GetExternalFunctionStub(void *FnAddr) {
1901 void *&Stub = ExternalFnToStubMap[FnAddr];
1902 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001903 return Stub;
1904
1905 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1906 startGVStub(0, SL.Size, SL.Alignment);
1907 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1908 finishGVStub();
1909
1910 return Stub;
1911 }
1912
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001913#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001914 const llvm::MCAsmInfo *mpAsmInfo;
1915 const llvm::MCDisassembler *mpDisassmbler;
1916 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001917
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001918 class BufferMemoryObject : public llvm::MemoryObject {
1919 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001920 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001921 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001922
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001923 public:
1924 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1925 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001926
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001927 uint64_t getBase() const { return 0; }
1928 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001929
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001930 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001931 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001932 return -1;
1933 *Byte = mBytes[Addr];
1934 return 0;
1935 }
1936 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001937
Zonr Chang932648d2010-10-13 22:23:56 +08001938 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001939 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001940 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001941#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001942 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001943 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1944 ErrorInfo,
1945 llvm::raw_fd_ostream::F_Append);
1946 if (!ErrorInfo.empty()) { // some errors occurred
1947 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001948 delete OS;
1949 return;
1950 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001951#else
1952 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001953#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001954 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1955 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001956
Zonr Chang932648d2010-10-13 22:23:56 +08001957 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001958 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001959 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001960 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001961 if (mpIP == NULL)
1962 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1963 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001964
Zonr Chang932648d2010-10-13 22:23:56 +08001965 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1966 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001967 uint64_t Size;
1968 uint64_t Index;
1969
Zonr Chang932648d2010-10-13 22:23:56 +08001970 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001971 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001972
Zonr Chang932648d2010-10-13 22:23:56 +08001973 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1974 /* REMOVED */ llvm::nulls())) {
1975 (*OS).indent(4)
1976 .write("0x", 2)
1977 .write_hex((uint32_t) Start + Index)
1978 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001979 mpIP->printInst(&Inst, *OS);
1980 *OS << "\n";
1981 } else {
1982 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08001983 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001984 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001985 }
1986
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001987 *OS << "\n";
1988 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001989
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001990#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08001991 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001992 OS->close();
1993 delete OS;
1994#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001995 return;
1996 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001997#else
Zonr Chang932648d2010-10-13 22:23:56 +08001998 inline void Disassemble(const std::string &Name, uint8_t *Start,
1999 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002000 return;
2001 }
Zonr Chang932648d2010-10-13 22:23:56 +08002002#endif // defined(USE_DISASSEMBLER)
2003
2004 // Resolver to undefined symbol in CodeEmitter
2005 BCCSymbolLookupFn mpSymbolLookupFn;
2006 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002007
2008 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002009 // Will take the ownership of @MemMgr
2010 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
2011 : mpMemMgr(pMemMgr),
2012 mpTarget(NULL),
2013 mpTJI(NULL),
2014 mpTD(NULL),
2015 mpCurEmitFunction(NULL),
2016 mpConstantPool(NULL),
2017 mpJumpTable(NULL),
2018 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002019#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002020 mpAsmInfo(NULL),
2021 mpDisassmbler(NULL),
2022 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002023#endif
Zonr Chang932648d2010-10-13 22:23:56 +08002024 mpSymbolLookupFn(NULL),
2025 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002026 return;
2027 }
2028
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002029 inline global_addresses_const_iterator global_address_begin() const {
2030 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002031 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002032 inline global_addresses_const_iterator global_address_end() const {
2033 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002034 }
2035
Zonr Chang932648d2010-10-13 22:23:56 +08002036 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002037 mpSymbolLookupFn = pFn;
2038 mpSymbolLookupContext = pContext;
2039 return;
2040 }
2041
Zonr Chang932648d2010-10-13 22:23:56 +08002042 void setTargetMachine(llvm::TargetMachine &TM) {
2043 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002044 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08002045 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002046 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08002047 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002048 mpTD = TM.getTargetData();
2049
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002050 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2051
2052 return;
2053 }
2054
Zonr Chang932648d2010-10-13 22:23:56 +08002055 // This callback is invoked when the specified function is about to be code
2056 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002057 void startFunction(llvm::MachineFunction &F) {
2058 uintptr_t ActualSize = 0;
2059
2060 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08002061
2062 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
2063 // MachineCodeEmitter, which is the super class of the class
2064 // JITCodeEmitter.
2065 //
2066 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
2067 // allocated for this code buffer.
2068 //
2069 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2070 // code. This is guranteed to be in the range
2071 // [BufferBegin, BufferEnd]. If this pointer is at
2072 // BufferEnd, it will never move due to code emission, and
2073 // all code emission requests will be ignored (this is the
2074 // buffer overflow condition).
2075 BufferBegin = CurBufferPtr =
2076 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002077 BufferEnd = BufferBegin + ActualSize;
2078
Zonr Chang932648d2010-10-13 22:23:56 +08002079 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002080 mpCurEmitFunction = new EmittedFunctionCode();
2081 mpCurEmitFunction->FunctionBody = BufferBegin;
2082
Zonr Chang932648d2010-10-13 22:23:56 +08002083 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002084 emitAlignment(16);
2085
2086 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08002087 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002088 initJumpTableInfo(MJTI);
2089
Zonr Chang932648d2010-10-13 22:23:56 +08002090 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002091 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2092
2093 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2094
2095 mpCurEmitFunction->Code = CurBufferPtr;
2096
2097 mMBBLocations.clear();
2098
2099 return;
2100 }
2101
Zonr Chang932648d2010-10-13 22:23:56 +08002102 // This callback is invoked when the specified function has finished code
2103 // generation. If a buffer overflow has occurred, this method returns true
2104 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002105 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08002106 if (CurBufferPtr == BufferEnd) {
2107 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002108 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2109 return false;
2110 }
2111
Zonr Chang932648d2010-10-13 22:23:56 +08002112 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002113 emitJumpTableInfo(MJTI);
2114
Zonr Chang932648d2010-10-13 22:23:56 +08002115 // FnStart is the start of the text, not the start of the constant pool
2116 // and other per-function data.
2117 uint8_t *FnStart =
2118 reinterpret_cast<uint8_t*>(
2119 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002120
Zonr Chang932648d2010-10-13 22:23:56 +08002121 // FnEnd is the end of the function's machine code.
2122 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002123
Zonr Chang932648d2010-10-13 22:23:56 +08002124 if (!mRelocations.empty()) {
2125 // Resolve the relocations to concrete pointers.
2126 for (int i = 0, e = mRelocations.size(); i != e; i++) {
2127 llvm::MachineRelocation &MR = mRelocations[i];
2128 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002129
Zonr Chang932648d2010-10-13 22:23:56 +08002130 if (!MR.letTargetResolve()) {
2131 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002132 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Zonr Chang932648d2010-10-13 22:23:56 +08002133 if (MR.mayNeedFarStub())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002134 ResultPtr = GetExternalFunctionStub(ResultPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002135 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002136 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2137 BufferBegin
2138 + MR.getMachineCodeOffset(),
2139 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002140 } else if (MR.isIndirectSymbol()) {
2141 ResultPtr =
2142 GetPointerToGVIndirectSym(
2143 MR.getGlobalValue(),
2144 BufferBegin + MR.getMachineCodeOffset());
2145 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002146 ResultPtr =
2147 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002148 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002149 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002150 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002151 } else {
2152 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2153 ResultPtr =
2154 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2155 }
2156
2157 MR.setResultPointer(ResultPtr);
2158 }
2159 }
2160
2161 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2162 mpMemMgr->getGOTBase());
2163 }
2164
2165 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002166 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2167 // global variables that were referenced in the relocations.
2168 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002169 return false;
2170
Zonr Chang932648d2010-10-13 22:23:56 +08002171 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002172 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2173 BufferBegin = CurBufferPtr = 0;
2174
Zonr Chang932648d2010-10-13 22:23:56 +08002175 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002176 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2177 mpCurEmitFunction = NULL;
2178
2179 mRelocations.clear();
2180 mConstPoolAddresses.clear();
2181
Zonr Chang932648d2010-10-13 22:23:56 +08002182 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002183 mpMMI->EndFunction();
2184
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002185 updateFunctionStub(F.getFunction());
2186
Zonr Chang932648d2010-10-13 22:23:56 +08002187 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002188 mpMemMgr->setMemoryExecutable();
2189
2190 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2191
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002192 return false;
2193 }
2194
Zonr Chang932648d2010-10-13 22:23:56 +08002195 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002196 unsigned Alignment) {
2197 mpSavedBufferBegin = BufferBegin;
2198 mpSavedBufferEnd = BufferEnd;
2199 mpSavedCurBufferPtr = CurBufferPtr;
2200
2201 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2202 Alignment);
2203 BufferEnd = BufferBegin + StubSize + 1;
2204
2205 return;
2206 }
2207
Zonr Chang932648d2010-10-13 22:23:56 +08002208 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002209 mpSavedBufferBegin = BufferBegin;
2210 mpSavedBufferEnd = BufferEnd;
2211 mpSavedCurBufferPtr = CurBufferPtr;
2212
Zonr Chang932648d2010-10-13 22:23:56 +08002213 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002214 BufferEnd = BufferBegin + StubSize + 1;
2215
2216 return;
2217 }
2218
2219 void finishGVStub() {
2220 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2221
Zonr Chang932648d2010-10-13 22:23:56 +08002222 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002223 BufferBegin = mpSavedBufferBegin;
2224 BufferEnd = mpSavedBufferEnd;
2225 CurBufferPtr = mpSavedCurBufferPtr;
2226
2227 return;
2228 }
2229
Zonr Chang932648d2010-10-13 22:23:56 +08002230 // Allocates and fills storage for an indirect GlobalValue, and returns the
2231 // address.
2232 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002233 const uint8_t *Buffer, size_t Size,
2234 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002235 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002236 memcpy(IndGV, Buffer, Size);
2237 return IndGV;
2238 }
2239
Zonr Chang932648d2010-10-13 22:23:56 +08002240 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002241 void emitLabel(llvm::MCSymbol *Label) {
2242 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002243 return;
2244 }
2245
Zonr Chang932648d2010-10-13 22:23:56 +08002246 // Allocate memory for a global. Unlike allocateSpace, this method does not
2247 // allocate memory in the current output buffer, because a global may live
2248 // longer than the current function.
2249 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2250 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002251 return mpMemMgr->allocateGlobal(Size, Alignment);
2252 }
2253
Zonr Chang932648d2010-10-13 22:23:56 +08002254 // This should be called by the target when a new basic block is about to be
2255 // emitted. This way the MCE knows where the start of the block is, and can
2256 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002257 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002258 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002259 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2260 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2261 return;
2262 }
2263
Zonr Chang932648d2010-10-13 22:23:56 +08002264 // Whenever a relocatable address is needed, it should be noted with this
2265 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002266 void addRelocation(const llvm::MachineRelocation &MR) {
2267 mRelocations.push_back(MR);
2268 return;
2269 }
2270
Zonr Chang932648d2010-10-13 22:23:56 +08002271 // Return the address of the @Index entry in the constant pool that was
2272 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002273 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2274 assert(Index < mpConstantPool->getConstants().size() &&
2275 "Invalid constant pool index!");
2276 return mConstPoolAddresses[Index];
2277 }
2278
Zonr Chang932648d2010-10-13 22:23:56 +08002279 // Return the address of the jump table with index @Index in the function
2280 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002281 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002282 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002283 mpJumpTable->getJumpTables();
2284
Zonr Chang932648d2010-10-13 22:23:56 +08002285 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002286
2287 unsigned int Offset = 0;
2288 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2289
Zonr Chang932648d2010-10-13 22:23:56 +08002290 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002291 Offset += JT[i].MBBs.size();
2292 Offset *= EntrySize;
2293
Zonr Chang932648d2010-10-13 22:23:56 +08002294 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002295 }
2296
Zonr Chang932648d2010-10-13 22:23:56 +08002297 // Return the address of the specified MachineBasicBlock, only usable after
2298 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002299 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2300 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002301 mMBBLocations[MBB->getNumber()] &&
2302 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002303 return mMBBLocations[MBB->getNumber()];
2304 }
2305
Zonr Chang932648d2010-10-13 22:23:56 +08002306 // Return the address of the specified LabelID, only usable after the
2307 // LabelID has been emitted.
2308 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002309 assert(mLabelLocations.count(Label) && "Label not emitted!");
2310 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002311 }
2312
Zonr Chang932648d2010-10-13 22:23:56 +08002313 // Specifies the MachineModuleInfo object. This is used for exception
2314 // handling purposes.
2315 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002316 mpMMI = Info;
2317 return;
2318 }
2319
Zonr Chang932648d2010-10-13 22:23:56 +08002320 void updateFunctionStub(const llvm::Function *F) {
2321 // Get the empty stub we generated earlier.
2322 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002323 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002324 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002325 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002326 else
2327 return;
2328
Zonr Chang932648d2010-10-13 22:23:56 +08002329 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002330
2331 assert(Addr != Stub &&
2332 "Function must have non-stub address to be updated.");
2333
Zonr Chang932648d2010-10-13 22:23:56 +08002334 // Tell the target jit info to rewrite the stub at the specified address,
2335 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002336 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2337 startGVStub(Stub, SL.Size);
2338 mpTJI->emitFunctionStub(F, Addr, *this);
2339 finishGVStub();
2340
Zonr Chang932648d2010-10-13 22:23:56 +08002341 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2342 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002343
2344 PendingFunctions.erase(I);
2345
2346 return;
2347 }
2348
Zonr Chang932648d2010-10-13 22:23:56 +08002349 // Once you finish the compilation on a translation unit, you can call this
2350 // function to recycle the memory (which is used at compilation time and not
2351 // needed for runtime).
2352 //
2353 // NOTE: You should not call this funtion until the code-gen passes for a
2354 // given module is done. Otherwise, the results is undefined and may
2355 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002356 void releaseUnnecessary() {
2357 mMBBLocations.clear();
2358 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002359 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002360 mFunctionToLazyStubMap.clear();
2361 GlobalToIndirectSymMap.clear();
2362 ExternalFnToStubMap.clear();
2363 PendingFunctions.clear();
2364
2365 return;
2366 }
2367
2368 void reset() {
2369 releaseUnnecessary();
2370
2371 mpSymbolLookupFn = NULL;
2372 mpSymbolLookupContext = NULL;
2373
2374 mpTJI = NULL;
2375 mpTD = NULL;
2376
Zonr Chang932648d2010-10-13 22:23:56 +08002377 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2378 E = mEmittedFunctions.end();
2379 I != E;
2380 I++)
2381 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002382 delete I->second;
2383 mEmittedFunctions.clear();
2384
2385 mpMemMgr->reset();
2386
2387 return;
2388 }
2389
Zonr Chang932648d2010-10-13 22:23:56 +08002390 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002391 return lookup( llvm::StringRef(Name) );
2392 }
2393
Zonr Chang932648d2010-10-13 22:23:56 +08002394 void *lookup(const llvm::StringRef &Name) {
2395 EmittedFunctionsMapTy::const_iterator I =
2396 mEmittedFunctions.find(Name.str());
2397 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002398 return NULL;
2399 else
2400 return I->second->Code;
2401 }
2402
Zonr Chang932648d2010-10-13 22:23:56 +08002403 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002404 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002405 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002406 int functionCount = mEmittedFunctions.size();
2407
Zonr Chang932648d2010-10-13 22:23:56 +08002408 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002409 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002410 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002411 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002412 if (functions)
2413 for (EmittedFunctionsMapTy::const_iterator
2414 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2415 (I != E) && (functionCount > 0);
2416 I++, functionCount--)
2417 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002418
2419 return;
2420 }
2421
Zonr Chang932648d2010-10-13 22:23:56 +08002422 void getFunctionBinary(BCCchar *label,
2423 BCCvoid **base,
2424 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002425 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002426 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002427 *base = NULL;
2428 *length = 0;
2429 } else {
2430 *base = I->second->Code;
2431 *length = I->second->Size;
2432 }
2433 return;
2434 }
2435
2436 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002437 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002438#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002439 delete mpAsmInfo;
2440 delete mpDisassmbler;
2441 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002442#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002443 return;
2444 }
Zonr Chang932648d2010-10-13 22:23:56 +08002445 };
2446 // End of Class CodeEmitter
2447 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002448
Zonr Chang932648d2010-10-13 22:23:56 +08002449 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002450 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002451 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002452 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2453 return mCodeEmitter.get();
2454 }
2455
2456 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002457 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002458
Zonr Chang932648d2010-10-13 22:23:56 +08002459 llvm::LLVMContext *mContext;
2460 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002461
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002462 bool mHasLinked;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002463
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002464 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002465 Compiler()
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002466 : mNeverCache(true),
2467 mCacheNew(false),
2468 mCacheFd(-1),
2469 mCacheMapAddr(NULL),
2470 mCacheHdr(NULL),
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002471 mCacheSize(0),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002472 mCacheDiff(0),
2473 mCodeDataAddr(NULL),
2474 mpSymbolLookupFn(NULL),
Zonr Chang932648d2010-10-13 22:23:56 +08002475 mpSymbolLookupContext(NULL),
2476 mContext(NULL),
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002477 mModule(NULL),
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002478 mHasLinked(false) /* Turn off linker */ {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002479 llvm::remove_fatal_error_handler();
2480 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002481 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002482 return;
2483 }
2484
Zonr Chang932648d2010-10-13 22:23:56 +08002485 // interface for BCCscript::registerSymbolCallback()
2486 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002487 mpSymbolLookupFn = pFn;
2488 mpSymbolLookupContext = pContext;
2489 return;
2490 }
2491
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002492 int readModule(llvm::Module *module) {
Zonr Changdbee68b2010-10-22 05:02:16 +08002493 GlobalInitialization();
2494 mModule = module;
2495 return hasError();
2496 }
2497
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002498 int readBC(const char *bitcode,
2499 size_t bitcodeSize,
2500 const BCCchar *resName) {
2501 GlobalInitialization();
2502
2503 if (resName) {
2504 // Turn off the default NeverCaching mode
2505 mNeverCache = false;
2506
2507 // TODO(sliao):
2508 mNeverCache = true;
2509#if 0
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002510 mCacheFd = openCacheFile(resName, true /* createIfMissing */);
2511 if (mCacheFd >= 0 && !mCacheNew) { // Just use cache file
2512 return -mCacheFd;
2513 }
2514#endif
2515 }
2516
2517 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002518
Zonr Chang932648d2010-10-13 22:23:56 +08002519 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002520 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002521
Zonr Chang932648d2010-10-13 22:23:56 +08002522 // Package input to object MemoryBuffer
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002523 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002524 llvm::StringRef(bitcode, bitcodeSize)));
2525
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002526 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002527 setError("Error reading input program bitcode into memory");
2528 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002529 }
2530
Zonr Chang932648d2010-10-13 22:23:56 +08002531 // Read the input Bitcode as a Module
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002532 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &mError);
2533 MEM.reset();
Zonr Chang97f5e612010-10-22 20:38:26 +08002534 return hasError();
2535 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002536
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002537 int linkBC(const char *bitcode, size_t bitcodeSize) {
2538 llvm::OwningPtr<llvm::MemoryBuffer> MEM;
Zonr Chang97f5e612010-10-22 20:38:26 +08002539
2540 if (bitcode == NULL || bitcodeSize <= 0)
2541 return 0;
2542
2543 if (mModule == NULL) {
2544 setError("No module presents for linking");
2545 return hasError();
2546 }
2547
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002548 MEM.reset(llvm::MemoryBuffer::getMemBuffer(
Zonr Chang97f5e612010-10-22 20:38:26 +08002549 llvm::StringRef(bitcode, bitcodeSize)));
2550
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002551 if (MEM.get() == NULL) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002552 setError("Error reading input library bitcode into memory");
2553 return hasError();
2554 }
2555
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002556 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(MEM.get(),
Zonr Chang97f5e612010-10-22 20:38:26 +08002557 *mContext,
2558 &mError));
2559 if (Lib.get() == NULL)
2560 return hasError();
2561
2562 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2563 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002564
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002565 // Everything for linking should be settled down here with no error occurs
2566 mHasLinked = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002567 return hasError();
2568 }
2569
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002570
2571 // interface for bccLoadBinary()
2572 int loader() {
2573 // Check File Descriptor
2574 if (mCacheFd < 0) {
2575 LOGE("loading cache from invalid mCacheFd = %d\n", (int)mCacheFd);
2576 goto giveup;
2577 }
2578
2579
2580 // Check File Size
2581 struct stat statCacheFd;
2582 if (fstat(mCacheFd, &statCacheFd) < 0) {
2583 LOGE("unable to stat mCacheFd = %d\n", (int)mCacheFd);
2584 goto giveup;
2585 }
2586
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002587 mCacheSize = statCacheFd.st_size;
2588
2589 if (mCacheSize < sizeof(oBCCHeader) ||
2590 mCacheSize <= MaxCodeSize + MaxGlobalVarSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002591 LOGE("mCacheFd %d is too small to be correct\n", (int)mCacheFd);
2592 goto giveup;
2593 }
2594
2595
2596 // Read File Content
2597 {
2598#ifdef BCC_CODE_ADDR
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002599 off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002600
2601 mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
2602 MaxCodeSize + MaxGlobalVarSize,
2603 PROT_READ | PROT_EXEC | PROT_WRITE,
2604 MAP_PRIVATE | MAP_FIXED,
2605 mCacheFd, heuristicCodeOffset);
2606
2607 if (mCodeDataAddr == MAP_FAILED) {
2608 LOGE("unable to mmap .oBBC cache code/data: %s\n", strerror(errno));
2609 flock(mCacheFd, LOCK_UN);
2610 goto giveup;
2611 }
2612
2613 mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
2614
2615 if (!mCacheMapAddr) {
2616 flock(mCacheFd, LOCK_UN);
2617 LOGE("allocation failed.\n");
2618 // TODO(all)
2619 goto bail;
2620 }
2621
2622 size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
2623 heuristicCodeOffset));
2624
2625 flock(mCacheFd, LOCK_UN);
2626
2627 if (nread != (size_t)heuristicCodeOffset) {
2628 LOGE("read(mCacheFd) failed\n");
2629 free(mCacheMapAddr);
2630 goto bail;
2631 }
2632
2633 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
2634
2635 if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
2636 LOGE("assertion failed: heuristic code offset is not correct.\n");
2637 goto bail;
2638 }
2639#else
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002640 mCacheMapAddr = (char *) mmap(0, mCacheSize,
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002641 PROT_READ | PROT_EXEC | PROT_WRITE,
2642 MAP_PRIVATE, mCacheFd, 0);
2643
2644 if (mCodeDataAddr == MAP_FAILED) {
2645 LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
2646 flock(mCacheFd, LOCK_UN);
2647 goto giveup;
2648 }
2649
2650 flock(mCacheFd, LOCK_UN);
2651
2652 mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
2653
2654 mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
2655#endif
2656 }
2657
2658
2659 // Verify the Cache File
2660 if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
2661 LOGE("bad magic word\n");
2662 goto bail;
2663 }
2664
2665 if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
2666 LOGE("bad oBCC version 0x%08x\n",
2667 *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
2668 goto bail;
2669 }
2670
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002671 if (mCacheSize < mCacheHdr->relocOffset +
2672 mCacheHdr->relocCount * sizeof(uint32_t) * 2) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002673 LOGE("relocate table overflow\n");
2674 goto bail;
2675 }
2676
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002677 if (mCacheSize < mCacheHdr->exportVarsOffset +
2678 mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002679 LOGE("export variables table overflow\n");
2680 goto bail;
2681 }
2682
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002683 if (mCacheSize < mCacheHdr->exportFuncsOffset +
2684 mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002685 LOGE("export functions table overflow\n");
2686 goto bail;
2687 }
2688
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002689 if (mCacheSize < mCacheHdr->exportPragmasOffset +
2690 mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002691 LOGE("export pragmas table overflow\n");
2692 goto bail;
2693 }
2694
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002695 if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002696 LOGE("code cache overflow\n");
2697 goto bail;
2698 }
2699
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002700 if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002701 LOGE("data (global variable) cache overflow\n");
2702 goto bail;
2703 }
2704
2705
2706 // Relocate
2707 {
2708 mCacheDiff = mCodeDataAddr -
2709 reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
2710
2711#ifdef BCC_CODE_ADDR
2712 if (mCacheDiff != 0) {
2713 LOGE("mCacheDiff should be zero but mCacheDiff = %d\n", mCacheDiff);
2714 goto bail;
2715 }
2716#else
2717 mCacheHdr->rootAddr += mCacheDiff;
2718 mCacheHdr->initAddr += mCacheDiff;
2719
2720 uint32_t *relocTable =
2721 reinterpret_cast<uint32_t *>(mCacheMapAddr + mCacheHdr->relocOffset);
2722
2723 // Read in the relocs
2724 for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
2725 // TODO(all): Patch the hole
2726
2727 //char *holeAddr = reinterpret_cast<char *>(*relocTable++) + mCacheDiff;
2728 //uint32_t holeTy = *relocTable++;
2729
2730 //patch(...); I.e., holeAddr += mCacheDiff
2731 }
2732#endif
2733 }
2734
2735 return 0;
2736
2737 bail:
2738#ifdef BCC_CODE_ADDR
2739 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
2740 LOGE("munmap failed: %s\n", strerror(errno));
2741 }
2742
2743 if (mCacheMapAddr) {
2744 free(mCacheMapAddr);
2745 }
2746#else
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08002747 if (munmap(mCacheMapAddr, mCacheSize) != 0) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002748 LOGE("munmap failed: %s\n", strerror(errno));
2749 }
2750#endif
2751
2752 giveup:
2753 return 1;
2754 }
2755
2756 // interace for bccCompileBC()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002757 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002758 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002759
Zonr Chang932648d2010-10-13 22:23:56 +08002760 llvm::TargetMachine *TM = NULL;
2761 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002762 std::string FeaturesStr;
2763
Zonr Chang932648d2010-10-13 22:23:56 +08002764 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002765
Zonr Chang932648d2010-10-13 22:23:56 +08002766 const llvm::NamedMDNode *PragmaMetadata;
2767 const llvm::NamedMDNode *ExportVarMetadata;
2768 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002769
Zonr Chang932648d2010-10-13 22:23:56 +08002770 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002771 return 0;
2772
Zonr Chang932648d2010-10-13 22:23:56 +08002773 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002774 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002775 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002776 goto on_bcc_compile_error;
2777
Zonr Chang932648d2010-10-13 22:23:56 +08002778 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002779 llvm::SubtargetFeatures F;
2780 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002781 for (std::vector<std::string>::const_iterator I = Features.begin(),
2782 E = Features.end();
2783 I != E;
2784 I++)
2785 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002786 FeaturesStr = F.getString();
2787 }
2788
2789 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002790 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002791 setError("Failed to create target machine implementation for the"
2792 " specified triple '" + Triple + "'");
2793 goto on_bcc_compile_error;
2794 }
2795
Zonr Chang932648d2010-10-13 22:23:56 +08002796 // Create memory manager for creation of code emitter later.
2797 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002798 setError("Failed to startup memory management for further compilation");
2799 goto on_bcc_compile_error;
2800 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002801 mCodeDataAddr = (char *) (mCodeMemMgr.get()->getCodeMemBase());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002802
Zonr Chang932648d2010-10-13 22:23:56 +08002803 // Create code emitter
2804 if (!mCodeEmitter.get()) {
2805 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002806 setError("Failed to create machine code emitter to complete"
2807 " the compilation");
2808 goto on_bcc_compile_error;
2809 }
2810 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002811 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002812 mCodeEmitter->reset();
2813 }
2814
2815 mCodeEmitter->setTargetMachine(*TM);
2816 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2817 mpSymbolLookupContext);
2818
Zonr Chang932648d2010-10-13 22:23:56 +08002819 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002820 TD = new llvm::TargetData(mModule);
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002821
Zonr Chang5d35b972010-10-23 14:36:47 +08002822 // Load named metadata
2823 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2824 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2825 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2826
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002827 // Create LTO passes and run them on the mModule
2828 if (mHasLinked) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002829 llvm::TimePassesIsEnabled = true; // TODO(all)
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002830 llvm::PassManager LTOPasses;
Zonr Chang5d35b972010-10-23 14:36:47 +08002831 LTOPasses.add(new llvm::TargetData(*TD));
2832
2833 std::vector<const char*> ExportSymbols;
2834
2835 // A workaround for getting export variable and function name. Will refine
2836 // it soon.
2837 if (ExportVarMetadata) {
2838 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2839 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2840 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2841 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2842 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2843 llvm::StringRef ExportVarName =
2844 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2845 ExportSymbols.push_back(ExportVarName.data());
2846 }
2847 }
2848 }
2849 }
2850
2851 if (ExportFuncMetadata) {
2852 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2853 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2854 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2855 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2856 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2857 llvm::StringRef ExportFuncName =
2858 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2859 ExportSymbols.push_back(ExportFuncName.data());
2860 }
2861 }
2862 }
2863 }
2864 // root() and init() are born to be exported
2865 ExportSymbols.push_back("root");
2866 ExportSymbols.push_back("init");
2867
Zonr Change5c7a542010-10-24 01:07:27 +08002868 // We now create passes list performing LTO. These are copied from
2869 // (including comments) llvm::createStandardLTOPasses().
2870
2871 // Internalize all other symbols not listed in ExportSymbols
Zonr Chang5d35b972010-10-23 14:36:47 +08002872 LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002873
Zonr Change5c7a542010-10-24 01:07:27 +08002874 // Propagate constants at call sites into the functions they call. This
2875 // opens opportunities for globalopt (and inlining) by substituting
2876 // function pointers passed as arguments to direct uses of functions.
2877 LTOPasses.add(llvm::createIPSCCPPass());
2878
2879 // Now that we internalized some globals, see if we can hack on them!
2880 LTOPasses.add(llvm::createGlobalOptimizerPass());
2881
2882 // Linking modules together can lead to duplicated global constants, only
2883 // keep one copy of each constant...
2884 LTOPasses.add(llvm::createConstantMergePass());
2885
2886 // Remove unused arguments from functions...
2887 LTOPasses.add(llvm::createDeadArgEliminationPass());
2888
2889 // Reduce the code after globalopt and ipsccp. Both can open up
2890 // significant simplification opportunities, and both can propagate
2891 // functions through function pointers. When this happens, we often have
2892 // to resolve varargs calls, etc, so let instcombine do this.
2893 LTOPasses.add(llvm::createInstructionCombiningPass());
2894
2895 // Inline small functions
2896 LTOPasses.add(llvm::createFunctionInliningPass());
2897
2898 // Remove dead EH info.
2899 LTOPasses.add(llvm::createPruneEHPass());
2900
2901 // Internalize the globals again after inlining
2902 LTOPasses.add(llvm::createGlobalOptimizerPass());
2903
2904 // Remove dead functions.
2905 LTOPasses.add(llvm::createGlobalDCEPass());
2906
2907 // If we didn't decide to inline a function, check to see if we can
2908 // transform it to pass arguments by value instead of by reference.
2909 LTOPasses.add(llvm::createArgumentPromotionPass());
2910
2911 // The IPO passes may leave cruft around. Clean up after them.
2912 LTOPasses.add(llvm::createInstructionCombiningPass());
2913 LTOPasses.add(llvm::createJumpThreadingPass());
2914
2915 // Break up allocas
2916 LTOPasses.add(llvm::createScalarReplAggregatesPass());
2917
2918 // Run a few AA driven optimizations here and now, to cleanup the code.
2919 LTOPasses.add(llvm::createFunctionAttrsPass()); // Add nocapture.
2920 LTOPasses.add(llvm::createGlobalsModRefPass()); // IP alias analysis.
2921
2922 // Hoist loop invariants.
2923 LTOPasses.add(llvm::createLICMPass());
2924
2925 // Remove redundancies.
2926 LTOPasses.add(llvm::createGVNPass());
2927
2928 // Remove dead memcpys.
2929 LTOPasses.add(llvm::createMemCpyOptPass());
2930
2931 // Nuke dead stores.
2932 LTOPasses.add(llvm::createDeadStoreEliminationPass());
2933
2934 // Cleanup and simplify the code after the scalar optimizations.
2935 LTOPasses.add(llvm::createInstructionCombiningPass());
2936
2937 LTOPasses.add(llvm::createJumpThreadingPass());
2938
2939 // Delete basic blocks, which optimization passes may have killed.
2940 LTOPasses.add(llvm::createCFGSimplificationPass());
2941
2942 // Now that we have optimized the program, discard unreachable functions.
2943 LTOPasses.add(llvm::createGlobalDCEPass());
2944
Zonr Chang6e1d6c32010-10-23 11:57:16 +08002945 LTOPasses.run(*mModule);
2946 }
2947
Zonr Chang932648d2010-10-13 22:23:56 +08002948 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002949 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08002950 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002951
Zonr Chang932648d2010-10-13 22:23:56 +08002952 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
2953 *mCodeEmitter,
2954 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002955 setError("The machine code emission is not supported by BCC on target '"
2956 + Triple + "'");
2957 goto on_bcc_compile_error;
2958 }
2959
Zonr Chang932648d2010-10-13 22:23:56 +08002960 // Run the pass (the code emitter) on every non-declaration function in the
2961 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002962 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08002963 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
2964 I != E;
2965 I++)
2966 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002967 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002968
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002969 CodeGenPasses->doFinalization();
2970
Zonr Chang932648d2010-10-13 22:23:56 +08002971 // Copy the global address mapping from code emitter and remapping
Zonr Chang932648d2010-10-13 22:23:56 +08002972 if (ExportVarMetadata) {
2973 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2974 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2975 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2976 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2977 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002978 llvm::StringRef ExportVarName =
2979 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08002980 CodeEmitter::global_addresses_const_iterator I, E;
2981 for (I = mCodeEmitter->global_address_begin(),
2982 E = mCodeEmitter->global_address_end();
2983 I != E;
2984 I++) {
2985 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002986 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08002987 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002988 mExportVars.push_back(I->second);
2989 break;
2990 }
2991 }
Zonr Chang932648d2010-10-13 22:23:56 +08002992 if (I != mCodeEmitter->global_address_end())
2993 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002994 }
2995 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08002996 // if reaching here, we know the global variable record in metadata is
2997 // not found. So we make an empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002998 mExportVars.push_back(NULL);
2999 }
3000 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
3001 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003002 }
3003
Zonr Chang932648d2010-10-13 22:23:56 +08003004 if (ExportFuncMetadata) {
3005 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
3006 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
3007 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
3008 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
3009 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003010 llvm::StringRef ExportFuncName =
3011 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
3012 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
3013 }
3014 }
3015 }
3016 }
3017
Zonr Chang932648d2010-10-13 22:23:56 +08003018 // Tell code emitter now can release the memory using during the JIT since
3019 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003020 mCodeEmitter->releaseUnnecessary();
3021
Zonr Chang932648d2010-10-13 22:23:56 +08003022 // Finally, read pragma information from the metadata node of the @Module if
3023 // any.
Zonr Chang932648d2010-10-13 22:23:56 +08003024 if (PragmaMetadata)
3025 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
3026 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
3027 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003028 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08003029 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
3030 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003031
Zonr Chang932648d2010-10-13 22:23:56 +08003032 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003033 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
3034 llvm::StringRef PragmaName =
3035 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
3036 llvm::StringRef PragmaValue =
3037 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
3038
Zonr Chang932648d2010-10-13 22:23:56 +08003039 mPragmas.push_back(
3040 std::make_pair(std::string(PragmaName.data(),
3041 PragmaName.size()),
3042 std::string(PragmaValue.data(),
3043 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003044 }
3045 }
3046 }
3047
3048 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08003049 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003050 if (CodeGenPasses) {
3051 delete CodeGenPasses;
3052 } else if (TD) {
3053 delete TD;
3054 }
3055 if (TM)
3056 delete TM;
3057
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003058 if (mError.empty()) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003059 if (!mNeverCache && mCacheFd >= 0 && mCacheNew) {
3060 genCacheFile();
3061 flock(mCacheFd, LOCK_UN);
3062 }
3063
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003064 return false;
3065 }
3066
Zonr Chang932648d2010-10-13 22:23:56 +08003067 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07003068 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003069 }
3070
Zonr Chang932648d2010-10-13 22:23:56 +08003071 // interface for bccGetScriptInfoLog()
3072 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003073 return const_cast<char*>(mError.c_str());
3074 }
3075
Zonr Chang932648d2010-10-13 22:23:56 +08003076 // interface for bccGetScriptLabel()
3077 void *lookup(const char *name) {
3078 void *addr = NULL;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003079 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3080 if (!strcmp(name, "root")) {
3081 addr = reinterpret_cast<void *>(mCacheHdr->rootAddr);
3082 } else if (!strcmp(name, "init")) {
3083 addr = reinterpret_cast<void *>(mCacheHdr->initAddr);
3084 }
3085 return addr;
3086 }
3087
Zonr Chang932648d2010-10-13 22:23:56 +08003088 if (mCodeEmitter.get())
3089 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003090 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003091 return addr;
3092 }
3093
Zonr Chang932648d2010-10-13 22:23:56 +08003094 // Interface for bccGetExportVars()
3095 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003096 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003097 BCCvoid **vars) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003098 int varCount;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003099
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003100 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3101 varCount = static_cast<int>(mCacheHdr->exportVarsCount);
3102 if (actualVarCount)
3103 *actualVarCount = varCount;
3104 if (varCount > maxVarCount)
3105 varCount = maxVarCount;
3106 if (vars) {
3107 uint32_t *cachedVars = (uint32_t *)(mCacheMapAddr +
3108 mCacheHdr->exportVarsOffset);
3109
3110 for (int i = 0; i < varCount; i++) {
3111 *vars++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedVars) +
3112 mCacheDiff);
3113 cachedVars++;
3114 }
3115 }
3116 return;
3117 }
3118
3119 varCount = mExportVars.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003120 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003121 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003122 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003123 varCount = maxVarCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003124 if (vars) {
Zonr Chang932648d2010-10-13 22:23:56 +08003125 for (ExportVarList::const_iterator I = mExportVars.begin(),
3126 E = mExportVars.end();
3127 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003128 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003129 *vars++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003130 }
3131 }
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003132
3133 return;
3134 }
3135
Zonr Chang932648d2010-10-13 22:23:56 +08003136 // Interface for bccGetExportFuncs()
3137 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003138 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003139 BCCvoid **funcs) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003140 int funcCount;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003141
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003142 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3143 funcCount = static_cast<int>(mCacheHdr->exportFuncsCount);
3144 if (actualFuncCount)
3145 *actualFuncCount = funcCount;
3146 if (funcCount > maxFuncCount)
3147 funcCount = maxFuncCount;
3148 if (funcs) {
3149 uint32_t *cachedFuncs = (uint32_t *)(mCacheMapAddr +
3150 mCacheHdr->exportFuncsOffset);
3151
3152 for (int i = 0; i < funcCount; i++) {
3153 *funcs++ = (BCCvoid *)(reinterpret_cast<char *>(*cachedFuncs) +
3154 mCacheDiff);
3155 cachedFuncs++;
3156 }
3157 }
3158 return;
3159 }
3160
3161 funcCount = mExportFuncs.size();
Zonr Chang932648d2010-10-13 22:23:56 +08003162 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003163 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003164 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003165 funcCount = maxFuncCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003166 if (funcs) {
Zonr Chang932648d2010-10-13 22:23:56 +08003167 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3168 E = mExportFuncs.end();
3169 I != E;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003170 I++) {
Zonr Chang932648d2010-10-13 22:23:56 +08003171 *funcs++ = *I;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003172 }
3173 }
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003174
3175 return;
3176 }
3177
Zonr Chang932648d2010-10-13 22:23:56 +08003178 // Interface for bccGetPragmas()
3179 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003180 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003181 BCCchar **strings) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003182 int stringCount;
3183 if (!mNeverCache && mCacheFd >= 0 && !mCacheNew) {
3184 if (actualStringCount)
3185 *actualStringCount = 0; // XXX
3186 return;
3187 }
3188
3189 stringCount = mPragmas.size() * 2;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003190
Zonr Chang932648d2010-10-13 22:23:56 +08003191 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003192 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08003193 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003194 stringCount = maxStringCount;
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003195 if (strings) {
Zonr Chang932648d2010-10-13 22:23:56 +08003196 for (PragmaList::const_iterator it = mPragmas.begin();
3197 stringCount > 0;
3198 stringCount -= 2, it++) {
3199 *strings++ = const_cast<BCCchar*>(it->first.c_str());
3200 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003201 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003202 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003203
3204 return;
3205 }
3206
Zonr Chang932648d2010-10-13 22:23:56 +08003207 // Interface for bccGetFunctions()
3208 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003209 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003210 BCCchar **functions) {
3211 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003212 mCodeEmitter->getFunctionNames(actualFunctionCount,
3213 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003214 functions);
3215 else
3216 *actualFunctionCount = 0;
3217
3218 return;
3219 }
3220
Zonr Chang932648d2010-10-13 22:23:56 +08003221 // Interface for bccGetFunctionBinary()
3222 void getFunctionBinary(BCCchar *function,
3223 BCCvoid **base,
3224 BCCsizei *length) {
3225 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003226 mCodeEmitter->getFunctionBinary(function, base, length);
3227 } else {
3228 *base = NULL;
3229 *length = 0;
3230 }
3231 return;
3232 }
3233
Zonr Chang932648d2010-10-13 22:23:56 +08003234 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003235 return mModule;
3236 }
3237
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003238 ~Compiler() {
Shih-wei Liao7f941bb2010-11-19 01:40:16 -08003239#ifdef BCC_CODE_ADDR
3240 if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
3241 if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
3242 LOGE("munmap failed while releasing mCodeDataAddr\n");
3243 }
3244 }
3245
3246 if (mCacheMapAddr) {
3247 free(mCacheMapAddr);
3248 }
3249#else
3250 if (mCacheMapAddr != 0 && mCacheMapAddr != MAP_FAILED) {
3251 if (munmap(mCacheMapAddr, mCacheSize) < 0) {
3252 LOGE("munmap failed while releasing mCacheMapAddr\n");
3253 }
3254 }
3255#endif
3256
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003257 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08003258 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003259 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003260 return;
3261 }
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003262
3263 private:
3264 // Note: loader() and genCacheFile() go hand in hand
3265 void genCacheFile() {
3266 if (lseek(mCacheFd, 0, SEEK_SET) != 0) {
3267 LOGE("Unable to seek to 0: %s\n", strerror(errno));
3268 return;
3269 }
3270
3271 bool codeOffsetNeedPadding = false;
3272
3273 uint32_t offset = sizeof(oBCCHeader);
3274
3275 // BCC Cache File Header
3276 oBCCHeader *hdr = (oBCCHeader *)malloc(sizeof(oBCCHeader));
3277
3278 if (!hdr) {
3279 LOGE("Unable to allocate oBCCHeader.\n");
3280 return;
3281 }
3282
3283 // Magic Words
3284 memcpy(hdr->magic, OBCC_MAGIC, 4);
3285 memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
3286
3287 // Timestamp
3288 hdr->sourceWhen = 0; // TODO(all)
3289 hdr->rslibWhen = 0; // TODO(all)
3290 hdr->libRSWhen = 0; // TODO(all)
3291 hdr->libbccWhen = 0; // TODO(all)
3292
3293 // Current Memory Address (Saved for Recalculation)
3294 hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
3295 hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
3296 hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
3297
3298 // Relocation Table Offset and Entry Count
3299 hdr->relocOffset = sizeof(oBCCHeader);
3300 hdr->relocCount = mCodeEmitter->mGlobalAddressMap.size();
3301
3302 offset += hdr->relocCount * (sizeof(uint32_t) * 2);
3303 // Note: each reloc has 2 entries: addr & relocTy
3304
3305 // Export Variable Table Offset and Entry Count
3306 hdr->exportVarsOffset = offset;
3307 hdr->exportVarsCount = mExportVars.size();
3308
3309 offset += hdr->exportVarsCount * sizeof(uint32_t);
3310
3311 // Export Function Table Offset and Entry Count
3312 hdr->exportFuncsOffset = offset;
3313 hdr->exportFuncsCount = mExportFuncs.size();
3314
3315 offset += hdr->exportFuncsCount * sizeof(uint32_t);
3316
3317 // Export Pragmas Table Offset and Entry Count
3318 hdr->exportPragmasOffset = offset;
3319 hdr->exportPragmasCount = 0; // TODO(all): mPragmas.size();
3320
3321 offset += hdr->exportPragmasCount * sizeof(uint32_t);
3322
3323 // Code Offset and Size
3324
3325#ifdef BCC_CODE_ADDR
3326 {
3327 long pagesize = sysconf(_SC_PAGESIZE);
3328
3329 if (offset % pagesize > 0) {
3330 codeOffsetNeedPadding = true;
3331 offset += pagesize - (offset % pagesize);
3332 }
3333 }
3334#else
3335 if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
3336 codeOffsetNeedPadding = true;
3337 offset += 0x08 - (offset & 0x07);
3338 }
3339#endif
3340
3341 hdr->codeOffset = offset;
3342 hdr->codeSize = MaxCodeSize;
3343
3344 offset += hdr->codeSize;
3345
3346 // Data (Global Variable) Offset and Size
3347 hdr->dataOffset = offset;
3348 hdr->dataSize = MaxGlobalVarSize;
3349
3350 offset += hdr->dataSize;
3351
3352 // Checksum
3353 hdr->checksum = 0; // Set Field checksum. TODO(all)
3354
3355 // Write Header
3356 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(hdr),
3357 sizeof(oBCCHeader), "Write oBCC header");
3358
3359 // TODO(all): This Code is Not Working. Fix This ASAP.
3360#if 0
3361 int *itemList = (int *) calloc(buf[k_relocCount], sizeof(void *));
3362 int *tmp = itemList;
3363
3364 CodeEmitter::global_addresses_const_iterator I, E;
3365 for (I = mCodeEmitter->global_address_begin(),
3366 E = mCodeEmitter->global_address_end();
3367 I != E;
3368 I++) {
3369 // *tmp++ = (int) I->second;
3370 // *tmp++ = 0; //XXX Output fixup_type. Assume fixup type is 0 for now.
3371 }
3372 if (tmp - itemList != buf[k_relocCount] * 4) {
3373 LOGE("reloc corrupted");
3374 goto bail;
3375 }
3376 sysWriteFully(mCacheFd,
3377 itemList,
3378 buf[k_relocCount]*sizeof(void*),
3379 "Write relocs");
3380#else
3381
3382 // Note: As long as we have comment out relocation code, we have to
3383 // seek the position to correct offset.
3384
3385 lseek(mCacheFd, hdr->exportVarsOffset, SEEK_SET);
3386#endif
3387
3388 // Write Export Variables Table
3389 {
3390 uint32_t *record, *ptr;
3391
3392 record = (uint32_t *)calloc(hdr->exportVarsCount, sizeof(uint32_t));
3393 ptr = record;
3394
3395 if (!record) {
3396 goto bail;
3397 }
3398
3399 for (ExportVarList::const_iterator I = mExportVars.begin(),
3400 E = mExportVars.end(); I != E; I++) {
3401 *ptr++ = reinterpret_cast<uint32_t>(*I);
3402 }
3403
3404 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3405 hdr->exportVarsCount * sizeof(uint32_t),
3406 "Write ExportVars");
3407
3408 free(record);
3409 }
3410
3411 // Write Export Functions Table
3412 {
3413 uint32_t *record, *ptr;
3414
3415 record = (uint32_t *)calloc(hdr->exportFuncsCount, sizeof(uint32_t));
3416 ptr = record;
3417
3418 if (!record) {
3419 goto bail;
3420 }
3421
3422 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
3423 E = mExportFuncs.end(); I != E; I++) {
3424 *ptr++ = reinterpret_cast<uint32_t>(*I);
3425 }
3426
3427 sysWriteFully(mCacheFd, reinterpret_cast<char const *>(record),
3428 hdr->exportFuncsCount * sizeof(uint32_t),
3429 "Write ExportFuncs");
3430
3431 free(record);
3432 }
3433
3434
3435 // TODO(all): Write Export Pragmas Table
3436#if 0
3437#else
3438 // Note: As long as we have comment out export pragmas table code,
3439 // we have to seek the position to correct offset.
3440
3441 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3442#endif
3443
3444 if (codeOffsetNeedPadding) {
3445 // requires additional padding
3446 lseek(mCacheFd, hdr->codeOffset, SEEK_SET);
3447 }
3448
3449 // Write Generated Code and Global Variable
3450 sysWriteFully(mCacheFd, mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize,
3451 "Write code and global variable");
3452
3453 goto close_return;
3454
3455 bail:
3456 if (ftruncate(mCacheFd, 0) != 0) {
3457 LOGW("Warning: unable to truncate cache file: %s\n", strerror(errno));
3458 }
3459
3460 close_return:
3461 free(hdr);
3462 close(mCacheFd);
3463 mCacheFd = -1;
3464 return;
3465 }
3466
3467 // OpenCacheFile() returns fd of the cache file.
3468 // Input:
3469 // BCCchar *resName: Used to genCacheFileName()
3470 // bool createIfMissing: If false, turn off caching
3471 // Output:
3472 // returns fd: If -1: Failed
3473 // mCacheNew: If true, the returned fd is new. Otherwise, the fd is the
3474 // cache file's file descriptor
3475 // Note: openCacheFile() will check the cache file's validity,
3476 // such as Magic number, sourceWhen... dependencies.
3477 int openCacheFile(const BCCchar *resName, bool createIfMissing) {
3478 int fd, cc;
3479 struct stat fdStat, fileStat;
3480 bool readOnly = false;
3481
3482 char *cacheFileName = genCacheFileName(resName, ".oBCC");
3483
3484 mCacheNew = false;
3485
3486 retry:
3487 /*
3488 * Try to open the cache file. If we've been asked to,
3489 * create it if it doesn't exist.
3490 */
3491 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
3492 if (fd < 0) {
3493 fd = open(cacheFileName, O_RDONLY, 0);
3494 if (fd < 0) {
3495 if (createIfMissing) {
3496 LOGE("Can't open bcc-cache '%s': %s\n",
3497 cacheFileName, strerror(errno));
3498 mCacheNew = true;
3499 }
3500 return fd;
3501 }
3502 readOnly = true;
3503 }
3504
3505 /*
3506 * Grab an exclusive lock on the cache file. If somebody else is
3507 * working on it, we'll block here until they complete.
3508 */
3509 LOGV("bcc: locking cache file %s (fd=%d, boot=%d)\n",
3510 cacheFileName, fd);
3511
3512 cc = flock(fd, LOCK_EX | LOCK_NB);
3513 if (cc != 0) {
3514 LOGD("bcc: sleeping on flock(%s)\n", cacheFileName);
3515 cc = flock(fd, LOCK_EX);
3516 }
3517
3518 if (cc != 0) {
3519 LOGE("Can't lock bcc cache '%s': %d\n", cacheFileName, cc);
3520 close(fd);
3521 return -1;
3522 }
3523 LOGV("bcc: locked cache file\n");
3524
3525 /*
3526 * Check to see if the fd we opened and locked matches the file in
3527 * the filesystem. If they don't, then somebody else unlinked ours
3528 * and created a new file, and we need to use that one instead. (If
3529 * we caught them between the unlink and the create, we'll get an
3530 * ENOENT from the file stat.)
3531 */
3532 cc = fstat(fd, &fdStat);
3533 if (cc != 0) {
3534 LOGE("Can't stat open file '%s'\n", cacheFileName);
3535 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3536 goto close_fail;
3537 }
3538 cc = stat(cacheFileName, &fileStat);
3539 if (cc != 0 ||
3540 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) {
3541 LOGD("bcc: our open cache file is stale; sleeping and retrying\n");
3542 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3543 flock(fd, LOCK_UN);
3544 close(fd);
3545 usleep(250 * 1000); // if something is hosed, don't peg machine
3546 goto retry;
3547 }
3548
3549 /*
3550 * We have the correct file open and locked. If the file size is zero,
3551 * then it was just created by us, and we want to fill in some fields
3552 * in the "bcc" header and set "mCacheNew". Otherwise, we want to
3553 * verify that the fields in the header match our expectations, and
3554 * reset the file if they don't.
3555 */
3556 if (fdStat.st_size == 0) {
3557 if (readOnly) { // The device is readOnly --> close_fail
3558 LOGW("bcc: file has zero length and isn't writable\n");
3559 goto close_fail;
3560 }
3561 /*cc = createEmptyHeader(fd);
3562 if (cc != 0)
3563 goto close_fail;
3564 */
3565 mCacheNew = true;
3566 LOGV("bcc: successfully initialized new cache file\n");
3567 } else {
3568 // Calculate sourceWhen
3569 // XXX
3570 uint32_t sourceWhen = 0;
3571 uint32_t rslibWhen = 0;
3572 uint32_t libRSWhen = 0;
3573 uint32_t libbccWhen = 0;
3574 if (!checkHeaderAndDependencies(fd,
3575 sourceWhen,
3576 rslibWhen,
3577 libRSWhen,
3578 libbccWhen)) {
3579 // If checkHeaderAndDependencies returns 0: FAILED
3580 // Will truncate the file and retry to createIfMissing the file
3581
3582 if (readOnly) { // Shouldn't be readonly.
3583 /*
3584 * We could unlink and rewrite the file if we own it or
3585 * the "sticky" bit isn't set on the directory. However,
3586 * we're not able to truncate it, which spoils things. So,
3587 * give up now.
3588 */
3589 if (createIfMissing) {
3590 LOGW("Cached file %s is stale and not writable\n",
3591 cacheFileName);
3592 }
3593 goto close_fail;
3594 }
3595
3596 /*
3597 * If we truncate the existing file before unlinking it, any
3598 * process that has it mapped will fail when it tries to touch
3599 * the pages? Probably OK because we use MAP_PRIVATE.
3600 */
3601 LOGD("oBCC file is stale or bad; removing and retrying (%s)\n",
3602 cacheFileName);
3603 if (ftruncate(fd, 0) != 0) {
3604 LOGW("Warning: unable to truncate cache file '%s': %s\n",
3605 cacheFileName, strerror(errno));
3606 /* keep going */
3607 }
3608 if (unlink(cacheFileName) != 0) {
3609 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
3610 cacheFileName, errno, strerror(errno));
3611 /* keep going; permission failure should probably be fatal */
3612 }
3613 LOGV("bcc: unlocking cache file %s\n", cacheFileName);
3614 flock(fd, LOCK_UN);
3615 close(fd);
3616 goto retry;
3617 } else {
3618 // Got cacheFile! Good to go.
3619 LOGV("Good cache file\n");
3620 }
3621 }
3622
3623 assert(fd >= 0);
3624 return fd;
3625
3626 close_fail:
3627 flock(fd, LOCK_UN);
3628 close(fd);
3629 return -1;
3630 } // End of openCacheFile()
3631
3632 char *genCacheFileName(const char *fileName, const char *subFileName) {
3633 char nameBuf[512];
3634 static const char kCachePath[] = "bcc-cache";
3635 char absoluteFile[sizeof(nameBuf)];
3636 const size_t kBufLen = sizeof(nameBuf) - 1;
3637 const char *dataRoot;
3638 char *cp;
3639
3640 // Get the absolute path of the raw/***.bc file.
3641 absoluteFile[0] = '\0';
3642 if (fileName[0] != '/') {
3643 /*
3644 * Generate the absolute path. This doesn't do everything it
3645 * should, e.g. if filename is "./out/whatever" it doesn't crunch
3646 * the leading "./" out, but it'll do.
3647 */
3648 if (getcwd(absoluteFile, kBufLen) == NULL) {
3649 LOGE("Can't get CWD while opening raw/***.bc file\n");
3650 return NULL;
3651 }
3652 // TODO(srhines): strncat() is a bit dangerous
3653 strncat(absoluteFile, "/", kBufLen);
3654 }
3655 strncat(absoluteFile, fileName, kBufLen);
3656
3657 if (subFileName != NULL) {
3658 strncat(absoluteFile, "/", kBufLen);
3659 strncat(absoluteFile, subFileName, kBufLen);
3660 }
3661
3662 /* Turn the path into a flat filename by replacing
3663 * any slashes after the first one with '@' characters.
3664 */
3665 cp = absoluteFile + 1;
3666 while (*cp != '\0') {
3667 if (*cp == '/') {
3668 *cp = '@';
3669 }
3670 cp++;
3671 }
3672
3673 /* Build the name of the cache directory.
3674 */
3675 dataRoot = getenv("ANDROID_DATA");
3676 if (dataRoot == NULL)
3677 dataRoot = "/data";
3678 snprintf(nameBuf, kBufLen, "%s/%s", dataRoot, kCachePath);
3679
3680 /* Tack on the file name for the actual cache file path.
3681 */
3682 strncat(nameBuf, absoluteFile, kBufLen);
3683
3684 LOGV("Cache file for '%s' '%s' is '%s'\n", fileName, subFileName, nameBuf);
3685 return strdup(nameBuf);
3686 }
3687
3688 /*
3689 * Read the oBCC header, verify it, then read the dependent section
3690 * and verify that data as well.
3691 *
3692 * On successful return, the file will be seeked immediately past the
3693 * oBCC header.
3694 */
3695 bool checkHeaderAndDependencies(int fd,
3696 uint32_t sourceWhen,
3697 uint32_t rslibWhen,
3698 uint32_t libRSWhen,
3699 uint32_t libbccWhen) {
3700 ssize_t actual;
3701 oBCCHeader optHdr;
3702 uint32_t val;
3703 uint8_t const *magic, *magicVer;
3704
3705 /*
3706 * Start at the start. The "bcc" header, when present, will always be
3707 * the first thing in the file.
3708 */
3709 if (lseek(fd, 0, SEEK_SET) != 0) {
3710 LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
3711 goto bail;
3712 }
3713
3714 /*
3715 * Read and do trivial verification on the bcc header. The header is
3716 * always in host byte order.
3717 */
3718 actual = read(fd, &optHdr, sizeof(optHdr));
3719 if (actual < 0) {
3720 LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
3721 goto bail;
3722 } else if (actual != sizeof(optHdr)) {
3723 LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
3724 (int) actual, sizeof(optHdr));
3725 goto bail;
3726 }
3727
3728 magic = optHdr.magic;
3729 if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
3730 /* not an oBCC file, or previous attempt was interrupted */
3731 LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
3732 magic[0], magic[1], magic[2], magic[3]);
3733 goto bail;
3734 }
3735
3736 magicVer = optHdr.magicVersion;
3737 if (memcmp(magic+4, OBCC_MAGIC_VERS, 4) != 0) {
3738 LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
3739 magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
3740 goto bail;
3741 }
3742
3743 /*
3744 * Do the header flags match up with what we want?
3745 *
3746 * This is useful because it allows us to automatically regenerate
3747 * a file when settings change (e.g. verification is now mandatory),
3748 * but can cause difficulties if the thing we depend upon
3749 * were handled differently than the current options specify.
3750 *
3751 * So, for now, we essentially ignore "expectVerify" and "expectOpt"
3752 * by limiting the match mask.
3753 *
3754 * The only thing we really can't handle is incorrect byte-ordering.
3755 */
3756
3757 val = optHdr.sourceWhen;
3758 if (val && (val != sourceWhen)) {
3759 LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
3760 val, sourceWhen);
3761 goto bail;
3762 }
3763 val = optHdr.rslibWhen;
3764 if (val && (val != rslibWhen)) {
3765 LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
3766 val, rslibWhen);
3767 goto bail;
3768 }
3769 val = optHdr.libRSWhen;
3770 if (val && (val != libRSWhen)) {
3771 LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
3772 val, libRSWhen);
3773 goto bail;
3774 }
3775 val = optHdr.libbccWhen;
3776 if (val && (val != libbccWhen)) {
3777 LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
3778 val, libbccWhen);
3779 goto bail;
3780 }
3781
3782 return true;
3783
3784 bail:
3785 return false;
3786 }
3787
Zonr Chang932648d2010-10-13 22:23:56 +08003788};
3789// End of Class Compiler
3790////////////////////////////////////////////////////////////////////////////////
3791
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003792
3793bool Compiler::GlobalInitialized = false;
3794
Zonr Chang932648d2010-10-13 22:23:56 +08003795// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003796llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
3797
3798std::string Compiler::Triple;
3799
3800std::string Compiler::CPU;
3801
3802std::vector<std::string> Compiler::Features;
3803
Zonr Chang932648d2010-10-13 22:23:56 +08003804// The named of metadata node that pragma resides (should be synced with
3805// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003806const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
3807
Zonr Chang932648d2010-10-13 22:23:56 +08003808// The named of metadata node that export variable name resides (should be
3809// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003810const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
3811
Zonr Chang932648d2010-10-13 22:23:56 +08003812// The named of metadata node that export function name resides (should be
3813// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003814const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
3815
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003816struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08003817 //////////////////////////////////////////////////////////////////////////////
3818 // Part I. Compiler
3819 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003820 Compiler compiler;
3821
Zonr Chang932648d2010-10-13 22:23:56 +08003822 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003823 compiler.registerSymbolCallback(pFn, pContext);
3824 }
3825
Zonr Chang932648d2010-10-13 22:23:56 +08003826 //////////////////////////////////////////////////////////////////////////////
3827 // Part II. Logistics & Error handling
3828 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003829 BCCscript() {
3830 bccError = BCC_NO_ERROR;
3831 }
3832
3833 ~BCCscript() {
3834 }
3835
3836 void setError(BCCenum error) {
3837 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
3838 bccError = error;
3839 }
3840 }
3841
3842 BCCenum getError() {
3843 BCCenum result = bccError;
3844 bccError = BCC_NO_ERROR;
3845 return result;
3846 }
3847
3848 BCCenum bccError;
3849};
3850
3851
3852extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003853BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003854 return new BCCscript();
3855}
3856
3857extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003858BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003859 return script->getError();
3860}
3861
3862extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003863void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003864 delete script;
3865}
3866
3867extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003868void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003869 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08003870 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003871 script->registerSymbolCallback(pFn, pContext);
3872}
3873
3874extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003875int bccReadModule(BCCscript *script,
Zonr Changdbee68b2010-10-22 05:02:16 +08003876 BCCvoid *module) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003877 return script->compiler.readModule(reinterpret_cast<llvm::Module*>(module));
Zonr Changdbee68b2010-10-22 05:02:16 +08003878}
3879
3880extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003881int bccReadBC(BCCscript *script,
3882 const BCCchar *bitcode,
3883 BCCint size,
3884 const BCCchar *resName) {
3885 return script->compiler.readBC(bitcode, size, resName);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003886}
3887
3888extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003889void bccLinkBC(BCCscript *script,
Zonr Chang97f5e612010-10-22 20:38:26 +08003890 const BCCchar *bitcode,
3891 BCCint size) {
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003892 script->compiler.linkBC(bitcode, size);
Zonr Chang97f5e612010-10-22 20:38:26 +08003893}
3894
3895extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003896void bccLoadBinary(BCCscript *script) {
3897 int result = script->compiler.loader();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003898 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003899 script->setError(BCC_INVALID_OPERATION);
3900}
3901
3902extern "C"
Shih-wei Liao7c5a5f72010-11-08 01:59:13 -08003903void bccCompileBC(BCCscript *script) {
3904 {
3905#if defined(__arm__)
3906 android::StopWatch compileTimer("RenderScript compile time");
3907#endif
3908 int result = script->compiler.compile();
3909 if (result)
3910 script->setError(BCC_INVALID_OPERATION);
3911 }
3912}
3913
3914extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003915void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003916 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08003917 BCCsizei *length,
3918 BCCchar *infoLog) {
3919 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003920 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003921 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003922 *length = messageLength;
3923
3924 if (infoLog && maxLength > 0) {
3925 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
3926 memcpy(infoLog, message, trimmedLength);
3927 infoLog[trimmedLength] = 0;
3928 }
3929}
3930
3931extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003932void bccGetScriptLabel(BCCscript *script,
3933 const BCCchar *name,
3934 BCCvoid **address) {
3935 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003936 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003937 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003938 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003939 script->setError(BCC_INVALID_VALUE);
3940}
3941
3942extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003943void bccGetExportVars(BCCscript *script,
3944 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003945 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003946 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003947 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
3948}
3949
3950extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003951void bccGetExportFuncs(BCCscript *script,
3952 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003953 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003954 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003955 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
3956}
3957
3958extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003959void bccGetPragmas(BCCscript *script,
3960 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003961 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003962 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003963 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
3964}
3965
3966extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003967void bccGetFunctions(BCCscript *script,
3968 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003969 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08003970 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003971 script->compiler.getFunctions(actualFunctionCount,
3972 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003973 functions);
3974}
3975
3976extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08003977void bccGetFunctionBinary(BCCscript *script,
3978 BCCchar *function,
3979 BCCvoid **base,
3980 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003981 script->compiler.getFunctionBinary(function, base, length);
3982}
3983
3984struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08003985 const Compiler *compiler;
3986 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003987};
3988
Zonr Chang932648d2010-10-13 22:23:56 +08003989} // namespace bcc