blob: 091bd47988f958e53225c5904381007cd425999d [file] [log] [blame]
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001/*
2 * Bitcode compiler (bcc) for Android:
3 * This is an eager-compilation JIT running on Android.
4 *
5 */
6
7#define LOG_TAG "bcc"
8#include <cutils/log.h>
9
10#include <ctype.h>
11#include <errno.h>
12#include <limits.h>
13#include <stdarg.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19
20#include <cutils/hashmap.h>
21
22#if defined(__i386__)
23#include <sys/mman.h>
24#endif
25
26#if defined(__arm__)
27 #define DEFAULT_ARM_CODEGEN
28 #define PROVIDE_ARM_CODEGEN
29#elif defined(__i386__)
30 #define DEFAULT_X86_CODEGEN
31 #define PROVIDE_X86_CODEGEN
32#elif defined(__x86_64__)
33 #define DEFAULT_X64_CODEGEN
34 #define PROVIDE_X64_CODEGEN
35#endif
36
37#if defined(FORCE_ARM_CODEGEN)
38 #define DEFAULT_ARM_CODEGEN
39 #undef DEFAULT_X86_CODEGEN
40 #undef DEFAULT_X64_CODEGEN
41 #define PROVIDE_ARM_CODEGEN
42 #undef PROVIDE_X86_CODEGEN
43 #undef PROVIDE_X64_CODEGEN
44#elif defined(FORCE_X86_CODEGEN)
45 #undef DEFAULT_ARM_CODEGEN
46 #define DEFAULT_X86_CODEGEN
47 #undef DEFAULT_X64_CODEGEN
48 #undef PROVIDE_ARM_CODEGEN
49 #define PROVIDE_X86_CODEGEN
50 #undef PROVIDE_X64_CODEGEN
51#elif defined(FORCE_X64_CODEGEN)
52 #undef DEFAULT_ARM_CODEGEN
53 #undef DEFAULT_X86_CODEGEN
54 #define DEFAULT_X64_CODEGEN
55 #undef PROVIDE_ARM_CODEGEN
56 #undef PROVIDE_X86_CODEGEN
57 #define PROVIDE_X64_CODEGEN
58#endif
59
60#if defined(DEFAULT_ARM_CODEGEN)
61 #define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
62#elif defined(DEFAULT_X86_CODEGEN)
63 #define TARGET_TRIPLE_STRING "i686-unknown-linux"
64#elif defined(DEFAULT_X64_CODEGEN)
65 #define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
66#endif
67
68#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
69#define ARM_USE_VFP
70#endif
71
72#include <bcc/bcc.h>
73#include "bcc_runtime.h"
74
75#define LOG_API(...) do {} while(0)
76// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
77
78#define LOG_STACK(...) do {} while(0)
79// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
80
81// #define PROVIDE_TRACE_CODEGEN
82
83#if defined(USE_DISASSEMBLER)
Shih-wei Liaocd61af32010-04-29 00:02:57 -070084# include "llvm/MC/MCInst.h" /* for class llvm::MCInst */
85# include "llvm/MC/MCAsmInfo.h" /* for class llvm::MCAsmInfo */
86# include "llvm/MC/MCInstPrinter.h" /* for class llvm::MCInstPrinter */
87# include "llvm/MC/MCDisassembler.h" /* for class llvm::MCDisassembler */
Shih-wei Liao3cf39d12010-04-29 19:30:51 -070088// If you want the disassemble results written to file, define this:
89# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -070090#endif
91
92#include <set>
93#include <map>
94#include <list>
95#include <cmath>
96#include <string>
97#include <cstring>
98#include <algorithm> /* for std::reverse */
99
100// Basic
101#include "llvm/Use.h" /* for class llvm::Use */
102#include "llvm/User.h" /* for class llvm::User */
103#include "llvm/Module.h" /* for class llvm::Module */
104#include "llvm/Function.h" /* for class llvm::Function */
105#include "llvm/Constant.h" /* for class llvm::Constant */
106#include "llvm/Constants.h" /* for class llvm::ConstantExpr */
107#include "llvm/Instruction.h" /* for class llvm::Instruction */
108#include "llvm/PassManager.h" /* for class llvm::PassManager and
109 * llvm::FunctionPassManager
110 */
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700111#include "llvm/LLVMContext.h" /* for class llvm::LLVMContext */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700112#include "llvm/GlobalValue.h" /* for class llvm::GlobalValue */
113#include "llvm/Instructions.h" /* for class llvm::CallInst */
114#include "llvm/OperandTraits.h" /* for macro
115 * DECLARE_TRANSPARENT_OPERAND_ACCESSORS
116 * and macro
117 * DEFINE_TRANSPARENT_OPERAND_ACCESSORS
118 */
119#include "llvm/TypeSymbolTable.h" /* for Type Reflection */
120
121// System
122#include "llvm/System/Host.h" /* for function
123 * llvm::sys::isLittleEndianHost()
124 */
125#include "llvm/System/Memory.h" /* for class llvm::sys::MemoryBlock */
126
127// ADT
128#include "llvm/ADT/APInt.h" /* for class llvm::APInt */
129#include "llvm/ADT/APFloat.h" /* for class llvm::APFloat */
130#include "llvm/ADT/DenseMap.h" /* for class llvm::DenseMap */
131#include "llvm/ADT/ValueMap.h" /* for class llvm::ValueMap and
132 * class llvm::ValueMapConfig
133 */
134#include "llvm/ADT/StringMap.h" /* for class llvm::StringMap */
135#include "llvm/ADT/OwningPtr.h" /* for class llvm::OwningPtr */
136#include "llvm/ADT/SmallString.h" /* for class llvm::SmallString */
137
138// Target
139#include "llvm/Target/TargetData.h" /* for class llvm::TargetData */
140#include "llvm/Target/TargetSelect.h" /* for function
141 * LLVMInitialize[ARM|X86]
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700142 * [TargetInfo|Target|Disassembler|
143 * AsmPrinter]()
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700144 */
145#include "llvm/Target/TargetOptions.h" /* for
146 * variable bool llvm::UseSoftFloat
147 * FloatABI::ABIType llvm::FloatABIType
148 * bool llvm::NoZerosInBSS
149 */
150#include "llvm/Target/TargetMachine.h" /* for class llvm::TargetMachine and
151 * llvm::TargetMachine::AssemblyFile
152 */
153#include "llvm/Target/TargetJITInfo.h" /* for class llvm::TargetJITInfo */
154#include "llvm/Target/TargetRegistry.h" /* for class llvm::TargetRegistry */
155#include "llvm/Target/SubtargetFeature.h"
156 /* for class llvm::SubtargetFeature */
157
158// Support
159#include "llvm/Support/Casting.h" /* for class cast<> */
160#include "llvm/Support/raw_ostream.h" /* for class llvm::raw_ostream and
161 * llvm::raw_string_ostream
162 */
163#include "llvm/Support/ValueHandle.h" /* for class AssertingVH<> */
164#include "llvm/Support/MemoryBuffer.h" /* for class llvm::MemoryBuffer */
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700165#include "llvm/Support/MemoryObject.h" /* for class llvm::MemoryObject */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700166#include "llvm/Support/ManagedStatic.h" /* for class llvm::llvm_shutdown */
167#include "llvm/Support/ErrorHandling.h" /* for function
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700168 * llvm::remove_fatal_error_handler()
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700169 * llvm::install_fatal_error_handler()
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700170 * and macro llvm_unreachable()
171 */
172#include "llvm/Support/StandardPasses.h"/* for function
173 * llvm::createStandardFunctionPasses()
174 * and
175 * llvm::createStandardModulePasses()
176 */
177#include "llvm/Support/FormattedStream.h"
178 /* for
179 * class llvm::formatted_raw_ostream
180 * llvm::formatted_raw_ostream::
181 * PRESERVE_STREAM
182 * llvm::FileModel::Error
183 */
184
185// Bitcode
186#include "llvm/Bitcode/ReaderWriter.h" /* for function
187 * llvm::ParseBitcodeFile()
188 */
189
190// CodeGen
191#include "llvm/CodeGen/Passes.h" /* for
192 * llvm::createLocalRegisterAllocator()
193 * and
194 * llvm::
195 * createLinearScanRegisterAllocator()
196 */
197#include "llvm/CodeGen/JITCodeEmitter.h"/* for class llvm::JITCodeEmitter */
198#include "llvm/CodeGen/MachineFunction.h"
199 /* for class llvm::MachineFunction */
200#include "llvm/CodeGen/RegAllocRegistry.h"
201 /* for class llvm::RegisterRegAlloc */
202#include "llvm/CodeGen/SchedulerRegistry.h"
203 /* for class llvm::RegisterScheduler
204 * and llvm::createDefaultScheduler()
205 */
206#include "llvm/CodeGen/MachineRelocation.h"
207 /* for class llvm::MachineRelocation */
208#include "llvm/CodeGen/MachineModuleInfo.h"
209 /* for class llvm::MachineModuleInfo */
210#include "llvm/CodeGen/MachineCodeEmitter.h"
211 /* for class llvm::MachineCodeEmitter */
212#include "llvm/CodeGen/MachineConstantPool.h"
213 /* for class llvm::MachineConstantPool
214 */
215#include "llvm/CodeGen/MachineJumpTableInfo.h"
216 /* for class llvm::MachineJumpTableInfo
217 */
218
219// ExecutionEngine
220#include "llvm/ExecutionEngine/GenericValue.h"
221 /* for struct llvm::GenericValue */
222#include "llvm/ExecutionEngine/JITMemoryManager.h"
223 /* for class llvm::JITMemoryManager */
224
225
226/*
227 * Compilation class that suits Android's needs.
228 * (Support: no argument passed, ...)
229 */
230
231namespace bcc {
232
233class Compiler {
234 /*
235 * This part is designed to be orthogonal to those exported bcc*() functions
236 * implementation and internal struct BCCscript.
237 */
238
239
240 /*********************************************
241 * The variable section below (e.g., Triple, CodeGenOptLevel)
242 * is initialized in GlobalInitialization()
243 */
244 static bool GlobalInitialized;
245
246 /*
247 * If given, this will be the name of the target triple to compile for.
248 * If not given, the initial values defined in this file will be used.
249 */
250 static std::string Triple;
251
252 static llvm::CodeGenOpt::Level CodeGenOptLevel;
253 /*
254 * End of section of GlobalInitializing variables
255 **********************************************/
256
257 /* If given, the name of the target CPU to generate code for. */
258 static std::string CPU;
259
260 /*
261 * The list of target specific features to enable or disable -- this should
262 * be a list of strings starting with '+' (enable) or '-' (disable).
263 */
264 static std::vector<std::string> Features;
265
266 struct Runtime {
267 const char* mName;
268 void* mPtr;
269 };
270 static struct Runtime Runtimes[];
271
272 static void GlobalInitialization() {
273 if(GlobalInitialized) return;
274
275 /* Set Triple, CPU and Features here */
276 Triple = TARGET_TRIPLE_STRING;
277
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700278 /* TODO: NEON for JIT */
279 //Features.push_back("+neon");
280 //Features.push_back("+vmlx");
281 //Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700282 Features.push_back("+vfp3");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700283
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700284#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
285 LLVMInitializeARMTargetInfo();
286 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700287#if defined(USE_DISASSEMBLER)
288 LLVMInitializeARMDisassembler();
289 LLVMInitializeARMAsmPrinter();
290#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700291#endif
292
293#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
294 LLVMInitializeX86TargetInfo();
295 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700296#if defined(USE_DISASSEMBLER)
297 LLVMInitializeX86Disassembler();
298 LLVMInitializeX86AsmPrinter();
299#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700300#endif
301
302#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
303 LLVMInitializeX86TargetInfo();
304 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700305#if defined(USE_DISASSEMBLER)
306 LLVMInitializeX86Disassembler();
307 LLVMInitializeX86AsmPrinter();
308#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700309#endif
310
311 /*
312 * -O0: llvm::CodeGenOpt::None
313 * -O1: llvm::CodeGenOpt::Less
314 * -O2: llvm::CodeGenOpt::Default
315 * -O3: llvm::CodeGenOpt::Aggressive
316 */
317 CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
318
319 /* Below are the global settings to LLVM */
320
321 /* Disable frame pointer elimination optimization */
322 llvm::NoFramePointerElim = false;
323
324 /*
325 * Use hardfloat ABI
326 *
327 * FIXME: Need to detect the CPU capability and decide whether to use
328 * softfp. To use softfp, change following 2 lines to
329 *
330 * llvm::FloatABIType = llvm::FloatABI::Soft;
331 * llvm::UseSoftFloat = true;
332 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700333 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700334 llvm::UseSoftFloat = false;
335
336 /*
337 * BCC needs all unknown symbols resolved at JIT/compilation time.
338 * So we don't need any dynamic relocation model.
339 */
340 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
341
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700342#if defined(DEFAULT_X64_CODEGEN)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700343 /* Data address in X86_64 architecture may reside in a far-away place */
344 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
345#else
346 /*
347 * This is set for the linker (specify how large of the virtual addresses
348 * we can access for all unknown symbols.)
349 */
350 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
351#endif
352
353 /* Register the scheduler */
354 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
355
356 /*
357 * Register allocation policy:
358 * createLocalRegisterAllocator: fast but bad quality
359 * createLinearScanRegisterAllocator: not so fast but good quality
360 */
361 llvm::RegisterRegAlloc::setDefault
362 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
363 llvm::createLocalRegisterAllocator :
364 llvm::createLinearScanRegisterAllocator);
365
366 GlobalInitialized = true;
367 return;
368 }
369
370 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
371 // std::string* Error = static_cast<std::string*>(UserData);
372 // Error->assign(Message);
373 // return;
374 fprintf(stderr, "%s\n", Message.c_str());
375 exit(1);
376 }
377
378 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700379 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700380 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700381
382 private:
383 std::string mError;
384
385 inline bool hasError() const {
386 return !mError.empty();
387 }
388 inline void setError(const char* Error) {
389 mError.assign(Error); // Copying
390 return;
391 }
392 inline void setError(const std::string& Error) {
393 mError = Error;
394 return;
395 }
396
397 typedef std::list< std::pair<std::string, std::string> > PragmaList;
398 PragmaList mPragmas;
399
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700400 typedef std::list<void*> ExportVarList;
401 ExportVarList mExportVars;
402
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700403 typedef std::list<void*> ExportFuncList;
404 ExportFuncList mExportFuncs;
405
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700406 /* Memory manager for the code reside in memory */
407 /*
408 * The memory for our code emitter is very simple and is conforming to the
409 * design decisions of Android RenderScript's Exection Environment:
410 * The code, data, and symbol sizes are limited (currently 100KB.)
411 *
412 * It's very different from typical compiler, which has no limitation
413 * on the code size. How does code emitter know the size of the code
414 * it is about to emit? It does not know beforehand. We want to solve
415 * this without complicating the code emitter too much.
416 *
417 * We solve this by pre-allocating a certain amount of memory,
418 * and then start the code emission. Once the buffer overflows, the emitter
419 * simply discards all the subsequent emission but still has a counter
420 * on how many bytes have been emitted.
421
422 * So once the whole emission is done, if there's a buffer overflow,
423 * it re-allocates the buffer with enough size (based on the
424 * counter from previous emission) and re-emit again.
425 */
426 class CodeMemoryManager : public llvm::JITMemoryManager {
427 /* {{{ */
428 private:
429 static const unsigned int MaxCodeSize = 100 * 1024; /* 100 KiB for code */
430 static const unsigned int MaxGOTSize = 1 * 1024; /* 1 KiB for global
431 offset table (GOT) */
432
433 /*
434 * Our memory layout is as follows:
435 *
436 * The direction of arrows (-> and <-) shows memory's growth direction
437 * when more space is needed.
438 *
439 * @mpCodeMem:
440 * +--------------------------------------------------------------+
441 * | Function Memory ... -> <- ... Global/Stub/GOT |
442 * +--------------------------------------------------------------+
443 * |<------------------ Total: @MaxCodeSize KiB ----------------->|
444 *
445 * Where size of GOT is @MaxGOTSize KiB.
446 *
447 * @mCurFuncMemIdx: The current index (starting from 0) of the last byte
448 * of function code's memoey usage
449 * @mCurGSGMemIdx: The current index (starting from 0) of the last byte
450 * of Global Stub/GOT's memory usage
451 *
452 */
453
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700454 uintptr_t mCurFuncMemIdx;
455 uintptr_t mCurGSGMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700456 llvm::sys::MemoryBlock* mpCodeMem;
457
458 /* GOT Base */
459 uint8_t* mpGOTBase;
460
461 typedef std::map<const llvm::Function*, pair<void* /* start address */,
462 void* /* end address */>
463 > FunctionMapTy;
464 FunctionMapTy mFunctionMap;
465
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700466 inline uintptr_t getFreeMemSize() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700467 return mCurGSGMemIdx - mCurFuncMemIdx;
468 }
469 inline uint8_t* getCodeMemBase() const {
470 return static_cast<uint8_t*>(mpCodeMem->base());
471 }
472
473 uint8_t* allocateGSGMemory(uintptr_t Size,
474 unsigned Alignment = 1 /* no alignment */)
475 {
476 if(getFreeMemSize() < Size)
477 /* The code size excesses our limit */
478 return NULL;
479
480 if(Alignment == 0)
481 Alignment = 1;
482
483 uint8_t* result = getCodeMemBase() + mCurGSGMemIdx - Size;
484 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
485
486 mCurGSGMemIdx = result - getCodeMemBase();
487
488 return result;
489 }
490
491 public:
492 CodeMemoryManager() : mpCodeMem(NULL), mpGOTBase(NULL) {
493 reset();
494 std::string ErrMsg;
495 llvm::sys::MemoryBlock B = llvm::sys::Memory::
496 AllocateRWX(MaxCodeSize, NULL, &ErrMsg);
497 if(B.base() == 0)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700498 llvm::report_fatal_error(
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700499 "Failed to allocate Memory for code emitter\n" + ErrMsg
500 );
501 mpCodeMem = new llvm::sys::MemoryBlock(B.base(), B.size());
502
503 return;
504 }
505
506 /*
507 * setMemoryWritable - When code generation is in progress,
508 * the code pages may need permissions changed.
509 */
510 void setMemoryWritable() {
511 llvm::sys::Memory::setWritable(*mpCodeMem);
512 return;
513 }
514
515 /*
516 * setMemoryExecutable - When code generation is done and we're ready to
517 * start execution, the code pages may need permissions changed.
518 */
519 void setMemoryExecutable() {
520 llvm::sys::Memory::setExecutable(*mpCodeMem);
521 return;
522 }
523
524 /*
525 * setPoisonMemory - Setting this flag to true makes the memory manager
526 * garbage values over freed memory. This is useful for testing and
527 * debugging, and is to be turned on by default in debug mode.
528 */
529 void setPoisonMemory(bool poison) {
530 /* no effect */
531 return;
532 }
533
534 /* Global Offset Table Management */
535
536 /*
537 * AllocateGOT - If the current table requires a Global Offset Table, this
538 * method is invoked to allocate it. This method is required to set HasGOT
539 * to true.
540 */
541 void AllocateGOT() {
542 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
543 mpGOTBase = allocateGSGMemory(MaxGOTSize);
544 HasGOT = true;
545 return;
546 }
547
548 /*
549 * getGOTBase - If this is managing a Global Offset Table, this method
550 * should return a pointer to its base.
551 */
552 uint8_t* getGOTBase() const {
553 return mpGOTBase;
554 }
555
556 /* Main Allocation Functions */
557
558 /*
559 * startFunctionBody - When we start JITing a function, the JIT calls this
560 * method to allocate a block of free RWX memory, which returns a pointer to
561 * it. If the JIT wants to request a block of memory of at least a certain
562 * size, it passes that value as ActualSize, and this method returns a block
563 * with at least that much space. If the JIT doesn't know ahead of time how
564 * much space it will need to emit the function, it passes 0 for the
565 * ActualSize. In either case, this method is required to pass back the size
566 * of the allocated block through ActualSize. The JIT will be careful to
567 * not write more than the returned ActualSize bytes of memory.
568 */
569 uint8_t* startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
570 if(getFreeMemSize() < ActualSize)
571 /* The code size excesses our limit */
572 return NULL;
573
574 ActualSize = getFreeMemSize();
575 return (getCodeMemBase() + mCurFuncMemIdx);
576 }
577
578 /*
579 * allocateStub - This method is called by the JIT to allocate space for a
580 * function stub (used to handle limited branch displacements) while it is
581 * JIT compiling a function. For example, if foo calls bar, and if bar
582 * either needs to be lazily compiled or is a native function that exists
583 * too
584 * far away from the call site to work, this method will be used to make a
585 * thunk for it. The stub should be "close" to the current function body,
586 * but should not be included in the 'actualsize' returned by
587 * startFunctionBody.
588 */
589 uint8_t* allocateStub(const llvm::GlobalValue* F, unsigned StubSize,
590 unsigned Alignment) {
591 return allocateGSGMemory(StubSize, Alignment);
592 }
593
594 /*
595 * endFunctionBody - This method is called when the JIT is done codegen'ing
596 * the specified function. At this point we know the size of the JIT
597 * compiled function. This passes in FunctionStart (which was returned by
598 * the startFunctionBody method) and FunctionEnd which is a pointer to the
599 * actual end of the function. This method should mark the space allocated
600 * and remember where it is in case the client wants to deallocate it.
601 */
602 void endFunctionBody(const llvm::Function* F, uint8_t* FunctionStart,
603 uint8_t* FunctionEnd) {
604 assert(FunctionEnd > FunctionStart);
605 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
606 "Mismatched function start/end!");
607
608 /* Advance the pointer */
609 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
610 assert(FunctionCodeSize <= getFreeMemSize() &&
611 "Code size excess the limitation!");
612 mCurFuncMemIdx += FunctionCodeSize;
613
614 /* Record there's a function in our memory start from @FunctionStart */
615 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
616 "Function already emitted!");
617 mFunctionMap.insert( make_pair<const llvm::Function*, pair<void*, void*>
618 >(F, make_pair(FunctionStart, FunctionEnd))
619 );
620
621 return;
622 }
623
624 /*
625 * allocateSpace - Allocate a (function code) memory block of the
626 * given size. This method cannot be called between
627 * calls to startFunctionBody and endFunctionBody.
628 */
629 uint8_t* allocateSpace(intptr_t Size, unsigned Alignment) {
630 if(getFreeMemSize() < Size)
631 /* The code size excesses our limit */
632 return NULL;
633
634 if(Alignment == 0)
635 Alignment = 1;
636
637 uint8_t* result = getCodeMemBase() + mCurFuncMemIdx;
638 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
639 ~(intptr_t) (Alignment - 1)
640 );
641
642 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
643
644 return result;
645 }
646
647 /* allocateGlobal - Allocate memory for a global. */
648 uint8_t* allocateGlobal(uintptr_t Size, unsigned Alignment) {
649 return allocateGSGMemory(Size, Alignment);
650 }
651
652 /*
653 * deallocateFunctionBody - Free the specified function body. The argument
654 * must be the return value from a call to startFunctionBody() that hasn't
655 * been deallocated yet. This is never called when the JIT is currently
656 * emitting a function.
657 */
658 void deallocateFunctionBody(void *Body) {
659 /* linear search */
660 FunctionMapTy::iterator I;
661 for(I = mFunctionMap.begin();
662 I != mFunctionMap.end();
663 I++)
664 if(I->second.first == Body)
665 break;
666
667 assert(I != mFunctionMap.end() && "Memory is never allocated!");
668
669 /* free the memory */
670 uint8_t* FunctionStart = (uint8_t*) I->second.first;
671 uint8_t* FunctionEnd = (uint8_t*) I->second.second;
672 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
673
674 assert(SizeNeedMove >= 0 &&
675 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
676 " be correctly calculated!");
677
678 if(SizeNeedMove > 0)
679 /* there's data behind deallocating function */
680 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
681 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
682
683 return;
684 }
685
686 /*
687 * startExceptionTable - When we finished JITing the function, if exception
688 * handling is set, we emit the exception table.
689 */
690 uint8_t* startExceptionTable(const llvm::Function* F, uintptr_t &ActualSize)
691 {
692 assert(false && "Exception is not allowed in our language specification");
693 return NULL;
694 }
695
696 /*
697 * endExceptionTable - This method is called when the JIT is done emitting
698 * the exception table.
699 */
700 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
701 uint8_t *TableEnd, uint8_t* FrameRegister) {
702 assert(false && "Exception is not allowed in our language specification");
703 return;
704 }
705
706 /*
707 * deallocateExceptionTable - Free the specified exception table's memory.
708 * The argument must be the return value from a call to
709 * startExceptionTable()
710 * that hasn't been deallocated yet. This is never called when the JIT is
711 * currently emitting an exception table.
712 */
713 void deallocateExceptionTable(void *ET) {
714 assert(false && "Exception is not allowed in our language specification");
715 return;
716 }
717
718 /* Below are the methods we create */
719 void reset() {
720 mpGOTBase = NULL;
721 HasGOT = false;
722
723 mCurFuncMemIdx = 0;
724 mCurGSGMemIdx = MaxCodeSize - 1;
725
726 mFunctionMap.clear();
727
728 return;
729 }
730
731 ~CodeMemoryManager() {
732 if(mpCodeMem != NULL)
733 llvm::sys::Memory::ReleaseRWX(*mpCodeMem);
734 return;
735 }
736 /* }}} */
737 }; /* End of class CodeMemoryManager */
738
739 /* The memory manager for code emitter */
740 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
741 CodeMemoryManager* createCodeMemoryManager() {
742 mCodeMemMgr.reset(new CodeMemoryManager());
743 return mCodeMemMgr.get();
744 }
745
746 /* Code emitter */
747 class CodeEmitter : public llvm::JITCodeEmitter {
748 /* {{{ */
749 public:
750 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
751 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
752
753 private:
754 CodeMemoryManager* mpMemMgr;
755
756 /* The JITInfo for the target we are compiling to */
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700757 const llvm::Target* mpTarget;
758
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700759 llvm::TargetJITInfo* mpTJI;
760
761 const llvm::TargetData* mpTD;
762
763 /*
764 * MBBLocations - This vector is a mapping from MBB ID's to their address.
765 * It is filled in by the StartMachineBasicBlock callback and queried by
766 * the getMachineBasicBlockAddress callback.
767 */
768 std::vector<uintptr_t> mMBBLocations;
769
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700770 /* mpConstantPool - The constant pool for the current function. */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700771 llvm::MachineConstantPool* mpConstantPool;
772
773 /* ConstantPoolBase - A pointer to the first entry in the constant pool. */
774 void *mpConstantPoolBase;
775
776 /* ConstPoolAddresses - Addresses of individual constant pool entries. */
777 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
778
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700779 /* mpJumpTable - The jump tables for the current function. */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700780 llvm::MachineJumpTableInfo *mpJumpTable;
781
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700782 /* mpJumpTableBase - A pointer to the first entry in the jump table. */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700783 void *mpJumpTableBase;
784
785 /*
786 * When outputting a function stub in the context of some other function, we
787 * save BufferBegin/BufferEnd/CurBufferPtr here.
788 */
789 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
790
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700791 /* mRelocations - These are the relocations that the function needs,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700792 as emitted. */
793 std::vector<llvm::MachineRelocation> mRelocations;
794
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700795 /* mLabelLocations - This vector is a mapping from Label ID's to their
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700796 address. */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700797 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700798
799 class EmittedFunctionCode {
800 public:
801 void* FunctionBody; // Beginning of the function's allocation.
802 void* Code; // The address the function's code actually starts at.
803 int Size; // The size of the function code
804
805 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
806 };
807 EmittedFunctionCode* mpCurEmitFunction;
808
809 typedef std::map<const std::string, EmittedFunctionCode*
810 > EmittedFunctionsMapTy;
811 EmittedFunctionsMapTy mEmittedFunctions;
812
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700813 /* mpMMI - Machine module info for exception informations */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700814 llvm::MachineModuleInfo* mpMMI;
815
816 GlobalAddressMapTy mGlobalAddressMap;
817
818 /*
819 * UpdateGlobalMapping - Replace an existing mapping for GV with a new
820 * address. This updates both maps as required. If "Addr" is null, the
821 * entry for the global is removed from the mappings.
822 */
823 void* UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
824 if(Addr == NULL) {
825 /* Removing mapping */
826 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
827 void *OldVal;
828
829 if(I == mGlobalAddressMap.end())
830 OldVal = NULL;
831 else {
832 OldVal = I->second;
833 mGlobalAddressMap.erase(I);
834 }
835
836 return OldVal;
837 }
838
839 void*& CurVal = mGlobalAddressMap[GV];
840 void* OldVal = CurVal;
841
842 CurVal = Addr;
843
844 return OldVal;
845 }
846
847 /*
848 * AddGlobalMapping - Tell the execution engine that the specified global is
849 * at the specified location. This is used internally as functions are
850 * JIT'd
851 * and as global variables are laid out in memory.
852 */
853 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
854 void*& CurVal = mGlobalAddressMap[GV];
855 assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!");
856 CurVal = Addr;
857 return;
858 }
859
860 /*
861 * GetPointerToGlobalIfAvailable - This returns the address of the specified
862 * global value if it is has already been codegen'd,
863 * otherwise it returns null.
864 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700865 void* GetPointerToGlobalIfAvailable(const llvm::GlobalValue* GV) {
866 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700867 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
868 }
869
870 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool* MCP) {
871 const std::vector<llvm::MachineConstantPoolEntry>& Constants =
872 MCP->getConstants();
873
874 if(Constants.empty())
875 return 0;
876
877 unsigned int Size = 0;
878 for(int i=0;i<Constants.size();i++) {
879 llvm::MachineConstantPoolEntry CPE = Constants[i];
880 unsigned int AlignMask = CPE.getAlignment() - 1;
881 Size = (Size + AlignMask) & ~AlignMask;
882 const llvm::Type* Ty = CPE.getType();
883 Size += mpTD->getTypeAllocSize(Ty);
884 }
885
886 return Size;
887 }
888
889 /*
890 * This function converts a Constant* into a GenericValue. The interesting
891 * part is if C is a ConstantExpr.
892 */
893 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue& Result) {
894 if(C->getValueID() == llvm::Value::UndefValueVal)
895 return;
896 else if(C->getValueID() == llvm::Value::ConstantExprVal) {
897 const llvm::ConstantExpr* CE = (llvm::ConstantExpr*) C;
898 const llvm::Constant* Op0 = CE->getOperand(0);
899
900 switch(CE->getOpcode()) {
901 case llvm::Instruction::GetElementPtr:
902 {
903 /* Compute the index */
904 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
905 CE->op_end());
906 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
907 &Indices[0],
908 Indices.size());
909
910 GetConstantValue(Op0, Result);
911 Result.PointerVal = (char*) Result.PointerVal + Offset;
912
913 return;
914 }
915 break;
916
917 case llvm::Instruction::Trunc:
918 {
919 uint32_t BitWidth =
920 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
921
922 GetConstantValue(Op0, Result);
923 Result.IntVal = Result.IntVal.trunc(BitWidth);
924
925 return;
926 }
927 break;
928
929 case llvm::Instruction::ZExt:
930 {
931 uint32_t BitWidth =
932 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
933
934 GetConstantValue(Op0, Result);
935 Result.IntVal = Result.IntVal.zext(BitWidth);
936
937 return;
938 }
939 break;
940
941 case llvm::Instruction::SExt:
942 {
943 uint32_t BitWidth =
944 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
945
946 GetConstantValue(Op0, Result);
947 Result.IntVal = Result.IntVal.sext(BitWidth);
948
949 return;
950 }
951 break;
952
953
954 case llvm::Instruction::FPTrunc:
955 {
956 /* FIXME long double */
957 GetConstantValue(Op0, Result);
958 Result.FloatVal = float(Result.DoubleVal);
959 return;
960 }
961 break;
962
963
964 case llvm::Instruction::FPExt:
965 {
966 /* FIXME long double */
967 GetConstantValue(Op0, Result);
968 Result.DoubleVal = double(Result.FloatVal);
969 return;
970 }
971 break;
972
973
974 case llvm::Instruction::UIToFP:
975 {
976 GetConstantValue(Op0, Result);
977 if(CE->getType()->isFloatTy())
978 Result.FloatVal = float(Result.IntVal.roundToDouble());
979 else if(CE->getType()->isDoubleTy())
980 Result.DoubleVal = Result.IntVal.roundToDouble();
981 else if(CE->getType()->isX86_FP80Ty()) {
982 const uint64_t zero[] = { 0, 0 };
983 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
984 apf.convertFromAPInt(Result.IntVal,
985 false,
986 llvm::APFloat::rmNearestTiesToEven);
987 Result.IntVal = apf.bitcastToAPInt();
988 }
989 return;
990 }
991 break;
992
993 case llvm::Instruction::SIToFP:
994 {
995 GetConstantValue(Op0, Result);
996 if(CE->getType()->isFloatTy())
997 Result.FloatVal = float(Result.IntVal.signedRoundToDouble());
998 else if(CE->getType()->isDoubleTy())
999 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1000 else if(CE->getType()->isX86_FP80Ty()) {
1001 const uint64_t zero[] = { 0, 0 };
1002 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1003 apf.convertFromAPInt(Result.IntVal,
1004 true,
1005 llvm::APFloat::rmNearestTiesToEven);
1006 Result.IntVal = apf.bitcastToAPInt();
1007 }
1008 return;
1009 }
1010 break;
1011
1012 /* double->APInt conversion handles sign */
1013 case llvm::Instruction::FPToUI:
1014 case llvm::Instruction::FPToSI:
1015 {
1016 uint32_t BitWidth =
1017 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1018
1019 GetConstantValue(Op0, Result);
1020 if(Op0->getType()->isFloatTy())
1021 Result.IntVal =
1022 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1023 else if(Op0->getType()->isDoubleTy())
1024 Result.IntVal =
1025 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal, BitWidth);
1026 else if(Op0->getType()->isX86_FP80Ty()) {
1027 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1028 uint64_t v;
1029 bool ignored;
1030 apf.convertToInteger(&v,
1031 BitWidth,
1032 CE->getOpcode()
1033 == llvm::Instruction::FPToSI,
1034 llvm::APFloat::rmTowardZero,
1035 &ignored);
1036 Result.IntVal = v; // endian?
1037 }
1038 return;
1039 }
1040 break;
1041
1042 case llvm::Instruction::PtrToInt:
1043 {
1044 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1045
1046 GetConstantValue(Op0, Result);
1047 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1048 (Result.PointerVal));
1049
1050 return;
1051 }
1052 break;
1053
1054 case llvm::Instruction::IntToPtr:
1055 {
1056 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1057
1058 GetConstantValue(Op0, Result);
1059 if(PtrWidth != Result.IntVal.getBitWidth())
1060 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1061 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1062
1063 Result.PointerVal = llvm::PointerTy
1064 (uintptr_t(Result.IntVal.getZExtValue()));
1065
1066 return;
1067 }
1068 break;
1069
1070 case llvm::Instruction::BitCast:
1071 {
1072 GetConstantValue(Op0, Result);
1073 const llvm::Type* DestTy = CE->getType();
1074
1075 switch(Op0->getType()->getTypeID()) {
1076 case llvm::Type::IntegerTyID:
1077 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1078 if(DestTy->isFloatTy())
1079 Result.FloatVal = Result.IntVal.bitsToFloat();
1080 else if(DestTy->isDoubleTy())
1081 Result.DoubleVal = Result.IntVal.bitsToDouble();
1082 break;
1083
1084 case llvm::Type::FloatTyID:
1085 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1086 Result.IntVal.floatToBits(Result.FloatVal);
1087 break;
1088
1089 case llvm::Type::DoubleTyID:
1090 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1091 Result.IntVal.doubleToBits(Result.DoubleVal);
1092 break;
1093
1094 case llvm::Type::PointerTyID:
1095 assert(DestTy->isPointerTy() && "Invalid bitcast");
1096 break; // getConstantValue(Op0) above already converted it
1097
1098 default:
1099 llvm_unreachable("Invalid bitcast operand");
1100 break;
1101 }
1102
1103 return;
1104 }
1105 break;
1106
1107 case llvm::Instruction::Add:
1108 case llvm::Instruction::FAdd:
1109 case llvm::Instruction::Sub:
1110 case llvm::Instruction::FSub:
1111 case llvm::Instruction::Mul:
1112 case llvm::Instruction::FMul:
1113 case llvm::Instruction::UDiv:
1114 case llvm::Instruction::SDiv:
1115 case llvm::Instruction::URem:
1116 case llvm::Instruction::SRem:
1117 case llvm::Instruction::And:
1118 case llvm::Instruction::Or:
1119 case llvm::Instruction::Xor:
1120 {
1121 llvm::GenericValue LHS, RHS;
1122 GetConstantValue(Op0, LHS);
1123 GetConstantValue(CE->getOperand(1), RHS);
1124
1125 switch(Op0->getType()->getTypeID()) {
1126 case llvm::Type::IntegerTyID:
1127 switch (CE->getOpcode()) {
1128 case llvm::Instruction::Add:
1129 Result.IntVal = LHS.IntVal + RHS.IntVal;
1130 break;
1131 case llvm::Instruction::Sub:
1132 Result.IntVal = LHS.IntVal - RHS.IntVal;
1133 break;
1134 case llvm::Instruction::Mul:
1135 Result.IntVal = LHS.IntVal * RHS.IntVal;
1136 break;
1137 case llvm::Instruction::UDiv:
1138 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1139 break;
1140 case llvm::Instruction::SDiv:
1141 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1142 break;
1143 case llvm::Instruction::URem:
1144 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1145 break;
1146 case llvm::Instruction::SRem:
1147 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1148 break;
1149 case llvm::Instruction::And:
1150 Result.IntVal = LHS.IntVal & RHS.IntVal;
1151 break;
1152 case llvm::Instruction::Or:
1153 Result.IntVal = LHS.IntVal | RHS.IntVal;
1154 break;
1155 case llvm::Instruction::Xor:
1156 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1157 break;
1158 default:
1159 llvm_unreachable("Invalid integer opcode");
1160 break;
1161 }
1162 break;
1163
1164 case llvm::Type::FloatTyID:
1165 switch (CE->getOpcode()) {
1166 case llvm::Instruction::FAdd:
1167 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1168 break;
1169 case llvm::Instruction::FSub:
1170 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1171 break;
1172 case llvm::Instruction::FMul:
1173 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1174 break;
1175 case llvm::Instruction::FDiv:
1176 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1177 break;
1178 case llvm::Instruction::FRem:
1179 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1180 break;
1181 default:
1182 llvm_unreachable("Invalid float opcode");
1183 break;
1184 }
1185 break;
1186
1187 case llvm::Type::DoubleTyID:
1188 switch (CE->getOpcode()) {
1189 case llvm::Instruction::FAdd:
1190 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1191 break;
1192 case llvm::Instruction::FSub:
1193 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1194 break;
1195 case llvm::Instruction::FMul:
1196 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1197 break;
1198 case llvm::Instruction::FDiv:
1199 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1200 break;
1201 case llvm::Instruction::FRem:
1202 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1203 break;
1204 default:
1205 llvm_unreachable("Invalid double opcode");
1206 break;
1207 }
1208 break;
1209
1210 case llvm::Type::X86_FP80TyID:
1211 case llvm::Type::PPC_FP128TyID:
1212 case llvm::Type::FP128TyID:
1213 {
1214 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1215 switch (CE->getOpcode()) {
1216 case llvm::Instruction::FAdd:
1217 apfLHS.add(llvm::APFloat(RHS.IntVal),
1218 llvm::APFloat::rmNearestTiesToEven);
1219 break;
1220 case llvm::Instruction::FSub:
1221 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1222 llvm::APFloat::rmNearestTiesToEven);
1223 break;
1224 case llvm::Instruction::FMul:
1225 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1226 llvm::APFloat::rmNearestTiesToEven);
1227 break;
1228 case llvm::Instruction::FDiv:
1229 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1230 llvm::APFloat::rmNearestTiesToEven);
1231 break;
1232 case llvm::Instruction::FRem:
1233 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1234 llvm::APFloat::rmNearestTiesToEven);
1235 break;
1236 default:
1237 llvm_unreachable("Invalid long double opcode");
1238 llvm_unreachable(0);
1239 break;
1240 }
1241
1242 Result.IntVal = apfLHS.bitcastToAPInt();
1243 }
1244 break;
1245
1246 default:
1247 llvm_unreachable("Bad add type!");
1248 break;
1249 } /* End switch(Op0->getType()->getTypeID()) */
1250
1251 return;
1252 }
1253
1254 default:
1255 break;
1256 } /* End switch(CE->getOpcode()) */
1257
1258 std::string msg;
1259 llvm::raw_string_ostream Msg(msg);
1260 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001261 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001262 } /* C->getValueID() == llvm::Value::ConstantExprVal */
1263
1264 switch (C->getType()->getTypeID()) {
1265 case llvm::Type::FloatTyID:
1266 Result.FloatVal = llvm::cast<llvm::ConstantFP>(C)
1267 ->getValueAPF().convertToFloat();
1268 break;
1269
1270 case llvm::Type::DoubleTyID:
1271 Result.DoubleVal = llvm::cast<llvm::ConstantFP>(C)
1272 ->getValueAPF().convertToDouble();
1273 break;
1274
1275 case llvm::Type::X86_FP80TyID:
1276 case llvm::Type::FP128TyID:
1277 case llvm::Type::PPC_FP128TyID:
1278 Result.IntVal = llvm::cast <llvm::ConstantFP>(C)
1279 ->getValueAPF().bitcastToAPInt();
1280 break;
1281
1282 case llvm::Type::IntegerTyID:
1283 Result.IntVal = llvm::cast<llvm::ConstantInt>(C)
1284 ->getValue();
1285 break;
1286
1287 case llvm::Type::PointerTyID:
1288 switch(C->getValueID()) {
1289 case llvm::Value::ConstantPointerNullVal:
1290 Result.PointerVal = NULL;
1291 break;
1292
1293 case llvm::Value::FunctionVal:
1294 {
1295 const llvm::Function* F = (llvm::Function*) C;
1296 Result.PointerVal = GetPointerToFunctionOrStub
1297 (const_cast<llvm::Function*>(F)
1298 );
1299 }
1300 break;
1301
1302 case llvm::Value::GlobalVariableVal:
1303 {
1304 const llvm::GlobalVariable* GV = (llvm::GlobalVariable*) C;
1305 Result.PointerVal = GetOrEmitGlobalVariable
1306 (const_cast<llvm::GlobalVariable*>(GV)
1307 );
1308 }
1309 break;
1310
1311 case llvm::Value::BlockAddressVal:
1312 {
1313 // const llvm::BlockAddress* BA = (llvm::BlockAddress*) C;
1314 // Result.PointerVal = getPointerToBasicBlock
1315 // (const_cast<llvm::BasicBlock*>(BA->getBasicBlock()));
1316 assert(false && "JIT does not support address-of-label yet!");
1317 }
1318 break;
1319
1320 default:
1321 llvm_unreachable("Unknown constant pointer type!");
1322 break;
1323 }
1324 break;
1325
1326 default:
1327 std::string msg;
1328 llvm::raw_string_ostream Msg(msg);
1329 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001330 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001331 break;
1332 }
1333
1334 return;
1335 }
1336
1337 /*
1338 * StoreValueToMemory -
1339 * Stores the data in @Val of type @Ty at address @Addr.
1340 */
1341 void StoreValueToMemory(const llvm::GenericValue& Val, void* Addr,
1342 const llvm::Type *Ty) {
1343 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1344
1345 switch(Ty->getTypeID()) {
1346 case llvm::Type::IntegerTyID:
1347 {
1348 const llvm::APInt& IntVal = Val.IntVal;
1349 assert((IntVal.getBitWidth() + 7) / 8 >= StoreBytes &&
1350 "Integer too small!");
1351
1352 uint8_t *Src = (uint8_t*) IntVal.getRawData();
1353
1354 if(llvm::sys::isLittleEndianHost()) {
1355 /*
1356 * Little-endian host - the source is ordered from LSB to MSB.
1357 * Order the destination from LSB to MSB: Do a straight copy.
1358 */
1359 memcpy(Addr, Src, StoreBytes);
1360 } else {
1361 /*
1362 * Big-endian host - the source is an array of 64 bit words
1363 * ordered from LSW to MSW.
1364 *
1365 * Each word is ordered from MSB to LSB.
1366 *
1367 * Order the destination from MSB to LSB:
1368 * Reverse the word order, but not the bytes in a word.
1369 */
1370 unsigned int i = StoreBytes;
1371 while(i > sizeof(uint64_t)) {
1372 i -= sizeof(uint64_t);
1373 memcpy((uint8_t*) Addr + i, Src, sizeof(uint64_t));
1374 Src += sizeof(uint64_t);
1375 }
1376
1377 memcpy(Addr, Src + sizeof(uint64_t) - i, i);
1378 }
1379 }
1380 break;
1381
1382 case llvm::Type::FloatTyID:
1383 {
1384 *((float*) Addr) = Val.FloatVal;
1385 }
1386 break;
1387
1388 case llvm::Type::DoubleTyID:
1389 {
1390 *((double*) Addr) = Val.DoubleVal;
1391 }
1392 break;
1393
1394 case llvm::Type::X86_FP80TyID:
1395 {
1396 memcpy(Addr, Val.IntVal.getRawData(), 10);
1397 }
1398 break;
1399
1400 case llvm::Type::PointerTyID:
1401 {
1402 /*
1403 * Ensure 64 bit target pointers are fully
1404 * initialized on 32 bit hosts.
1405 */
1406 if(StoreBytes != sizeof(llvm::PointerTy))
1407 memset(Addr, 0, StoreBytes);
1408 *((llvm::PointerTy*) Addr) = Val.PointerVal;
1409 }
1410 break;
1411
1412 default:
1413 break;
1414 }
1415
1416 if(llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1417 std::reverse((uint8_t*) Addr, (uint8_t*) Addr + StoreBytes);
1418
1419 return;
1420 }
1421
1422 /*
1423 * InitializeConstantToMemory -
1424 * Recursive function to apply a @Constant value into the
1425 * specified memory location @Addr.
1426 */
1427 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
1428 switch(C->getValueID()) {
1429 case llvm::Value::UndefValueVal:
1430 // Nothing to do
1431 break;
1432
1433 case llvm::Value::ConstantVectorVal:
1434 {
1435 // dynamic cast may hurt performance
1436 const llvm::ConstantVector* CP = (llvm::ConstantVector*) C;
1437
1438 unsigned int ElementSize = mpTD->getTypeAllocSize
1439 (CP->getType()->getElementType());
1440
1441 for(int i=0;i<CP->getNumOperands();i++)
1442 InitializeConstantToMemory(CP->getOperand(i),
1443 (char*) Addr + i * ElementSize);
1444 }
1445 break;
1446
1447 case llvm::Value::ConstantAggregateZeroVal:
1448 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1449 break;
1450
1451 case llvm::Value::ConstantArrayVal:
1452 {
1453 const llvm::ConstantArray* CPA = (llvm::ConstantArray*) C;
1454 unsigned int ElementSize = mpTD->getTypeAllocSize
1455 (CPA->getType()->getElementType());
1456
1457 for(int i=0;i<CPA->getNumOperands();i++)
1458 InitializeConstantToMemory(CPA->getOperand(i),
1459 (char*) Addr + i * ElementSize);
1460 }
1461 break;
1462
1463 case llvm::Value::ConstantStructVal:
1464 {
1465 const llvm::ConstantStruct* CPS = (llvm::ConstantStruct*) C;
1466 const llvm::StructLayout* SL = mpTD->getStructLayout
1467 (llvm::cast<llvm::StructType>(CPS->getType()));
1468
1469 for(int i=0;i<CPS->getNumOperands();i++)
1470 InitializeConstantToMemory(CPS->getOperand(i),
1471 (char*) Addr +
1472 SL->getElementOffset(i));
1473 }
1474 break;
1475
1476 default:
1477 {
1478 if(C->getType()->isFirstClassType()) {
1479 llvm::GenericValue Val;
1480 GetConstantValue(C, Val);
1481 StoreValueToMemory(Val, Addr, C->getType());
1482 } else
1483 llvm_unreachable
1484 ("Unknown constant type to initialize memory with!");
1485 }
1486 break;
1487 }
1488
1489 return;
1490 }
1491
1492 void emitConstantPool(llvm::MachineConstantPool *MCP) {
1493 if(mpTJI->hasCustomConstantPool())
1494 return;
1495
1496 /*
1497 * Constant pool address resolution is handled by the target itself in ARM
1498 * (TargetJITInfo::hasCustomConstantPool() return true).
1499 */
1500#if !defined(PROVIDE_ARM_CODEGEN)
1501 const std::vector<llvm::MachineConstantPoolEntry>& Constants =
1502 MCP->getConstants();
1503
1504 if(Constants.empty())
1505 return;
1506
1507 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1508 unsigned Align = MCP->getConstantPoolAlignment();
1509
1510 mpConstantPoolBase = allocateSpace(Size, Align);
1511 mpConstantPool = MCP;
1512
1513 if(mpConstantPoolBase == NULL)
1514 return; /* out of memory */
1515
1516 unsigned Offset = 0;
1517 for(int i=0;i<Constants.size();i++) {
1518 llvm::MachineConstantPoolEntry CPE = Constants[i];
1519 unsigned AlignMask = CPE.getAlignment() - 1;
1520 Offset = (Offset + AlignMask) & ~AlignMask;
1521
1522 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1523 mConstPoolAddresses.push_back(CAddr);
1524
1525 if(CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001526 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001527 ("Initialize memory with machine specific constant pool"
1528 " entry has not been implemented!");
1529
1530 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1531
1532 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1533 Offset += mpTD->getTypeAllocSize(Ty);
1534 }
1535#endif
1536 return;
1537 }
1538
1539 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
1540 if(mpTJI->hasCustomJumpTables())
1541 return;
1542
1543 const std::vector<llvm::MachineJumpTableEntry>& JT =
1544 MJTI->getJumpTables();
1545 if(JT.empty())
1546 return;
1547
1548 unsigned NumEntries = 0;
1549 for(int i=0;i<JT.size();i++)
1550 NumEntries += JT[i].MBBs.size();
1551
1552 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1553
1554 mpJumpTable = MJTI;;
1555 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
1556 MJTI->getEntryAlignment(*mpTD));
1557
1558 return;
1559 }
1560
1561 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
1562 if(mpTJI->hasCustomJumpTables())
1563 return;
1564
1565 const std::vector<llvm::MachineJumpTableEntry>& JT =
1566 MJTI->getJumpTables();
1567 if(JT.empty() || mpJumpTableBase == 0)
1568 return;
1569
1570 assert((llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static)
1571 && "Cross JIT'ing?");
1572 assert(MJTI->getEntrySize(*mpTD) == sizeof(void*) && "Cross JIT'ing?");
1573
1574 /*
1575 * For each jump table, map each target in the jump table to the
1576 * address of an emitted MachineBasicBlock.
1577 */
1578 intptr_t *SlotPtr = (intptr_t*) mpJumpTableBase;
1579 for(int i=0;i<JT.size();i++) {
1580 const std::vector<llvm::MachineBasicBlock*>& MBBs = JT[i].MBBs;
1581 /*
1582 * Store the address of the basic block for this jump table slot in the
1583 * memory we allocated for the jump table in 'initJumpTableInfo'
1584 */
1585 for(int j=0;j<MBBs.size();j++)
1586 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1587 }
1588 }
1589
1590 void* GetPointerToGlobal(llvm::GlobalValue* V, void* Reference,
1591 bool MayNeedFarStub) {
1592 switch(V->getValueID()) {
1593 case llvm::Value::FunctionVal:
1594 {
1595 llvm::Function* F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001596
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001597 /* If we have code, go ahead and return that. */
1598 if(void* ResultPtr = GetPointerToGlobalIfAvailable(F))
1599 return ResultPtr;
1600
1601 if(void* FnStub = GetLazyFunctionStubIfAvailable(F))
1602 /*
1603 * Return the function stub if it's already created.
1604 * We do this first so that:
1605 * we're returning the same address for the function
1606 * as any previous call.
1607 *
1608 * TODO: Yes, this is wrong. The lazy stub isn't guaranteed
1609 * to be close enough to call.
1610 */
1611 return FnStub;
1612
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001613 /*
1614 * If we know the target can handle arbitrary-distance calls, try to
1615 * return a direct pointer.
1616 */
1617 if(!MayNeedFarStub) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001618 /*
1619 * x86_64 architecture may encounter the bug
1620 * http://hlvm.llvm.org/bugs/show_bug.cgi?id=5201
1621 * which generate instruction "call" instead of "callq".
1622 *
1623 * And once the real address of stub is
1624 * greater than 64-bit long, the replacement will truncate
1625 * to 32-bit resulting a serious problem.
1626 */
1627#if !defined(__x86_64__)
1628 /*
1629 * If this is an external function pointer,
1630 * we can force the JIT to
1631 * 'compile' it, which really just adds it to the map.
1632 */
1633 if(F->isDeclaration() || F->hasAvailableExternallyLinkage())
1634 return GetPointerToFunction(F, /* AbortOnFailure */true);
1635#endif
1636 }
1637
1638 /*
1639 * Otherwise, we may need a to emit a stub, and, conservatively, we
1640 * always do so.
1641 */
1642 return GetLazyFunctionStub(F);
1643 }
1644 break;
1645
1646 case llvm::Value::GlobalVariableVal:
1647 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1648 break;
1649
1650 case llvm::Value::GlobalAliasVal:
1651 {
1652 llvm::GlobalAlias* GA = (llvm::GlobalAlias*) V;
1653 const llvm::GlobalValue* GV = GA->resolveAliasedGlobal(false);
1654
1655 switch(GV->getValueID()) {
1656 case llvm::Value::FunctionVal:
1657 /* FIXME: is there's any possibility that the function
1658 is not code-gen'd? */
1659 return GetPointerToFunction(
1660 const_cast<llvm::Function*>((const llvm::Function*) GV),
1661 /* AbortOnFailure */true
1662 );
1663 break;
1664
1665 case llvm::Value::GlobalVariableVal:
1666 {
1667 if(void* p = mGlobalAddressMap[GV])
1668 return p;
1669
1670 llvm::GlobalVariable* GVar = (llvm::GlobalVariable*) GV;
1671 EmitGlobalVariable(GVar);
1672
1673 return mGlobalAddressMap[GV];
1674 }
1675 break;
1676
1677 case llvm::Value::GlobalAliasVal:
1678 assert(false && "Alias should be resolved ultimately!");
1679 break;
1680 }
1681 }
1682 break;
1683
1684 default:
1685 break;
1686 }
1687
1688 llvm_unreachable("Unknown type of global value!");
1689
1690 }
1691
1692 /*
1693 * GetPointerToFunctionOrStub - If the specified function has been
1694 * code-gen'd, return a pointer to the function.
1695 * If not, compile it, or use
1696 * a stub to implement lazy compilation if available.
1697 */
1698 void* GetPointerToFunctionOrStub(llvm::Function* F) {
1699 /*
1700 * If we have already code generated the function,
1701 * just return the address.
1702 */
1703 if(void* Addr = GetPointerToGlobalIfAvailable(F))
1704 return Addr;
1705
1706 /* Get a stub if the target supports it. */
1707 return GetLazyFunctionStub(F);
1708 }
1709
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001710 typedef llvm::DenseMap<const llvm::Function*, void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001711 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1712
1713 void* GetLazyFunctionStubIfAvailable(llvm::Function* F) {
1714 return mFunctionToLazyStubMap.lookup(F);
1715 }
1716
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001717 std::set<const llvm::Function*> PendingFunctions;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001718 void* GetLazyFunctionStub(llvm::Function* F) {
1719 /* If we already have a lazy stub for this function, recycle it. */
1720 void*& Stub = mFunctionToLazyStubMap[F];
1721 if(Stub)
1722 return Stub;
1723
1724 /*
1725 * In any cases, we should NOT resolve function at runtime
1726 * (though we are able to).
1727 * We resolve this right now.
1728 */
1729 void* Actual = NULL;
1730 if(F->isDeclaration() || F->hasAvailableExternallyLinkage())
1731 Actual = GetPointerToFunction(F, /* AbortOnFailure */true);
1732
1733 /*
1734 * Codegen a new stub, calling the actual address of
1735 * the external function, if it was resolved.
1736 */
1737 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1738 startGVStub(F, SL.Size, SL.Alignment);
1739 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1740 finishGVStub();
1741
1742 /*
1743 * We really want the address of the stub in the GlobalAddressMap
1744 * for the JIT, not the address of the external function.
1745 */
1746 UpdateGlobalMapping(F, Stub);
1747
1748 if(!Actual)
1749 PendingFunctions.insert(F);
1750 else
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001751 Disassemble(F->getName(), (uint8_t*) Stub, SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001752
1753 return Stub;
1754 }
1755
1756 /* Our resolver to undefined symbol */
1757 BCCSymbolLookupFn mpSymbolLookupFn;
1758 void* mpSymbolLookupContext;
1759
1760 void* GetPointerToFunction(llvm::Function* F, bool AbortOnFailure) {
1761 void* Addr = GetPointerToGlobalIfAvailable(F);
1762 if(Addr)
1763 return Addr;
1764
1765 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1766 "Internal error: only external defined function routes here!");
1767
1768 /* Handle the failure resolution by ourselves. */
1769 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
1770 /* AbortOnFailure */ false);
1771
1772 /*
1773 * If we resolved the symbol to a null address (eg. a weak external)
1774 * return a null pointer let the application handle it.
1775 */
1776 if(Addr == NULL)
1777 if(AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001778 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001779 ("Could not resolve external function address: " + F->getName()
1780 );
1781 else
1782 return NULL;
1783
1784 AddGlobalMapping(F, Addr);
1785
1786 return Addr;
1787 }
1788
1789 void* GetPointerToNamedSymbol(const std::string& Name,
1790 bool AbortOnFailure) {
1791 if(void* Addr = FindRuntimeFunction(Name.c_str()))
1792 return Addr;
1793
1794 if(mpSymbolLookupFn)
1795 if(void* Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
1796 return Addr;
1797
1798 if(AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001799 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001800 "' which could not be resolved!");
1801
1802 return NULL;
1803 }
1804
1805 /*
1806 * GetOrEmitGlobalVariable - Return the address of the specified global
1807 * variable, possibly emitting it to memory if needed. This is used by the
1808 * Emitter.
1809 */
1810 void* GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1811 void* Ptr = GetPointerToGlobalIfAvailable(GV);
1812 if(Ptr)
1813 return Ptr;
1814
1815 if(GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1816 /* If the global is external, just remember the address. */
1817 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1818 AddGlobalMapping(GV, Ptr);
1819 } else {
1820 /* If the global hasn't been emitted to memory yet,
1821 allocate space and emit it into memory. */
1822 Ptr = GetMemoryForGV(GV);
1823 AddGlobalMapping(GV, Ptr);
1824 EmitGlobalVariable(GV);
1825 }
1826
1827 return Ptr;
1828 }
1829
1830 /*
1831 * GetMemoryForGV - This method abstracts memory allocation of global
1832 * variable so that the JIT can allocate thread local variables depending
1833 * on the target.
1834 */
1835 void* GetMemoryForGV(const llvm::GlobalVariable* GV) {
1836 char* Ptr;
1837
1838 const llvm::Type* GlobalType = GV->getType()->getElementType();
1839 size_t S = mpTD->getTypeAllocSize(GlobalType);
1840 size_t A = mpTD->getPreferredAlignment(GV);
1841
1842 if(GV->isThreadLocal()) {
1843 /*
1844 * We can support TLS by
1845 *
1846 * Ptr = TJI.allocateThreadLocalMemory(S);
1847 *
1848 * But I tend not to .
1849 * (should we disable this in the front-end (i.e. slang)?).
1850 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001851 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001852 ("Compilation of Thread Local Storage (TLS) is disabled!");
1853
1854 } else if(mpTJI->allocateSeparateGVMemory()) {
1855 /*
1856 * On the Apple's ARM target (such as iPhone),
1857 * the global variable should be
1858 * placed in separately allocated heap memory rather than in the same
1859 * code memory.
1860 * The question is, how about the Android?
1861 */
1862 if(A <= 8) {
1863 Ptr = (char*) malloc(S);
1864 } else {
1865 /*
1866 * Allocate (S + A) bytes of memory,
1867 * then use an aligned pointer within that space.
1868 */
1869 Ptr = (char*) malloc(S + A);
1870 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
1871 Ptr = Ptr + (MisAligned ? (A - MisAligned) : 0);
1872 }
1873 } else {
1874 Ptr = (char*) allocateGlobal(S, A);
1875 }
1876
1877 return Ptr;
1878 }
1879
1880 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
1881 void* GA = GetPointerToGlobalIfAvailable(GV);
1882
1883 if(GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001884 llvm::report_fatal_error
1885 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001886
1887 if(GA == NULL) {
1888 /* If it's not already specified, allocate memory for the global. */
1889 GA = GetMemoryForGV(GV);
1890 AddGlobalMapping(GV, GA);
1891 }
1892
1893 InitializeConstantToMemory(GV->getInitializer(), GA);
1894
1895 /* You can do some statistics on global variable here */
1896 return;
1897 }
1898
1899 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1900 > GlobalToIndirectSymMapTy;
1901 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1902
1903 void* GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1904 /*
1905 * Make sure GV is emitted first, and create a stub containing the fully
1906 * resolved address.
1907 */
1908 void* GVAddress = GetPointerToGlobal(V, Reference, false);
1909
1910 /* If we already have a stub for this global variable, recycle it. */
1911 void*& IndirectSym = GlobalToIndirectSymMap[V];
1912 /* Otherwise, codegen a new indirect symbol. */
1913 if(!IndirectSym)
1914 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1915
1916 return IndirectSym;
1917 }
1918
1919 /*
1920 * ExternalFnToStubMap - This is the equivalent of FunctionToLazyStubMap
1921 * for external functions.
1922 *
1923 * TODO: Of course, external functions don't need a lazy stub.
1924 * It's actually
1925 * here to make it more likely that far calls succeed, but no single
1926 * stub can guarantee that. I'll remove this in a subsequent checkin
1927 * when I actually fix far calls. (comment from LLVM source)
1928 */
1929 std::map<void*, void*> ExternalFnToStubMap;
1930
1931 /*
1932 * GetExternalFunctionStub - Return a stub for the function at the
1933 * specified address.
1934 */
1935 void* GetExternalFunctionStub(void* FnAddr) {
1936 void*& Stub = ExternalFnToStubMap[FnAddr];
1937 if(Stub)
1938 return Stub;
1939
1940 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1941 startGVStub(0, SL.Size, SL.Alignment);
1942 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1943 finishGVStub();
1944
1945 return Stub;
1946 }
1947
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001948#if defined(USE_DISASSEMBLER)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001949 const llvm::MCAsmInfo* mpAsmInfo;
1950 const llvm::MCDisassembler* mpDisassmbler;
1951 llvm::MCInstPrinter* mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001952
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001953 class BufferMemoryObject : public llvm::MemoryObject {
1954 private:
1955 const uint8_t* mBytes;
1956 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001957
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001958 public:
1959 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1960 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001961
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001962 uint64_t getBase() const { return 0; }
1963 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001964
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001965 int readByte(uint64_t Addr, uint8_t *Byte) const {
1966 if(Addr > getExtent())
1967 return -1;
1968 *Byte = mBytes[Addr];
1969 return 0;
1970 }
1971 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001972
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001973 void Disassemble(const llvm::StringRef& Name, uint8_t* Start,
1974 size_t Length, bool IsStub) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001975 llvm::raw_fd_ostream* OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001976#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001977 std::string ErrorInfo;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001978 OS = new llvm::raw_fd_ostream(
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001979 "/data/local/tmp/out.S", ErrorInfo, llvm::raw_fd_ostream::F_Append);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001980 if(!ErrorInfo.empty()) { // some errors occurred
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001981 //LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001982 delete OS;
1983 return;
1984 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001985#else
1986 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001987#endif
1988
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001989
1990 *OS << "JIT: Disassembled code: " << Name
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001991 << ((IsStub) ? " (stub)" : "") << "\n";
1992
1993 if(mpAsmInfo == NULL)
1994 mpAsmInfo = mpTarget->createAsmInfo(Triple);
1995 if(mpDisassmbler == NULL)
1996 mpDisassmbler = mpTarget->createMCDisassembler();
1997 if(mpIP == NULL)
1998 mpIP = mpTarget->createMCInstPrinter(
1999 mpAsmInfo->getAssemblerDialect(), *mpAsmInfo);
2000
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002001 const BufferMemoryObject* BufferMObj =
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002002 new BufferMemoryObject(Start, Length);
2003 uint64_t Size;
2004 uint64_t Index;
2005
2006 for(Index=0;Index<Length;Index+=Size) {
2007 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002008
2009 if(mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2010 /* REMOVED */ llvm::nulls()))
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002011 {
2012 OS->indent(4).write("0x", 2).
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002013 write_hex((uint32_t) Start + Index).write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002014 mpIP->printInst(&Inst, *OS);
2015 *OS << "\n";
2016 } else {
2017 if (Size == 0)
2018 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002019 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002020 }
2021
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002022 *OS << "\n";
2023 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002024
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002025#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002026 /* If you want the disassemble results write to file, uncomment this */
2027 OS->close();
2028 delete OS;
2029#endif
2030
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002031 return;
2032 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002033#else
2034 void Disassemble(const std::string& Name, uint8_t* Start,
2035 size_t Length, bool IsStub) {
2036 return;
2037 }
2038#endif /* defined(USE_DISASSEMBLER) */
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002039
2040 public:
2041 /* Will take the ownership of @MemMgr */
2042 CodeEmitter(CodeMemoryManager* pMemMgr) :
2043 mpMemMgr(pMemMgr),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002044 mpTarget(NULL),
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002045 mpTJI(NULL),
2046 mpTD(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002047#if defined(USE_DISASSEMBLER)
2048 mpAsmInfo(NULL),
2049 mpDisassmbler(NULL),
2050 mpIP(NULL),
2051#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002052 mpCurEmitFunction(NULL),
2053 mpConstantPool(NULL),
2054 mpJumpTable(NULL),
2055 mpMMI(NULL),
2056 mpSymbolLookupFn(NULL),
2057 mpSymbolLookupContext(NULL)
2058 {
2059 return;
2060 }
2061
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002062 inline global_addresses_const_iterator global_address_begin() const {
2063 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002064 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002065 inline global_addresses_const_iterator global_address_end() const {
2066 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002067 }
2068
2069 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid* pContext) {
2070 mpSymbolLookupFn = pFn;
2071 mpSymbolLookupContext = pContext;
2072 return;
2073 }
2074
2075 void setTargetMachine(llvm::TargetMachine& TM) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002076 /* set Target */
2077 mpTarget = &TM.getTarget();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002078 /* set TargetJITInfo */
2079 mpTJI = TM.getJITInfo();
2080 /* set TargetData */
2081 mpTD = TM.getTargetData();
2082
2083 /*
2084 if(mpTJI->needsGOT())
2085 mpMemMgr->AllocateGOT(); // however,
2086 // both X86 and ARM target don't need GOT
2087 // (mpTJI->needsGOT() always returns false)
2088 */
2089 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2090
2091 return;
2092 }
2093
2094 /*
2095 * startFunction - This callback is invoked when the specified function is
2096 * about to be code generated. This initializes the BufferBegin/End/Ptr
2097 * fields.
2098 */
2099 void startFunction(llvm::MachineFunction &F) {
2100 uintptr_t ActualSize = 0;
2101
2102 mpMemMgr->setMemoryWritable();
2103
2104 /*
2105 * BufferBegin, BufferEnd and CurBufferPtr
2106 * are all inherited from class MachineCodeEmitter,
2107 * which is the super class of the class JITCodeEmitter.
2108 *
2109 * BufferBegin/BufferEnd - Pointers to the start and end of the memory
2110 * allocated for this code buffer.
2111 *
2112 * CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2113 * code.
2114 * This is guranteed to be in the range [BufferBegin,BufferEnd]. If
2115 * this pointer is at BufferEnd, it will never move due to code emission,
2116 * and
2117 * all code emission requests will be ignored (this is
2118 * the buffer overflow condition).
2119 */
2120 BufferBegin = CurBufferPtr = mpMemMgr
2121 ->startFunctionBody(F.getFunction(), ActualSize);
2122 BufferEnd = BufferBegin + ActualSize;
2123
2124 if(mpCurEmitFunction == NULL)
2125 mpCurEmitFunction = new EmittedFunctionCode();
2126 mpCurEmitFunction->FunctionBody = BufferBegin;
2127
2128 /* Ensure the constant pool/jump table info is at least 4-byte aligned. */
2129 emitAlignment(16);
2130
2131 emitConstantPool(F.getConstantPool());
2132 if(llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
2133 initJumpTableInfo(MJTI);
2134
2135 /* About to start emitting the machine code for the function. */
2136 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2137
2138 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2139
2140 mpCurEmitFunction->Code = CurBufferPtr;
2141
2142 mMBBLocations.clear();
2143
2144 return;
2145 }
2146
2147 /*
2148 * finishFunction - This callback is invoked
2149 * when the specified function has
2150 * finished code generation.
2151 * If a buffer overflow has occurred, this method
2152 * returns true (the callee is required to try again), otherwise it returns
2153 * false.
2154 */
2155 bool finishFunction(llvm::MachineFunction &F) {
2156 if(CurBufferPtr == BufferEnd) {
2157 /* No enough memory */
2158 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2159 return false;
2160 }
2161
2162 if(llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
2163 emitJumpTableInfo(MJTI);
2164
2165 /*
2166 * FnStart is the start of the text,
2167 * not the start of the constant pool and other per-function data.
2168 */
2169 uint8_t* FnStart = (uint8_t*) GetPointerToGlobalIfAvailable
2170 (F.getFunction());
2171
2172 /* FnEnd is the end of the function's machine code. */
2173 uint8_t* FnEnd = CurBufferPtr;
2174
2175 if(!mRelocations.empty()) {
2176 /* Resolve the relocations to concrete pointers. */
2177 for(int i=0;i<mRelocations.size();i++) {
2178 llvm::MachineRelocation& MR = mRelocations[i];
2179 void* ResultPtr = NULL;
2180
2181 if(!MR.letTargetResolve()) {
2182 if(MR.isExternalSymbol()) {
2183 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
2184 if(MR.mayNeedFarStub())
2185 ResultPtr = GetExternalFunctionStub(ResultPtr);
2186 } else if(MR.isGlobalValue()) {
2187 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2188 BufferBegin
2189 + MR.getMachineCodeOffset(),
2190 MR.mayNeedFarStub());
2191 } else if(MR.isIndirectSymbol()) {
2192 ResultPtr = GetPointerToGVIndirectSym
2193 (MR.getGlobalValue(),
2194 BufferBegin + MR.getMachineCodeOffset()
2195 );
2196 } else if(MR.isBasicBlock()) {
2197 ResultPtr =
2198 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
2199 } else if(MR.isConstantPoolIndex()) {
2200 ResultPtr =
2201 (void*) getConstantPoolEntryAddress
2202 (MR.getConstantPoolIndex());
2203 } else {
2204 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2205 ResultPtr =
2206 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2207 }
2208
2209 MR.setResultPointer(ResultPtr);
2210 }
2211 }
2212
2213 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2214 mpMemMgr->getGOTBase());
2215 }
2216
2217 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2218 /*
2219 * CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2220 * global variables that were referenced in the relocations.
2221 */
2222 if(CurBufferPtr == BufferEnd)
2223 return false;
2224
2225 /* Now that we've succeeded in emitting the function */
2226 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2227 BufferBegin = CurBufferPtr = 0;
2228
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002229 if(F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002230 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2231 mpCurEmitFunction = NULL;
2232
2233 mRelocations.clear();
2234 mConstPoolAddresses.clear();
2235
2236 /* Mark code region readable and executable if it's not so already. */
2237 mpMemMgr->setMemoryExecutable();
2238
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002239 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002240
2241 if(mpMMI)
2242 mpMMI->EndFunction();
2243
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002244 updateFunctionStub(F.getFunction());
2245
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002246 return false;
2247 }
2248
2249 void startGVStub(const llvm::GlobalValue* GV, unsigned StubSize,
2250 unsigned Alignment) {
2251 mpSavedBufferBegin = BufferBegin;
2252 mpSavedBufferEnd = BufferEnd;
2253 mpSavedCurBufferPtr = CurBufferPtr;
2254
2255 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2256 Alignment);
2257 BufferEnd = BufferBegin + StubSize + 1;
2258
2259 return;
2260 }
2261
2262 void startGVStub(void* Buffer, unsigned StubSize) {
2263 mpSavedBufferBegin = BufferBegin;
2264 mpSavedBufferEnd = BufferEnd;
2265 mpSavedCurBufferPtr = CurBufferPtr;
2266
2267 BufferBegin = CurBufferPtr = (uint8_t *) Buffer;
2268 BufferEnd = BufferBegin + StubSize + 1;
2269
2270 return;
2271 }
2272
2273 void finishGVStub() {
2274 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2275
2276 /* restore */
2277 BufferBegin = mpSavedBufferBegin;
2278 BufferEnd = mpSavedBufferEnd;
2279 CurBufferPtr = mpSavedCurBufferPtr;
2280
2281 return;
2282 }
2283
2284 /*
2285 * allocIndirectGV - Allocates and fills storage for an indirect
2286 * GlobalValue, and returns the address.
2287 */
2288 void* allocIndirectGV(const llvm::GlobalValue *GV,
2289 const uint8_t *Buffer, size_t Size,
2290 unsigned Alignment) {
2291 uint8_t* IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
2292 memcpy(IndGV, Buffer, Size);
2293 return IndGV;
2294 }
2295
2296 /* emitLabel - Emits a label */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002297 void emitLabel(llvm::MCSymbol *Label) {
2298 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002299 return;
2300 }
2301
2302 /*
2303 * allocateGlobal - Allocate memory for a global. Unlike allocateSpace,
2304 * this method does not allocate memory in the current output buffer,
2305 * because a global may live longer than the current function.
2306 */
2307 void* allocateGlobal(uintptr_t Size, unsigned Alignment) {
2308 /* Delegate this call through the memory manager. */
2309 return mpMemMgr->allocateGlobal(Size, Alignment);
2310 }
2311
2312 /*
2313 * StartMachineBasicBlock - This should be called by the target when a new
2314 * basic block is about to be emitted. This way the MCE knows where the
2315 * start of the block is, and can implement getMachineBasicBlockAddress.
2316 */
2317 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
2318 if(mMBBLocations.size() <= (unsigned) MBB->getNumber())
2319 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2320 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2321 return;
2322 }
2323
2324 /*
2325 * addRelocation - Whenever a relocatable address is needed, it should be
2326 * noted with this interface.
2327 */
2328 void addRelocation(const llvm::MachineRelocation &MR) {
2329 mRelocations.push_back(MR);
2330 return;
2331 }
2332
2333 /*
2334 * getConstantPoolEntryAddress - Return the address of the 'Index' entry in
2335 * the constant pool that was last emitted with
2336 * the emitConstantPool method.
2337 */
2338 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2339 assert(Index < mpConstantPool->getConstants().size() &&
2340 "Invalid constant pool index!");
2341 return mConstPoolAddresses[Index];
2342 }
2343
2344 /*
2345 * getJumpTableEntryAddress - Return the address of the jump table
2346 * with index
2347 * 'Index' in the function that last called initJumpTableInfo.
2348 */
2349 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
2350 const std::vector<llvm::MachineJumpTableEntry>& JT =
2351 mpJumpTable->getJumpTables();
2352
2353 assert(Index < JT.size() && "Invalid jump table index!");
2354
2355 unsigned int Offset = 0;
2356 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2357
2358 for(int i=0;i<Index;i++)
2359 Offset += JT[i].MBBs.size();
2360 Offset *= EntrySize;
2361
2362 return (uintptr_t)((char *) mpJumpTableBase + Offset);
2363 }
2364
2365 /*
2366 * getMachineBasicBlockAddress - Return the address of the specified
2367 * MachineBasicBlock, only usable after the label for the MBB has been
2368 * emitted.
2369 */
2370 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2371 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
2372 mMBBLocations[MBB->getNumber()] && "MBB not emitted!");
2373 return mMBBLocations[MBB->getNumber()];
2374 }
2375
2376 /*
2377 * getLabelAddress - Return the address of the specified LabelID,
2378 * only usable after the LabelID has been emitted.
2379 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002380 uintptr_t getLabelAddress(llvm::MCSymbol* Label) const {
2381 assert(mLabelLocations.count(Label) && "Label not emitted!");
2382 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002383 }
2384
2385 /*
2386 * Specifies the MachineModuleInfo object.
2387 * This is used for exception handling
2388 * purposes.
2389 */
2390 void setModuleInfo(llvm::MachineModuleInfo* Info) {
2391 mpMMI = Info;
2392 return;
2393 }
2394
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002395 void updateFunctionStub(const llvm::Function* F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002396 /* Get the empty stub we generated earlier. */
2397 void* Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002398 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002399 if(I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002400 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002401 else
2402 return;
2403
2404 void* Addr = GetPointerToGlobalIfAvailable(F);
2405
2406 assert(Addr != Stub &&
2407 "Function must have non-stub address to be updated.");
2408
2409 /*
2410 * Tell the target jit info to rewrite the stub at the specified address,
2411 * rather than creating a new one.
2412 */
2413 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2414 startGVStub(Stub, SL.Size);
2415 mpTJI->emitFunctionStub(F, Addr, *this);
2416 finishGVStub();
2417
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002418 Disassemble(F->getName(), (uint8_t*) Stub, SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002419
2420 PendingFunctions.erase(I);
2421
2422 return;
2423 }
2424
2425 /*
2426 * Once you finish the compilation on a translation unit,
2427 * you can call this function to recycle the memory
2428 * (which is used at compilation time and not needed for runtime).
2429 *
2430 * NOTE: You should not call this funtion until the code-gen passes
2431 * for a given module is done.
2432 * Otherwise, the results is undefined and may cause the system crash!
2433 */
2434 void releaseUnnecessary() {
2435 mMBBLocations.clear();
2436 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002437 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002438 mFunctionToLazyStubMap.clear();
2439 GlobalToIndirectSymMap.clear();
2440 ExternalFnToStubMap.clear();
2441 PendingFunctions.clear();
2442
2443 return;
2444 }
2445
2446 void reset() {
2447 releaseUnnecessary();
2448
2449 mpSymbolLookupFn = NULL;
2450 mpSymbolLookupContext = NULL;
2451
2452 mpTJI = NULL;
2453 mpTD = NULL;
2454
2455 for(EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin();
2456 I != mEmittedFunctions.end();
2457 I++)
2458 if(I->second != NULL)
2459 delete I->second;
2460 mEmittedFunctions.clear();
2461
2462 mpMemMgr->reset();
2463
2464 return;
2465 }
2466
2467 void* lookup(const char* Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002468 return lookup( llvm::StringRef(Name) );
2469 }
2470
2471 void* lookup(const llvm::StringRef& Name) {
2472 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(Name.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002473 if(I == mEmittedFunctions.end())
2474 return NULL;
2475 else
2476 return I->second->Code;
2477 }
2478
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002479 void getFunctionNames(BCCsizei* actualFunctionCount,
2480 BCCsizei maxFunctionCount,
2481 BCCchar** functions) {
2482 int functionCount = mEmittedFunctions.size();
2483
2484 if(actualFunctionCount)
2485 *actualFunctionCount = functionCount;
2486 if(functionCount > maxFunctionCount)
2487 functionCount = maxFunctionCount;
2488 if(functions)
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002489 for(EmittedFunctionsMapTy::const_iterator it =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002490 mEmittedFunctions.begin();
2491 functionCount > 0;
2492 functionCount--, it++)
2493 *functions++ = (BCCchar*) it->first.c_str();
2494
2495 return;
2496 }
2497
2498 void getFunctionBinary(BCCchar* label,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002499 BCCvoid** base,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002500 BCCsizei* length) {
2501 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002502 if(I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002503 *base = NULL;
2504 *length = 0;
2505 } else {
2506 *base = I->second->Code;
2507 *length = I->second->Size;
2508 }
2509 return;
2510 }
2511
2512 ~CodeEmitter() {
2513 if(mpMemMgr)
2514 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002515#if defined(USE_DISASSEMBLER)
2516 if(mpAsmInfo)
2517 delete mpAsmInfo;
2518 if(mpDisassmbler)
2519 delete mpDisassmbler;
2520 if(mpIP)
2521 delete mpIP;
2522#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002523 return;
2524 }
2525 /* }}} */
2526 }; /* End of Class CodeEmitter */
2527
2528 /* The CodeEmitter */
2529 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
2530 CodeEmitter* createCodeEmitter() {
2531 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2532 return mCodeEmitter.get();
2533 }
2534
2535 BCCSymbolLookupFn mpSymbolLookupFn;
2536 void* mpSymbolLookupContext;
2537
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002538 llvm::LLVMContext* mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002539 llvm::Module* mModule;
2540
2541 bool mTypeInformationPrepared;
2542 std::vector<const llvm::Type*> mTypes;
2543
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002544 public:
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002545 Compiler() :
2546 mpSymbolLookupFn(NULL),
2547 mpSymbolLookupContext(NULL),
2548 mContext(NULL),
2549 mModule(NULL)
2550 {
Shih-wei Liao5bde66c2010-05-07 02:23:29 -07002551 llvm::remove_fatal_error_handler();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002552 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002553 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002554 return;
2555 }
2556
2557 /* interface for BCCscript::registerSymbolCallback() */
2558 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid* pContext) {
2559 mpSymbolLookupFn = pFn;
2560 mpSymbolLookupContext = pContext;
2561 return;
2562 }
2563
2564 int loadModule(const char* bitcode, size_t bitcodeSize) {
2565 llvm::MemoryBuffer* SB = NULL;
2566
2567 if(bitcode == NULL || bitcodeSize <= 0)
2568 return 0;
2569
2570 GlobalInitialization();
2571
2572 /* Package input to object MemoryBuffer */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002573 SB = llvm::MemoryBuffer::getMemBuffer(
2574 llvm::StringRef(bitcode, bitcodeSize));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002575 if(SB == NULL) {
2576 setError("Error reading input Bitcode into memory");
2577 goto on_bcc_load_module_error;
2578 }
2579
2580 /* Read the input Bitcode as a Module */
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002581 mModule = llvm::ParseBitcodeFile(SB, *mContext, &mError);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002582
2583on_bcc_load_module_error:
2584 if (SB)
2585 delete SB;
2586
2587 return hasError();
2588 }
2589
2590 /* interace for bccCompileScript() */
2591 int compile() {
2592 llvm::TargetData* TD = NULL;
2593
2594 llvm::TargetMachine* TM = NULL;
2595 const llvm::Target* Target;
2596 std::string FeaturesStr;
2597
2598 llvm::FunctionPassManager* CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002599
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002600 const llvm::NamedMDNode* PragmaMetadata;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002601 const llvm::NamedMDNode* ExportVarMetadata;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002602 const llvm::NamedMDNode* ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002603
2604 if(mModule == NULL) /* No module was loaded */
2605 return 0;
2606
2607 /* Create TargetMachine */
2608 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2609 if(hasError())
2610 goto on_bcc_compile_error;
2611
2612 if(!CPU.empty() || !Features.empty()) {
2613 llvm::SubtargetFeatures F;
2614 F.setCPU(CPU);
2615 for(std::vector<std::string>::const_iterator it = Features.begin();
2616 it != Features.end();
2617 it++)
2618 F.AddFeature(*it);
2619 FeaturesStr = F.getString();
2620 }
2621
2622 TM = Target->createTargetMachine(Triple, FeaturesStr);
2623 if(TM == NULL) {
2624 setError("Failed to create target machine implementation for the"
2625 " specified triple '" + Triple + "'");
2626 goto on_bcc_compile_error;
2627 }
2628
2629 /* Create memory manager for creation of code emitter later */
2630 if(!mCodeMemMgr.get() && !createCodeMemoryManager()) {
2631 setError("Failed to startup memory management for further compilation");
2632 goto on_bcc_compile_error;
2633 }
2634
2635 /* Create code emitter */
2636 if(!mCodeEmitter.get()) {
2637 if(!createCodeEmitter()) {
2638 setError("Failed to create machine code emitter to complete"
2639 " the compilation");
2640 goto on_bcc_compile_error;
2641 }
2642 } else {
2643 /* reuse the code emitter */
2644 mCodeEmitter->reset();
2645 }
2646
2647 mCodeEmitter->setTargetMachine(*TM);
2648 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2649 mpSymbolLookupContext);
2650
2651 /* Get target data from Module */
2652 TD = new llvm::TargetData(mModule);
2653 /* Create code-gen pass to run the code emitter */
2654 CodeGenPasses = new llvm::FunctionPassManager(mModule);
2655 CodeGenPasses->add(TD); // Will take the ownership of TD
2656
2657 if(TM->addPassesToEmitMachineCode(*CodeGenPasses,
2658 *mCodeEmitter, CodeGenOptLevel)) {
2659 setError("The machine code emission is not supported by BCC on target '"
2660 + Triple + "'");
2661 goto on_bcc_compile_error;
2662 }
2663
2664 /*
2665 * Run the pass (the code emitter) on every non-declaration function
2666 * in the module
2667 */
2668 CodeGenPasses->doInitialization();
2669 for(llvm::Module::iterator I = mModule->begin();
2670 I != mModule->end();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002671 I++)
2672 if(!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002673 CodeGenPasses->run(*I);
2674
2675 CodeGenPasses->doFinalization();
2676
2677 /* Copy the global address mapping from code emitter and remapping */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002678 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2679 if(ExportVarMetadata) {
2680 for(int i=0;i<ExportVarMetadata->getNumOperands();i++) {
2681 llvm::MDNode* ExportVar = ExportVarMetadata->getOperand(i);
2682 if(ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2683 llvm::Value* ExportVarNameMDS = ExportVar->getOperand(0);
2684 if(ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2685 llvm::StringRef ExportVarName =
2686 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2687 CodeEmitter::global_addresses_const_iterator I;
2688 for(I = mCodeEmitter->global_address_begin();
2689 I != mCodeEmitter->global_address_end();
2690 I++)
2691 {
2692 if(I->first->getValueID() != llvm::Value::GlobalVariableVal)
2693 continue;
2694 if(ExportVarName == I->first->getName()) {
2695 mExportVars.push_back(I->second);
2696 break;
2697 }
2698 }
2699 if(I != mCodeEmitter->global_address_end())
2700 continue; // found
2701 }
2702 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002703 // if here, the global variable record in metadata is not
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002704 // found, make an empty slot
2705 mExportVars.push_back(NULL);
2706 }
2707 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
2708 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002709 }
2710
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002711 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2712 if(ExportFuncMetadata) {
2713 for(int i=0;i<ExportFuncMetadata->getNumOperands();i++) {
2714 llvm::MDNode* ExportFunc = ExportFuncMetadata->getOperand(i);
2715 if(ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2716 llvm::Value* ExportFuncNameMDS = ExportFunc->getOperand(0);
2717 if(ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2718 llvm::StringRef ExportFuncName =
2719 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2720 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
2721 }
2722 }
2723 }
2724 }
2725
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002726 /*
2727 * Tell code emitter now can release the memory using
2728 * during the JIT since we have done the code emission
2729 */
2730 mCodeEmitter->releaseUnnecessary();
2731
2732 /*
2733 * Finally, read pragma information from the metadata node
2734 * of the @Module if any
2735 */
2736 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2737 if(PragmaMetadata)
2738 for(int i=0;i<PragmaMetadata->getNumOperands();i++) {
2739 llvm::MDNode* Pragma = PragmaMetadata->getOperand(i);
2740 if(Pragma != NULL &&
2741 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
2742 llvm::Value* PragmaNameMDS = Pragma->getOperand(0);
2743 llvm::Value* PragmaValueMDS = Pragma->getOperand(1);
2744
2745 if((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
2746 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
2747 llvm::StringRef PragmaName =
2748 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
2749 llvm::StringRef PragmaValue =
2750 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
2751
2752 mPragmas.push_back( make_pair( std::string(PragmaName.data(),
2753 PragmaName.size()),
2754 std::string(PragmaValue.data(),
2755 PragmaValue.size())
2756 )
2757 );
2758 }
2759 }
2760 }
2761
2762 on_bcc_compile_error:
2763 if (CodeGenPasses) {
2764 delete CodeGenPasses;
2765 } else if (TD) {
2766 delete TD;
2767 }
2768 if (TM)
2769 delete TM;
2770
2771 return hasError();
2772 }
2773
2774 /* interface for bccGetScriptInfoLog() */
2775 char* getErrorMessage() {
2776 return const_cast<char*>(mError.c_str());
2777 }
2778
2779 /* interface for bccGetScriptLabel() */
2780 void* lookup(const char* name) {
2781 void* addr = NULL;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002782 if(mCodeEmitter.get())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002783 /* Find function pointer */
2784 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002785 return addr;
2786 }
2787
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002788 /* Interface for bccGetExportVars() */
2789 void getExportVars(BCCsizei* actualVarCount,
2790 BCCsizei maxVarCount,
2791 BCCvoid** vars) {
2792 int varCount = mExportVars.size();
2793
2794 if(actualVarCount)
2795 *actualVarCount = varCount;
2796 if(varCount > maxVarCount)
2797 varCount = maxVarCount;
2798 if(vars)
2799 for(ExportVarList::const_iterator it = mExportVars.begin();
2800 it != mExportVars.end();
2801 it++)
2802 {
2803 *vars++ = *it;
2804 }
2805
2806 return;
2807 }
2808
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002809 /* Interface for bccGetExportFuncs() */
2810 void getExportFuncs(BCCsizei* actualFuncCount,
2811 BCCsizei maxFuncCount,
2812 BCCvoid** funcs) {
2813 int funcCount = mExportFuncs.size();
2814
2815 if(actualFuncCount)
2816 *actualFuncCount = funcCount;
2817 if(funcCount > maxFuncCount)
2818 funcCount = maxFuncCount;
2819 if(funcs)
2820 for(ExportFuncList::const_iterator it = mExportFuncs.begin();
2821 it != mExportFuncs.end();
2822 it++)
2823 {
2824 *funcs++ = *it;
2825 }
2826
2827 return;
2828 }
2829
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002830 /* Interface for bccGetPragmas() */
2831 void getPragmas(BCCsizei* actualStringCount,
2832 BCCsizei maxStringCount,
2833 BCCchar** strings) {
2834 int stringCount = mPragmas.size() * 2;
2835
2836 if(actualStringCount)
2837 *actualStringCount = stringCount;
2838 if(stringCount > maxStringCount)
2839 stringCount = maxStringCount;
2840 if(strings)
2841 for(PragmaList::const_iterator it = mPragmas.begin();
2842 stringCount > 0;
2843 stringCount-=2, it++)
2844 {
2845 *strings++ = (BCCchar*) it->first.c_str();
2846 *strings++ = (BCCchar*) it->second.c_str();
2847 }
2848
2849 return;
2850 }
2851
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002852 /* Interface for bccGetFunctions() */
2853 void getFunctions(BCCsizei* actualFunctionCount,
2854 BCCsizei maxFunctionCount,
2855 BCCchar** functions) {
2856 if(mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002857 mCodeEmitter->getFunctionNames(actualFunctionCount,
2858 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002859 functions);
2860 else
2861 *actualFunctionCount = 0;
2862
2863 return;
2864 }
2865
2866 /* Interface for bccGetFunctionBinary() */
2867 void getFunctionBinary(BCCchar* function,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002868 BCCvoid** base,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002869 BCCsizei* length) {
2870 if(mCodeEmitter.get()) {
2871 mCodeEmitter->getFunctionBinary(function, base, length);
2872 } else {
2873 *base = NULL;
2874 *length = 0;
2875 }
2876 return;
2877 }
2878
2879 inline const llvm::Module* getModule() const {
2880 return mModule;
2881 }
2882
2883 inline const std::vector<const llvm::Type*>& getTypes() const {
2884 return mTypes;
2885 }
2886
2887 ~Compiler() {
2888 delete mModule;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002889 llvm::llvm_shutdown();
2890 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002891 return;
2892 }
2893}; /* End of Class Compiler */
2894
2895bool Compiler::GlobalInitialized = false;
2896
2897/* Code generation optimization level for the compiler */
2898llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
2899
2900std::string Compiler::Triple;
2901
2902std::string Compiler::CPU;
2903
2904std::vector<std::string> Compiler::Features;
2905
2906/*
2907 * The named of metadata node that pragma resides
2908 * (should be synced with slang.cpp)
2909 */
2910const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
2911
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002912/*
2913 * The named of metadata node that export variable name resides
2914 * (should be synced with slang.cpp)
2915 */
2916const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
2917
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002918/*
2919 * The named of metadata node that export function name resides
2920 * (should be synced with slang.cpp)
2921 */
2922const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
2923
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002924struct BCCscript {
2925 /*
2926 * Part I. Compiler
2927 */
2928
2929 Compiler compiler;
2930
2931 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid* pContext) {
2932 compiler.registerSymbolCallback(pFn, pContext);
2933 }
2934
2935 /*
2936 * Part II. Logistics & Error handling
2937 */
2938
2939 BCCscript() {
2940 bccError = BCC_NO_ERROR;
2941 }
2942
2943 ~BCCscript() {
2944 }
2945
2946 void setError(BCCenum error) {
2947 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
2948 bccError = error;
2949 }
2950 }
2951
2952 BCCenum getError() {
2953 BCCenum result = bccError;
2954 bccError = BCC_NO_ERROR;
2955 return result;
2956 }
2957
2958 BCCenum bccError;
2959};
2960
2961
2962extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002963BCCscript* bccCreateScript()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002964{
2965 return new BCCscript();
2966}
2967
2968extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002969BCCenum bccGetError( BCCscript* script )
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002970{
2971 return script->getError();
2972}
2973
2974extern "C"
2975void bccDeleteScript(BCCscript* script) {
2976 delete script;
2977}
2978
2979extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002980void bccRegisterSymbolCallback(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002981 BCCSymbolLookupFn pFn,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002982 BCCvoid* pContext)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002983{
2984 script->registerSymbolCallback(pFn, pContext);
2985}
2986
2987extern "C"
2988void bccScriptBitcode(BCCscript* script,
2989 const BCCchar* bitcode,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002990 BCCint size)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002991{
2992 script->compiler.loadModule(bitcode, size);
2993}
2994
2995extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002996void bccCompileScript(BCCscript* script)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002997{
2998 int result = script->compiler.compile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002999 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003000 script->setError(BCC_INVALID_OPERATION);
3001}
3002
3003extern "C"
3004void bccGetScriptInfoLog(BCCscript* script,
3005 BCCsizei maxLength,
3006 BCCsizei* length,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003007 BCCchar* infoLog)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003008{
3009 char* message = script->compiler.getErrorMessage();
3010 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003011 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003012 *length = messageLength;
3013
3014 if (infoLog && maxLength > 0) {
3015 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
3016 memcpy(infoLog, message, trimmedLength);
3017 infoLog[trimmedLength] = 0;
3018 }
3019}
3020
3021extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003022void bccGetScriptLabel(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003023 const BCCchar * name,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003024 BCCvoid ** address)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003025{
3026 void* value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003027 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003028 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003029 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003030 script->setError(BCC_INVALID_VALUE);
3031}
3032
3033extern "C"
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003034void bccGetExportVars(BCCscript* script,
3035 BCCsizei* actualVarCount,
3036 BCCsizei maxVarCount,
3037 BCCvoid** vars)
3038{
3039 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
3040}
3041
3042extern "C"
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003043void bccGetExportFuncs(BCCscript* script,
3044 BCCsizei* actualFuncCount,
3045 BCCsizei maxFuncCount,
3046 BCCvoid** funcs)
3047{
3048 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
3049}
3050
3051extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003052void bccGetPragmas(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003053 BCCsizei* actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003054 BCCsizei maxStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003055 BCCchar** strings)
3056{
3057 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
3058}
3059
3060extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003061void bccGetFunctions(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003062 BCCsizei* actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003063 BCCsizei maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003064 BCCchar** functions)
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003065{
3066 script->compiler.getFunctions(actualFunctionCount,
3067 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003068 functions);
3069}
3070
3071extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003072void bccGetFunctionBinary(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003073 BCCchar* function,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003074 BCCvoid** base,
3075 BCCsizei* length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003076{
3077 script->compiler.getFunctionBinary(function, base, length);
3078}
3079
3080struct BCCtype {
3081 const Compiler* compiler;
3082 const llvm::Type* t;
3083};
3084
3085} /* End of namespace bcc */