blob: c092f86a03fd65a816eee5a0ea6ff8417e41e907 [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;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700274
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700275 // if (!llvm::llvm_is_multithreaded())
276 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700277
278 /* Set Triple, CPU and Features here */
279 Triple = TARGET_TRIPLE_STRING;
280
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700281 /* TODO: NEON for JIT */
282 //Features.push_back("+neon");
283 //Features.push_back("+vmlx");
284 //Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700285 Features.push_back("+vfp3");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700286
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700287#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
288 LLVMInitializeARMTargetInfo();
289 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700290#if defined(USE_DISASSEMBLER)
291 LLVMInitializeARMDisassembler();
292 LLVMInitializeARMAsmPrinter();
293#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700294#endif
295
296#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
297 LLVMInitializeX86TargetInfo();
298 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700299#if defined(USE_DISASSEMBLER)
300 LLVMInitializeX86Disassembler();
301 LLVMInitializeX86AsmPrinter();
302#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700303#endif
304
305#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
306 LLVMInitializeX86TargetInfo();
307 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700308#if defined(USE_DISASSEMBLER)
309 LLVMInitializeX86Disassembler();
310 LLVMInitializeX86AsmPrinter();
311#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700312#endif
313
314 /*
315 * -O0: llvm::CodeGenOpt::None
316 * -O1: llvm::CodeGenOpt::Less
317 * -O2: llvm::CodeGenOpt::Default
318 * -O3: llvm::CodeGenOpt::Aggressive
319 */
320 CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
321
322 /* Below are the global settings to LLVM */
323
324 /* Disable frame pointer elimination optimization */
325 llvm::NoFramePointerElim = false;
326
327 /*
328 * Use hardfloat ABI
329 *
330 * FIXME: Need to detect the CPU capability and decide whether to use
331 * softfp. To use softfp, change following 2 lines to
332 *
333 * llvm::FloatABIType = llvm::FloatABI::Soft;
334 * llvm::UseSoftFloat = true;
335 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700336 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700337 llvm::UseSoftFloat = false;
338
339 /*
340 * BCC needs all unknown symbols resolved at JIT/compilation time.
341 * So we don't need any dynamic relocation model.
342 */
343 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
344
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700345#if defined(DEFAULT_X64_CODEGEN)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700346 /* Data address in X86_64 architecture may reside in a far-away place */
347 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
348#else
349 /*
350 * This is set for the linker (specify how large of the virtual addresses
351 * we can access for all unknown symbols.)
352 */
353 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
354#endif
355
356 /* Register the scheduler */
357 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
358
359 /*
360 * Register allocation policy:
361 * createLocalRegisterAllocator: fast but bad quality
362 * createLinearScanRegisterAllocator: not so fast but good quality
363 */
364 llvm::RegisterRegAlloc::setDefault
365 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
366 llvm::createLocalRegisterAllocator :
367 llvm::createLinearScanRegisterAllocator);
368
369 GlobalInitialized = true;
370 return;
371 }
372
373 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
374 // std::string* Error = static_cast<std::string*>(UserData);
375 // Error->assign(Message);
376 // return;
377 fprintf(stderr, "%s\n", Message.c_str());
378 exit(1);
379 }
380
381 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700382 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700383 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700384
385 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700386 std::string mError;
387
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700388 inline bool hasError() const {
389 return !mError.empty();
390 }
391 inline void setError(const char* Error) {
392 mError.assign(Error); // Copying
393 return;
394 }
395 inline void setError(const std::string& Error) {
396 mError = Error;
397 return;
398 }
399
400 typedef std::list< std::pair<std::string, std::string> > PragmaList;
401 PragmaList mPragmas;
402
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700403 typedef std::list<void*> ExportVarList;
404 ExportVarList mExportVars;
405
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700406 typedef std::list<void*> ExportFuncList;
407 ExportFuncList mExportFuncs;
408
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700409 /* Memory manager for the code reside in memory */
410 /*
411 * The memory for our code emitter is very simple and is conforming to the
412 * design decisions of Android RenderScript's Exection Environment:
413 * The code, data, and symbol sizes are limited (currently 100KB.)
414 *
415 * It's very different from typical compiler, which has no limitation
416 * on the code size. How does code emitter know the size of the code
417 * it is about to emit? It does not know beforehand. We want to solve
418 * this without complicating the code emitter too much.
419 *
420 * We solve this by pre-allocating a certain amount of memory,
421 * and then start the code emission. Once the buffer overflows, the emitter
422 * simply discards all the subsequent emission but still has a counter
423 * on how many bytes have been emitted.
424
425 * So once the whole emission is done, if there's a buffer overflow,
426 * it re-allocates the buffer with enough size (based on the
427 * counter from previous emission) and re-emit again.
428 */
429 class CodeMemoryManager : public llvm::JITMemoryManager {
430 /* {{{ */
431 private:
432 static const unsigned int MaxCodeSize = 100 * 1024; /* 100 KiB for code */
433 static const unsigned int MaxGOTSize = 1 * 1024; /* 1 KiB for global
434 offset table (GOT) */
435
436 /*
437 * Our memory layout is as follows:
438 *
439 * The direction of arrows (-> and <-) shows memory's growth direction
440 * when more space is needed.
441 *
442 * @mpCodeMem:
443 * +--------------------------------------------------------------+
444 * | Function Memory ... -> <- ... Global/Stub/GOT |
445 * +--------------------------------------------------------------+
446 * |<------------------ Total: @MaxCodeSize KiB ----------------->|
447 *
448 * Where size of GOT is @MaxGOTSize KiB.
449 *
450 * @mCurFuncMemIdx: The current index (starting from 0) of the last byte
451 * of function code's memoey usage
452 * @mCurGSGMemIdx: The current index (starting from 0) of the last byte
453 * of Global Stub/GOT's memory usage
454 *
455 */
456
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700457 uintptr_t mCurFuncMemIdx;
458 uintptr_t mCurGSGMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700459 llvm::sys::MemoryBlock* mpCodeMem;
460
461 /* GOT Base */
462 uint8_t* mpGOTBase;
463
464 typedef std::map<const llvm::Function*, pair<void* /* start address */,
465 void* /* end address */>
466 > FunctionMapTy;
467 FunctionMapTy mFunctionMap;
468
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700469 inline uintptr_t getFreeMemSize() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700470 return mCurGSGMemIdx - mCurFuncMemIdx;
471 }
472 inline uint8_t* getCodeMemBase() const {
473 return static_cast<uint8_t*>(mpCodeMem->base());
474 }
475
476 uint8_t* allocateGSGMemory(uintptr_t Size,
477 unsigned Alignment = 1 /* no alignment */)
478 {
479 if(getFreeMemSize() < Size)
480 /* The code size excesses our limit */
481 return NULL;
482
483 if(Alignment == 0)
484 Alignment = 1;
485
486 uint8_t* result = getCodeMemBase() + mCurGSGMemIdx - Size;
487 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
488
489 mCurGSGMemIdx = result - getCodeMemBase();
490
491 return result;
492 }
493
494 public:
495 CodeMemoryManager() : mpCodeMem(NULL), mpGOTBase(NULL) {
496 reset();
497 std::string ErrMsg;
498 llvm::sys::MemoryBlock B = llvm::sys::Memory::
499 AllocateRWX(MaxCodeSize, NULL, &ErrMsg);
500 if(B.base() == 0)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700501 llvm::report_fatal_error(
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700502 "Failed to allocate Memory for code emitter\n" + ErrMsg
503 );
504 mpCodeMem = new llvm::sys::MemoryBlock(B.base(), B.size());
505
506 return;
507 }
508
509 /*
510 * setMemoryWritable - When code generation is in progress,
511 * the code pages may need permissions changed.
512 */
513 void setMemoryWritable() {
514 llvm::sys::Memory::setWritable(*mpCodeMem);
515 return;
516 }
517
518 /*
519 * setMemoryExecutable - When code generation is done and we're ready to
520 * start execution, the code pages may need permissions changed.
521 */
522 void setMemoryExecutable() {
523 llvm::sys::Memory::setExecutable(*mpCodeMem);
524 return;
525 }
526
527 /*
528 * setPoisonMemory - Setting this flag to true makes the memory manager
529 * garbage values over freed memory. This is useful for testing and
530 * debugging, and is to be turned on by default in debug mode.
531 */
532 void setPoisonMemory(bool poison) {
533 /* no effect */
534 return;
535 }
536
537 /* Global Offset Table Management */
538
539 /*
540 * AllocateGOT - If the current table requires a Global Offset Table, this
541 * method is invoked to allocate it. This method is required to set HasGOT
542 * to true.
543 */
544 void AllocateGOT() {
545 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
546 mpGOTBase = allocateGSGMemory(MaxGOTSize);
547 HasGOT = true;
548 return;
549 }
550
551 /*
552 * getGOTBase - If this is managing a Global Offset Table, this method
553 * should return a pointer to its base.
554 */
555 uint8_t* getGOTBase() const {
556 return mpGOTBase;
557 }
558
559 /* Main Allocation Functions */
560
561 /*
562 * startFunctionBody - When we start JITing a function, the JIT calls this
563 * method to allocate a block of free RWX memory, which returns a pointer to
564 * it. If the JIT wants to request a block of memory of at least a certain
565 * size, it passes that value as ActualSize, and this method returns a block
566 * with at least that much space. If the JIT doesn't know ahead of time how
567 * much space it will need to emit the function, it passes 0 for the
568 * ActualSize. In either case, this method is required to pass back the size
569 * of the allocated block through ActualSize. The JIT will be careful to
570 * not write more than the returned ActualSize bytes of memory.
571 */
572 uint8_t* startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
573 if(getFreeMemSize() < ActualSize)
574 /* The code size excesses our limit */
575 return NULL;
576
577 ActualSize = getFreeMemSize();
578 return (getCodeMemBase() + mCurFuncMemIdx);
579 }
580
581 /*
582 * allocateStub - This method is called by the JIT to allocate space for a
583 * function stub (used to handle limited branch displacements) while it is
584 * JIT compiling a function. For example, if foo calls bar, and if bar
585 * either needs to be lazily compiled or is a native function that exists
586 * too
587 * far away from the call site to work, this method will be used to make a
588 * thunk for it. The stub should be "close" to the current function body,
589 * but should not be included in the 'actualsize' returned by
590 * startFunctionBody.
591 */
592 uint8_t* allocateStub(const llvm::GlobalValue* F, unsigned StubSize,
593 unsigned Alignment) {
594 return allocateGSGMemory(StubSize, Alignment);
595 }
596
597 /*
598 * endFunctionBody - This method is called when the JIT is done codegen'ing
599 * the specified function. At this point we know the size of the JIT
600 * compiled function. This passes in FunctionStart (which was returned by
601 * the startFunctionBody method) and FunctionEnd which is a pointer to the
602 * actual end of the function. This method should mark the space allocated
603 * and remember where it is in case the client wants to deallocate it.
604 */
605 void endFunctionBody(const llvm::Function* F, uint8_t* FunctionStart,
606 uint8_t* FunctionEnd) {
607 assert(FunctionEnd > FunctionStart);
608 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
609 "Mismatched function start/end!");
610
611 /* Advance the pointer */
612 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
613 assert(FunctionCodeSize <= getFreeMemSize() &&
614 "Code size excess the limitation!");
615 mCurFuncMemIdx += FunctionCodeSize;
616
617 /* Record there's a function in our memory start from @FunctionStart */
618 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
619 "Function already emitted!");
620 mFunctionMap.insert( make_pair<const llvm::Function*, pair<void*, void*>
621 >(F, make_pair(FunctionStart, FunctionEnd))
622 );
623
624 return;
625 }
626
627 /*
628 * allocateSpace - Allocate a (function code) memory block of the
629 * given size. This method cannot be called between
630 * calls to startFunctionBody and endFunctionBody.
631 */
632 uint8_t* allocateSpace(intptr_t Size, unsigned Alignment) {
633 if(getFreeMemSize() < Size)
634 /* The code size excesses our limit */
635 return NULL;
636
637 if(Alignment == 0)
638 Alignment = 1;
639
640 uint8_t* result = getCodeMemBase() + mCurFuncMemIdx;
641 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
642 ~(intptr_t) (Alignment - 1)
643 );
644
645 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
646
647 return result;
648 }
649
650 /* allocateGlobal - Allocate memory for a global. */
651 uint8_t* allocateGlobal(uintptr_t Size, unsigned Alignment) {
652 return allocateGSGMemory(Size, Alignment);
653 }
654
655 /*
656 * deallocateFunctionBody - Free the specified function body. The argument
657 * must be the return value from a call to startFunctionBody() that hasn't
658 * been deallocated yet. This is never called when the JIT is currently
659 * emitting a function.
660 */
661 void deallocateFunctionBody(void *Body) {
662 /* linear search */
663 FunctionMapTy::iterator I;
664 for(I = mFunctionMap.begin();
665 I != mFunctionMap.end();
666 I++)
667 if(I->second.first == Body)
668 break;
669
670 assert(I != mFunctionMap.end() && "Memory is never allocated!");
671
672 /* free the memory */
673 uint8_t* FunctionStart = (uint8_t*) I->second.first;
674 uint8_t* FunctionEnd = (uint8_t*) I->second.second;
675 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
676
677 assert(SizeNeedMove >= 0 &&
678 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
679 " be correctly calculated!");
680
681 if(SizeNeedMove > 0)
682 /* there's data behind deallocating function */
683 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
684 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
685
686 return;
687 }
688
689 /*
690 * startExceptionTable - When we finished JITing the function, if exception
691 * handling is set, we emit the exception table.
692 */
693 uint8_t* startExceptionTable(const llvm::Function* F, uintptr_t &ActualSize)
694 {
695 assert(false && "Exception is not allowed in our language specification");
696 return NULL;
697 }
698
699 /*
700 * endExceptionTable - This method is called when the JIT is done emitting
701 * the exception table.
702 */
703 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
704 uint8_t *TableEnd, uint8_t* FrameRegister) {
705 assert(false && "Exception is not allowed in our language specification");
706 return;
707 }
708
709 /*
710 * deallocateExceptionTable - Free the specified exception table's memory.
711 * The argument must be the return value from a call to
712 * startExceptionTable()
713 * that hasn't been deallocated yet. This is never called when the JIT is
714 * currently emitting an exception table.
715 */
716 void deallocateExceptionTable(void *ET) {
717 assert(false && "Exception is not allowed in our language specification");
718 return;
719 }
720
721 /* Below are the methods we create */
722 void reset() {
723 mpGOTBase = NULL;
724 HasGOT = false;
725
726 mCurFuncMemIdx = 0;
727 mCurGSGMemIdx = MaxCodeSize - 1;
728
729 mFunctionMap.clear();
730
731 return;
732 }
733
734 ~CodeMemoryManager() {
735 if(mpCodeMem != NULL)
736 llvm::sys::Memory::ReleaseRWX(*mpCodeMem);
737 return;
738 }
739 /* }}} */
740 }; /* End of class CodeMemoryManager */
741
742 /* The memory manager for code emitter */
743 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
744 CodeMemoryManager* createCodeMemoryManager() {
745 mCodeMemMgr.reset(new CodeMemoryManager());
746 return mCodeMemMgr.get();
747 }
748
749 /* Code emitter */
750 class CodeEmitter : public llvm::JITCodeEmitter {
751 /* {{{ */
752 public:
753 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
754 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
755
756 private:
757 CodeMemoryManager* mpMemMgr;
758
759 /* The JITInfo for the target we are compiling to */
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700760 const llvm::Target* mpTarget;
761
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700762 llvm::TargetJITInfo* mpTJI;
763
764 const llvm::TargetData* mpTD;
765
766 /*
767 * MBBLocations - This vector is a mapping from MBB ID's to their address.
768 * It is filled in by the StartMachineBasicBlock callback and queried by
769 * the getMachineBasicBlockAddress callback.
770 */
771 std::vector<uintptr_t> mMBBLocations;
772
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700773 /* mpConstantPool - The constant pool for the current function. */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700774 llvm::MachineConstantPool* mpConstantPool;
775
776 /* ConstantPoolBase - A pointer to the first entry in the constant pool. */
777 void *mpConstantPoolBase;
778
779 /* ConstPoolAddresses - Addresses of individual constant pool entries. */
780 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
781
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700782 /* mpJumpTable - The jump tables for the current function. */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700783 llvm::MachineJumpTableInfo *mpJumpTable;
784
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700785 /* mpJumpTableBase - A pointer to the first entry in the jump table. */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700786 void *mpJumpTableBase;
787
788 /*
789 * When outputting a function stub in the context of some other function, we
790 * save BufferBegin/BufferEnd/CurBufferPtr here.
791 */
792 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
793
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700794 /* mRelocations - These are the relocations that the function needs,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700795 as emitted. */
796 std::vector<llvm::MachineRelocation> mRelocations;
797
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700798 /* mLabelLocations - This vector is a mapping from Label ID's to their
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700799 address. */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700800 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700801
802 class EmittedFunctionCode {
803 public:
804 void* FunctionBody; // Beginning of the function's allocation.
805 void* Code; // The address the function's code actually starts at.
806 int Size; // The size of the function code
807
808 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
809 };
810 EmittedFunctionCode* mpCurEmitFunction;
811
812 typedef std::map<const std::string, EmittedFunctionCode*
813 > EmittedFunctionsMapTy;
814 EmittedFunctionsMapTy mEmittedFunctions;
815
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700816 /* mpMMI - Machine module info for exception informations */
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700817 llvm::MachineModuleInfo* mpMMI;
818
819 GlobalAddressMapTy mGlobalAddressMap;
820
821 /*
822 * UpdateGlobalMapping - Replace an existing mapping for GV with a new
823 * address. This updates both maps as required. If "Addr" is null, the
824 * entry for the global is removed from the mappings.
825 */
826 void* UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
827 if(Addr == NULL) {
828 /* Removing mapping */
829 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
830 void *OldVal;
831
832 if(I == mGlobalAddressMap.end())
833 OldVal = NULL;
834 else {
835 OldVal = I->second;
836 mGlobalAddressMap.erase(I);
837 }
838
839 return OldVal;
840 }
841
842 void*& CurVal = mGlobalAddressMap[GV];
843 void* OldVal = CurVal;
844
845 CurVal = Addr;
846
847 return OldVal;
848 }
849
850 /*
851 * AddGlobalMapping - Tell the execution engine that the specified global is
852 * at the specified location. This is used internally as functions are
853 * JIT'd
854 * and as global variables are laid out in memory.
855 */
856 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
857 void*& CurVal = mGlobalAddressMap[GV];
858 assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!");
859 CurVal = Addr;
860 return;
861 }
862
863 /*
864 * GetPointerToGlobalIfAvailable - This returns the address of the specified
865 * global value if it is has already been codegen'd,
866 * otherwise it returns null.
867 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700868 void* GetPointerToGlobalIfAvailable(const llvm::GlobalValue* GV) {
869 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700870 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
871 }
872
873 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool* MCP) {
874 const std::vector<llvm::MachineConstantPoolEntry>& Constants =
875 MCP->getConstants();
876
877 if(Constants.empty())
878 return 0;
879
880 unsigned int Size = 0;
881 for(int i=0;i<Constants.size();i++) {
882 llvm::MachineConstantPoolEntry CPE = Constants[i];
883 unsigned int AlignMask = CPE.getAlignment() - 1;
884 Size = (Size + AlignMask) & ~AlignMask;
885 const llvm::Type* Ty = CPE.getType();
886 Size += mpTD->getTypeAllocSize(Ty);
887 }
888
889 return Size;
890 }
891
892 /*
893 * This function converts a Constant* into a GenericValue. The interesting
894 * part is if C is a ConstantExpr.
895 */
896 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue& Result) {
897 if(C->getValueID() == llvm::Value::UndefValueVal)
898 return;
899 else if(C->getValueID() == llvm::Value::ConstantExprVal) {
900 const llvm::ConstantExpr* CE = (llvm::ConstantExpr*) C;
901 const llvm::Constant* Op0 = CE->getOperand(0);
902
903 switch(CE->getOpcode()) {
904 case llvm::Instruction::GetElementPtr:
905 {
906 /* Compute the index */
907 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
908 CE->op_end());
909 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
910 &Indices[0],
911 Indices.size());
912
913 GetConstantValue(Op0, Result);
914 Result.PointerVal = (char*) Result.PointerVal + Offset;
915
916 return;
917 }
918 break;
919
920 case llvm::Instruction::Trunc:
921 {
922 uint32_t BitWidth =
923 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
924
925 GetConstantValue(Op0, Result);
926 Result.IntVal = Result.IntVal.trunc(BitWidth);
927
928 return;
929 }
930 break;
931
932 case llvm::Instruction::ZExt:
933 {
934 uint32_t BitWidth =
935 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
936
937 GetConstantValue(Op0, Result);
938 Result.IntVal = Result.IntVal.zext(BitWidth);
939
940 return;
941 }
942 break;
943
944 case llvm::Instruction::SExt:
945 {
946 uint32_t BitWidth =
947 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
948
949 GetConstantValue(Op0, Result);
950 Result.IntVal = Result.IntVal.sext(BitWidth);
951
952 return;
953 }
954 break;
955
956
957 case llvm::Instruction::FPTrunc:
958 {
959 /* FIXME long double */
960 GetConstantValue(Op0, Result);
961 Result.FloatVal = float(Result.DoubleVal);
962 return;
963 }
964 break;
965
966
967 case llvm::Instruction::FPExt:
968 {
969 /* FIXME long double */
970 GetConstantValue(Op0, Result);
971 Result.DoubleVal = double(Result.FloatVal);
972 return;
973 }
974 break;
975
976
977 case llvm::Instruction::UIToFP:
978 {
979 GetConstantValue(Op0, Result);
980 if(CE->getType()->isFloatTy())
981 Result.FloatVal = float(Result.IntVal.roundToDouble());
982 else if(CE->getType()->isDoubleTy())
983 Result.DoubleVal = Result.IntVal.roundToDouble();
984 else if(CE->getType()->isX86_FP80Ty()) {
985 const uint64_t zero[] = { 0, 0 };
986 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
987 apf.convertFromAPInt(Result.IntVal,
988 false,
989 llvm::APFloat::rmNearestTiesToEven);
990 Result.IntVal = apf.bitcastToAPInt();
991 }
992 return;
993 }
994 break;
995
996 case llvm::Instruction::SIToFP:
997 {
998 GetConstantValue(Op0, Result);
999 if(CE->getType()->isFloatTy())
1000 Result.FloatVal = float(Result.IntVal.signedRoundToDouble());
1001 else if(CE->getType()->isDoubleTy())
1002 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
1003 else if(CE->getType()->isX86_FP80Ty()) {
1004 const uint64_t zero[] = { 0, 0 };
1005 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
1006 apf.convertFromAPInt(Result.IntVal,
1007 true,
1008 llvm::APFloat::rmNearestTiesToEven);
1009 Result.IntVal = apf.bitcastToAPInt();
1010 }
1011 return;
1012 }
1013 break;
1014
1015 /* double->APInt conversion handles sign */
1016 case llvm::Instruction::FPToUI:
1017 case llvm::Instruction::FPToSI:
1018 {
1019 uint32_t BitWidth =
1020 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
1021
1022 GetConstantValue(Op0, Result);
1023 if(Op0->getType()->isFloatTy())
1024 Result.IntVal =
1025 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
1026 else if(Op0->getType()->isDoubleTy())
1027 Result.IntVal =
1028 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal, BitWidth);
1029 else if(Op0->getType()->isX86_FP80Ty()) {
1030 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
1031 uint64_t v;
1032 bool ignored;
1033 apf.convertToInteger(&v,
1034 BitWidth,
1035 CE->getOpcode()
1036 == llvm::Instruction::FPToSI,
1037 llvm::APFloat::rmTowardZero,
1038 &ignored);
1039 Result.IntVal = v; // endian?
1040 }
1041 return;
1042 }
1043 break;
1044
1045 case llvm::Instruction::PtrToInt:
1046 {
1047 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1048
1049 GetConstantValue(Op0, Result);
1050 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
1051 (Result.PointerVal));
1052
1053 return;
1054 }
1055 break;
1056
1057 case llvm::Instruction::IntToPtr:
1058 {
1059 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
1060
1061 GetConstantValue(Op0, Result);
1062 if(PtrWidth != Result.IntVal.getBitWidth())
1063 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
1064 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
1065
1066 Result.PointerVal = llvm::PointerTy
1067 (uintptr_t(Result.IntVal.getZExtValue()));
1068
1069 return;
1070 }
1071 break;
1072
1073 case llvm::Instruction::BitCast:
1074 {
1075 GetConstantValue(Op0, Result);
1076 const llvm::Type* DestTy = CE->getType();
1077
1078 switch(Op0->getType()->getTypeID()) {
1079 case llvm::Type::IntegerTyID:
1080 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
1081 if(DestTy->isFloatTy())
1082 Result.FloatVal = Result.IntVal.bitsToFloat();
1083 else if(DestTy->isDoubleTy())
1084 Result.DoubleVal = Result.IntVal.bitsToDouble();
1085 break;
1086
1087 case llvm::Type::FloatTyID:
1088 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
1089 Result.IntVal.floatToBits(Result.FloatVal);
1090 break;
1091
1092 case llvm::Type::DoubleTyID:
1093 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1094 Result.IntVal.doubleToBits(Result.DoubleVal);
1095 break;
1096
1097 case llvm::Type::PointerTyID:
1098 assert(DestTy->isPointerTy() && "Invalid bitcast");
1099 break; // getConstantValue(Op0) above already converted it
1100
1101 default:
1102 llvm_unreachable("Invalid bitcast operand");
1103 break;
1104 }
1105
1106 return;
1107 }
1108 break;
1109
1110 case llvm::Instruction::Add:
1111 case llvm::Instruction::FAdd:
1112 case llvm::Instruction::Sub:
1113 case llvm::Instruction::FSub:
1114 case llvm::Instruction::Mul:
1115 case llvm::Instruction::FMul:
1116 case llvm::Instruction::UDiv:
1117 case llvm::Instruction::SDiv:
1118 case llvm::Instruction::URem:
1119 case llvm::Instruction::SRem:
1120 case llvm::Instruction::And:
1121 case llvm::Instruction::Or:
1122 case llvm::Instruction::Xor:
1123 {
1124 llvm::GenericValue LHS, RHS;
1125 GetConstantValue(Op0, LHS);
1126 GetConstantValue(CE->getOperand(1), RHS);
1127
1128 switch(Op0->getType()->getTypeID()) {
1129 case llvm::Type::IntegerTyID:
1130 switch (CE->getOpcode()) {
1131 case llvm::Instruction::Add:
1132 Result.IntVal = LHS.IntVal + RHS.IntVal;
1133 break;
1134 case llvm::Instruction::Sub:
1135 Result.IntVal = LHS.IntVal - RHS.IntVal;
1136 break;
1137 case llvm::Instruction::Mul:
1138 Result.IntVal = LHS.IntVal * RHS.IntVal;
1139 break;
1140 case llvm::Instruction::UDiv:
1141 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1142 break;
1143 case llvm::Instruction::SDiv:
1144 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1145 break;
1146 case llvm::Instruction::URem:
1147 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1148 break;
1149 case llvm::Instruction::SRem:
1150 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1151 break;
1152 case llvm::Instruction::And:
1153 Result.IntVal = LHS.IntVal & RHS.IntVal;
1154 break;
1155 case llvm::Instruction::Or:
1156 Result.IntVal = LHS.IntVal | RHS.IntVal;
1157 break;
1158 case llvm::Instruction::Xor:
1159 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1160 break;
1161 default:
1162 llvm_unreachable("Invalid integer opcode");
1163 break;
1164 }
1165 break;
1166
1167 case llvm::Type::FloatTyID:
1168 switch (CE->getOpcode()) {
1169 case llvm::Instruction::FAdd:
1170 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1171 break;
1172 case llvm::Instruction::FSub:
1173 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1174 break;
1175 case llvm::Instruction::FMul:
1176 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1177 break;
1178 case llvm::Instruction::FDiv:
1179 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1180 break;
1181 case llvm::Instruction::FRem:
1182 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1183 break;
1184 default:
1185 llvm_unreachable("Invalid float opcode");
1186 break;
1187 }
1188 break;
1189
1190 case llvm::Type::DoubleTyID:
1191 switch (CE->getOpcode()) {
1192 case llvm::Instruction::FAdd:
1193 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1194 break;
1195 case llvm::Instruction::FSub:
1196 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1197 break;
1198 case llvm::Instruction::FMul:
1199 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1200 break;
1201 case llvm::Instruction::FDiv:
1202 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1203 break;
1204 case llvm::Instruction::FRem:
1205 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1206 break;
1207 default:
1208 llvm_unreachable("Invalid double opcode");
1209 break;
1210 }
1211 break;
1212
1213 case llvm::Type::X86_FP80TyID:
1214 case llvm::Type::PPC_FP128TyID:
1215 case llvm::Type::FP128TyID:
1216 {
1217 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1218 switch (CE->getOpcode()) {
1219 case llvm::Instruction::FAdd:
1220 apfLHS.add(llvm::APFloat(RHS.IntVal),
1221 llvm::APFloat::rmNearestTiesToEven);
1222 break;
1223 case llvm::Instruction::FSub:
1224 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1225 llvm::APFloat::rmNearestTiesToEven);
1226 break;
1227 case llvm::Instruction::FMul:
1228 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1229 llvm::APFloat::rmNearestTiesToEven);
1230 break;
1231 case llvm::Instruction::FDiv:
1232 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1233 llvm::APFloat::rmNearestTiesToEven);
1234 break;
1235 case llvm::Instruction::FRem:
1236 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1237 llvm::APFloat::rmNearestTiesToEven);
1238 break;
1239 default:
1240 llvm_unreachable("Invalid long double opcode");
1241 llvm_unreachable(0);
1242 break;
1243 }
1244
1245 Result.IntVal = apfLHS.bitcastToAPInt();
1246 }
1247 break;
1248
1249 default:
1250 llvm_unreachable("Bad add type!");
1251 break;
1252 } /* End switch(Op0->getType()->getTypeID()) */
1253
1254 return;
1255 }
1256
1257 default:
1258 break;
1259 } /* End switch(CE->getOpcode()) */
1260
1261 std::string msg;
1262 llvm::raw_string_ostream Msg(msg);
1263 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001264 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001265 } /* C->getValueID() == llvm::Value::ConstantExprVal */
1266
1267 switch (C->getType()->getTypeID()) {
1268 case llvm::Type::FloatTyID:
1269 Result.FloatVal = llvm::cast<llvm::ConstantFP>(C)
1270 ->getValueAPF().convertToFloat();
1271 break;
1272
1273 case llvm::Type::DoubleTyID:
1274 Result.DoubleVal = llvm::cast<llvm::ConstantFP>(C)
1275 ->getValueAPF().convertToDouble();
1276 break;
1277
1278 case llvm::Type::X86_FP80TyID:
1279 case llvm::Type::FP128TyID:
1280 case llvm::Type::PPC_FP128TyID:
1281 Result.IntVal = llvm::cast <llvm::ConstantFP>(C)
1282 ->getValueAPF().bitcastToAPInt();
1283 break;
1284
1285 case llvm::Type::IntegerTyID:
1286 Result.IntVal = llvm::cast<llvm::ConstantInt>(C)
1287 ->getValue();
1288 break;
1289
1290 case llvm::Type::PointerTyID:
1291 switch(C->getValueID()) {
1292 case llvm::Value::ConstantPointerNullVal:
1293 Result.PointerVal = NULL;
1294 break;
1295
1296 case llvm::Value::FunctionVal:
1297 {
1298 const llvm::Function* F = (llvm::Function*) C;
1299 Result.PointerVal = GetPointerToFunctionOrStub
1300 (const_cast<llvm::Function*>(F)
1301 );
1302 }
1303 break;
1304
1305 case llvm::Value::GlobalVariableVal:
1306 {
1307 const llvm::GlobalVariable* GV = (llvm::GlobalVariable*) C;
1308 Result.PointerVal = GetOrEmitGlobalVariable
1309 (const_cast<llvm::GlobalVariable*>(GV)
1310 );
1311 }
1312 break;
1313
1314 case llvm::Value::BlockAddressVal:
1315 {
1316 // const llvm::BlockAddress* BA = (llvm::BlockAddress*) C;
1317 // Result.PointerVal = getPointerToBasicBlock
1318 // (const_cast<llvm::BasicBlock*>(BA->getBasicBlock()));
1319 assert(false && "JIT does not support address-of-label yet!");
1320 }
1321 break;
1322
1323 default:
1324 llvm_unreachable("Unknown constant pointer type!");
1325 break;
1326 }
1327 break;
1328
1329 default:
1330 std::string msg;
1331 llvm::raw_string_ostream Msg(msg);
1332 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001333 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001334 break;
1335 }
1336
1337 return;
1338 }
1339
1340 /*
1341 * StoreValueToMemory -
1342 * Stores the data in @Val of type @Ty at address @Addr.
1343 */
1344 void StoreValueToMemory(const llvm::GenericValue& Val, void* Addr,
1345 const llvm::Type *Ty) {
1346 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1347
1348 switch(Ty->getTypeID()) {
1349 case llvm::Type::IntegerTyID:
1350 {
1351 const llvm::APInt& IntVal = Val.IntVal;
1352 assert((IntVal.getBitWidth() + 7) / 8 >= StoreBytes &&
1353 "Integer too small!");
1354
1355 uint8_t *Src = (uint8_t*) IntVal.getRawData();
1356
1357 if(llvm::sys::isLittleEndianHost()) {
1358 /*
1359 * Little-endian host - the source is ordered from LSB to MSB.
1360 * Order the destination from LSB to MSB: Do a straight copy.
1361 */
1362 memcpy(Addr, Src, StoreBytes);
1363 } else {
1364 /*
1365 * Big-endian host - the source is an array of 64 bit words
1366 * ordered from LSW to MSW.
1367 *
1368 * Each word is ordered from MSB to LSB.
1369 *
1370 * Order the destination from MSB to LSB:
1371 * Reverse the word order, but not the bytes in a word.
1372 */
1373 unsigned int i = StoreBytes;
1374 while(i > sizeof(uint64_t)) {
1375 i -= sizeof(uint64_t);
1376 memcpy((uint8_t*) Addr + i, Src, sizeof(uint64_t));
1377 Src += sizeof(uint64_t);
1378 }
1379
1380 memcpy(Addr, Src + sizeof(uint64_t) - i, i);
1381 }
1382 }
1383 break;
1384
1385 case llvm::Type::FloatTyID:
1386 {
1387 *((float*) Addr) = Val.FloatVal;
1388 }
1389 break;
1390
1391 case llvm::Type::DoubleTyID:
1392 {
1393 *((double*) Addr) = Val.DoubleVal;
1394 }
1395 break;
1396
1397 case llvm::Type::X86_FP80TyID:
1398 {
1399 memcpy(Addr, Val.IntVal.getRawData(), 10);
1400 }
1401 break;
1402
1403 case llvm::Type::PointerTyID:
1404 {
1405 /*
1406 * Ensure 64 bit target pointers are fully
1407 * initialized on 32 bit hosts.
1408 */
1409 if(StoreBytes != sizeof(llvm::PointerTy))
1410 memset(Addr, 0, StoreBytes);
1411 *((llvm::PointerTy*) Addr) = Val.PointerVal;
1412 }
1413 break;
1414
1415 default:
1416 break;
1417 }
1418
1419 if(llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1420 std::reverse((uint8_t*) Addr, (uint8_t*) Addr + StoreBytes);
1421
1422 return;
1423 }
1424
1425 /*
1426 * InitializeConstantToMemory -
1427 * Recursive function to apply a @Constant value into the
1428 * specified memory location @Addr.
1429 */
1430 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
1431 switch(C->getValueID()) {
1432 case llvm::Value::UndefValueVal:
1433 // Nothing to do
1434 break;
1435
1436 case llvm::Value::ConstantVectorVal:
1437 {
1438 // dynamic cast may hurt performance
1439 const llvm::ConstantVector* CP = (llvm::ConstantVector*) C;
1440
1441 unsigned int ElementSize = mpTD->getTypeAllocSize
1442 (CP->getType()->getElementType());
1443
1444 for(int i=0;i<CP->getNumOperands();i++)
1445 InitializeConstantToMemory(CP->getOperand(i),
1446 (char*) Addr + i * ElementSize);
1447 }
1448 break;
1449
1450 case llvm::Value::ConstantAggregateZeroVal:
1451 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1452 break;
1453
1454 case llvm::Value::ConstantArrayVal:
1455 {
1456 const llvm::ConstantArray* CPA = (llvm::ConstantArray*) C;
1457 unsigned int ElementSize = mpTD->getTypeAllocSize
1458 (CPA->getType()->getElementType());
1459
1460 for(int i=0;i<CPA->getNumOperands();i++)
1461 InitializeConstantToMemory(CPA->getOperand(i),
1462 (char*) Addr + i * ElementSize);
1463 }
1464 break;
1465
1466 case llvm::Value::ConstantStructVal:
1467 {
1468 const llvm::ConstantStruct* CPS = (llvm::ConstantStruct*) C;
1469 const llvm::StructLayout* SL = mpTD->getStructLayout
1470 (llvm::cast<llvm::StructType>(CPS->getType()));
1471
1472 for(int i=0;i<CPS->getNumOperands();i++)
1473 InitializeConstantToMemory(CPS->getOperand(i),
1474 (char*) Addr +
1475 SL->getElementOffset(i));
1476 }
1477 break;
1478
1479 default:
1480 {
1481 if(C->getType()->isFirstClassType()) {
1482 llvm::GenericValue Val;
1483 GetConstantValue(C, Val);
1484 StoreValueToMemory(Val, Addr, C->getType());
1485 } else
1486 llvm_unreachable
1487 ("Unknown constant type to initialize memory with!");
1488 }
1489 break;
1490 }
1491
1492 return;
1493 }
1494
1495 void emitConstantPool(llvm::MachineConstantPool *MCP) {
1496 if(mpTJI->hasCustomConstantPool())
1497 return;
1498
1499 /*
1500 * Constant pool address resolution is handled by the target itself in ARM
1501 * (TargetJITInfo::hasCustomConstantPool() return true).
1502 */
1503#if !defined(PROVIDE_ARM_CODEGEN)
1504 const std::vector<llvm::MachineConstantPoolEntry>& Constants =
1505 MCP->getConstants();
1506
1507 if(Constants.empty())
1508 return;
1509
1510 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1511 unsigned Align = MCP->getConstantPoolAlignment();
1512
1513 mpConstantPoolBase = allocateSpace(Size, Align);
1514 mpConstantPool = MCP;
1515
1516 if(mpConstantPoolBase == NULL)
1517 return; /* out of memory */
1518
1519 unsigned Offset = 0;
1520 for(int i=0;i<Constants.size();i++) {
1521 llvm::MachineConstantPoolEntry CPE = Constants[i];
1522 unsigned AlignMask = CPE.getAlignment() - 1;
1523 Offset = (Offset + AlignMask) & ~AlignMask;
1524
1525 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1526 mConstPoolAddresses.push_back(CAddr);
1527
1528 if(CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001529 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001530 ("Initialize memory with machine specific constant pool"
1531 " entry has not been implemented!");
1532
1533 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1534
1535 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1536 Offset += mpTD->getTypeAllocSize(Ty);
1537 }
1538#endif
1539 return;
1540 }
1541
1542 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
1543 if(mpTJI->hasCustomJumpTables())
1544 return;
1545
1546 const std::vector<llvm::MachineJumpTableEntry>& JT =
1547 MJTI->getJumpTables();
1548 if(JT.empty())
1549 return;
1550
1551 unsigned NumEntries = 0;
1552 for(int i=0;i<JT.size();i++)
1553 NumEntries += JT[i].MBBs.size();
1554
1555 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1556
1557 mpJumpTable = MJTI;;
1558 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
1559 MJTI->getEntryAlignment(*mpTD));
1560
1561 return;
1562 }
1563
1564 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
1565 if(mpTJI->hasCustomJumpTables())
1566 return;
1567
1568 const std::vector<llvm::MachineJumpTableEntry>& JT =
1569 MJTI->getJumpTables();
1570 if(JT.empty() || mpJumpTableBase == 0)
1571 return;
1572
1573 assert((llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static)
1574 && "Cross JIT'ing?");
1575 assert(MJTI->getEntrySize(*mpTD) == sizeof(void*) && "Cross JIT'ing?");
1576
1577 /*
1578 * For each jump table, map each target in the jump table to the
1579 * address of an emitted MachineBasicBlock.
1580 */
1581 intptr_t *SlotPtr = (intptr_t*) mpJumpTableBase;
1582 for(int i=0;i<JT.size();i++) {
1583 const std::vector<llvm::MachineBasicBlock*>& MBBs = JT[i].MBBs;
1584 /*
1585 * Store the address of the basic block for this jump table slot in the
1586 * memory we allocated for the jump table in 'initJumpTableInfo'
1587 */
1588 for(int j=0;j<MBBs.size();j++)
1589 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1590 }
1591 }
1592
1593 void* GetPointerToGlobal(llvm::GlobalValue* V, void* Reference,
1594 bool MayNeedFarStub) {
1595 switch(V->getValueID()) {
1596 case llvm::Value::FunctionVal:
1597 {
1598 llvm::Function* F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001599
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001600 /* If we have code, go ahead and return that. */
1601 if(void* ResultPtr = GetPointerToGlobalIfAvailable(F))
1602 return ResultPtr;
1603
1604 if(void* FnStub = GetLazyFunctionStubIfAvailable(F))
1605 /*
1606 * Return the function stub if it's already created.
1607 * We do this first so that:
1608 * we're returning the same address for the function
1609 * as any previous call.
1610 *
1611 * TODO: Yes, this is wrong. The lazy stub isn't guaranteed
1612 * to be close enough to call.
1613 */
1614 return FnStub;
1615
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001616 /*
1617 * If we know the target can handle arbitrary-distance calls, try to
1618 * return a direct pointer.
1619 */
1620 if(!MayNeedFarStub) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001621 /*
1622 * x86_64 architecture may encounter the bug
1623 * http://hlvm.llvm.org/bugs/show_bug.cgi?id=5201
1624 * which generate instruction "call" instead of "callq".
1625 *
1626 * And once the real address of stub is
1627 * greater than 64-bit long, the replacement will truncate
1628 * to 32-bit resulting a serious problem.
1629 */
1630#if !defined(__x86_64__)
1631 /*
1632 * If this is an external function pointer,
1633 * we can force the JIT to
1634 * 'compile' it, which really just adds it to the map.
1635 */
1636 if(F->isDeclaration() || F->hasAvailableExternallyLinkage())
1637 return GetPointerToFunction(F, /* AbortOnFailure */true);
1638#endif
1639 }
1640
1641 /*
1642 * Otherwise, we may need a to emit a stub, and, conservatively, we
1643 * always do so.
1644 */
1645 return GetLazyFunctionStub(F);
1646 }
1647 break;
1648
1649 case llvm::Value::GlobalVariableVal:
1650 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1651 break;
1652
1653 case llvm::Value::GlobalAliasVal:
1654 {
1655 llvm::GlobalAlias* GA = (llvm::GlobalAlias*) V;
1656 const llvm::GlobalValue* GV = GA->resolveAliasedGlobal(false);
1657
1658 switch(GV->getValueID()) {
1659 case llvm::Value::FunctionVal:
1660 /* FIXME: is there's any possibility that the function
1661 is not code-gen'd? */
1662 return GetPointerToFunction(
1663 const_cast<llvm::Function*>((const llvm::Function*) GV),
1664 /* AbortOnFailure */true
1665 );
1666 break;
1667
1668 case llvm::Value::GlobalVariableVal:
1669 {
1670 if(void* p = mGlobalAddressMap[GV])
1671 return p;
1672
1673 llvm::GlobalVariable* GVar = (llvm::GlobalVariable*) GV;
1674 EmitGlobalVariable(GVar);
1675
1676 return mGlobalAddressMap[GV];
1677 }
1678 break;
1679
1680 case llvm::Value::GlobalAliasVal:
1681 assert(false && "Alias should be resolved ultimately!");
1682 break;
1683 }
1684 }
1685 break;
1686
1687 default:
1688 break;
1689 }
1690
1691 llvm_unreachable("Unknown type of global value!");
1692
1693 }
1694
1695 /*
1696 * GetPointerToFunctionOrStub - If the specified function has been
1697 * code-gen'd, return a pointer to the function.
1698 * If not, compile it, or use
1699 * a stub to implement lazy compilation if available.
1700 */
1701 void* GetPointerToFunctionOrStub(llvm::Function* F) {
1702 /*
1703 * If we have already code generated the function,
1704 * just return the address.
1705 */
1706 if(void* Addr = GetPointerToGlobalIfAvailable(F))
1707 return Addr;
1708
1709 /* Get a stub if the target supports it. */
1710 return GetLazyFunctionStub(F);
1711 }
1712
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001713 typedef llvm::DenseMap<const llvm::Function*, void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001714 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1715
1716 void* GetLazyFunctionStubIfAvailable(llvm::Function* F) {
1717 return mFunctionToLazyStubMap.lookup(F);
1718 }
1719
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001720 std::set<const llvm::Function*> PendingFunctions;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001721 void* GetLazyFunctionStub(llvm::Function* F) {
1722 /* If we already have a lazy stub for this function, recycle it. */
1723 void*& Stub = mFunctionToLazyStubMap[F];
1724 if(Stub)
1725 return Stub;
1726
1727 /*
1728 * In any cases, we should NOT resolve function at runtime
1729 * (though we are able to).
1730 * We resolve this right now.
1731 */
1732 void* Actual = NULL;
1733 if(F->isDeclaration() || F->hasAvailableExternallyLinkage())
1734 Actual = GetPointerToFunction(F, /* AbortOnFailure */true);
1735
1736 /*
1737 * Codegen a new stub, calling the actual address of
1738 * the external function, if it was resolved.
1739 */
1740 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1741 startGVStub(F, SL.Size, SL.Alignment);
1742 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1743 finishGVStub();
1744
1745 /*
1746 * We really want the address of the stub in the GlobalAddressMap
1747 * for the JIT, not the address of the external function.
1748 */
1749 UpdateGlobalMapping(F, Stub);
1750
1751 if(!Actual)
1752 PendingFunctions.insert(F);
1753 else
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001754 Disassemble(F->getName(), (uint8_t*) Stub, SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001755
1756 return Stub;
1757 }
1758
1759 /* Our resolver to undefined symbol */
1760 BCCSymbolLookupFn mpSymbolLookupFn;
1761 void* mpSymbolLookupContext;
1762
1763 void* GetPointerToFunction(llvm::Function* F, bool AbortOnFailure) {
1764 void* Addr = GetPointerToGlobalIfAvailable(F);
1765 if(Addr)
1766 return Addr;
1767
1768 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1769 "Internal error: only external defined function routes here!");
1770
1771 /* Handle the failure resolution by ourselves. */
1772 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
1773 /* AbortOnFailure */ false);
1774
1775 /*
1776 * If we resolved the symbol to a null address (eg. a weak external)
1777 * return a null pointer let the application handle it.
1778 */
1779 if(Addr == NULL)
1780 if(AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001781 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001782 ("Could not resolve external function address: " + F->getName()
1783 );
1784 else
1785 return NULL;
1786
1787 AddGlobalMapping(F, Addr);
1788
1789 return Addr;
1790 }
1791
1792 void* GetPointerToNamedSymbol(const std::string& Name,
1793 bool AbortOnFailure) {
1794 if(void* Addr = FindRuntimeFunction(Name.c_str()))
1795 return Addr;
1796
1797 if(mpSymbolLookupFn)
1798 if(void* Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
1799 return Addr;
1800
1801 if(AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001802 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001803 "' which could not be resolved!");
1804
1805 return NULL;
1806 }
1807
1808 /*
1809 * GetOrEmitGlobalVariable - Return the address of the specified global
1810 * variable, possibly emitting it to memory if needed. This is used by the
1811 * Emitter.
1812 */
1813 void* GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1814 void* Ptr = GetPointerToGlobalIfAvailable(GV);
1815 if(Ptr)
1816 return Ptr;
1817
1818 if(GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1819 /* If the global is external, just remember the address. */
1820 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1821 AddGlobalMapping(GV, Ptr);
1822 } else {
1823 /* If the global hasn't been emitted to memory yet,
1824 allocate space and emit it into memory. */
1825 Ptr = GetMemoryForGV(GV);
1826 AddGlobalMapping(GV, Ptr);
1827 EmitGlobalVariable(GV);
1828 }
1829
1830 return Ptr;
1831 }
1832
1833 /*
1834 * GetMemoryForGV - This method abstracts memory allocation of global
1835 * variable so that the JIT can allocate thread local variables depending
1836 * on the target.
1837 */
1838 void* GetMemoryForGV(const llvm::GlobalVariable* GV) {
1839 char* Ptr;
1840
1841 const llvm::Type* GlobalType = GV->getType()->getElementType();
1842 size_t S = mpTD->getTypeAllocSize(GlobalType);
1843 size_t A = mpTD->getPreferredAlignment(GV);
1844
1845 if(GV->isThreadLocal()) {
1846 /*
1847 * We can support TLS by
1848 *
1849 * Ptr = TJI.allocateThreadLocalMemory(S);
1850 *
1851 * But I tend not to .
1852 * (should we disable this in the front-end (i.e. slang)?).
1853 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001854 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001855 ("Compilation of Thread Local Storage (TLS) is disabled!");
1856
1857 } else if(mpTJI->allocateSeparateGVMemory()) {
1858 /*
1859 * On the Apple's ARM target (such as iPhone),
1860 * the global variable should be
1861 * placed in separately allocated heap memory rather than in the same
1862 * code memory.
1863 * The question is, how about the Android?
1864 */
1865 if(A <= 8) {
1866 Ptr = (char*) malloc(S);
1867 } else {
1868 /*
1869 * Allocate (S + A) bytes of memory,
1870 * then use an aligned pointer within that space.
1871 */
1872 Ptr = (char*) malloc(S + A);
1873 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
1874 Ptr = Ptr + (MisAligned ? (A - MisAligned) : 0);
1875 }
1876 } else {
1877 Ptr = (char*) allocateGlobal(S, A);
1878 }
1879
1880 return Ptr;
1881 }
1882
1883 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
1884 void* GA = GetPointerToGlobalIfAvailable(GV);
1885
1886 if(GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001887 llvm::report_fatal_error
1888 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001889
1890 if(GA == NULL) {
1891 /* If it's not already specified, allocate memory for the global. */
1892 GA = GetMemoryForGV(GV);
1893 AddGlobalMapping(GV, GA);
1894 }
1895
1896 InitializeConstantToMemory(GV->getInitializer(), GA);
1897
1898 /* You can do some statistics on global variable here */
1899 return;
1900 }
1901
1902 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1903 > GlobalToIndirectSymMapTy;
1904 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1905
1906 void* GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1907 /*
1908 * Make sure GV is emitted first, and create a stub containing the fully
1909 * resolved address.
1910 */
1911 void* GVAddress = GetPointerToGlobal(V, Reference, false);
1912
1913 /* If we already have a stub for this global variable, recycle it. */
1914 void*& IndirectSym = GlobalToIndirectSymMap[V];
1915 /* Otherwise, codegen a new indirect symbol. */
1916 if(!IndirectSym)
1917 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1918
1919 return IndirectSym;
1920 }
1921
1922 /*
1923 * ExternalFnToStubMap - This is the equivalent of FunctionToLazyStubMap
1924 * for external functions.
1925 *
1926 * TODO: Of course, external functions don't need a lazy stub.
1927 * It's actually
1928 * here to make it more likely that far calls succeed, but no single
1929 * stub can guarantee that. I'll remove this in a subsequent checkin
1930 * when I actually fix far calls. (comment from LLVM source)
1931 */
1932 std::map<void*, void*> ExternalFnToStubMap;
1933
1934 /*
1935 * GetExternalFunctionStub - Return a stub for the function at the
1936 * specified address.
1937 */
1938 void* GetExternalFunctionStub(void* FnAddr) {
1939 void*& Stub = ExternalFnToStubMap[FnAddr];
1940 if(Stub)
1941 return Stub;
1942
1943 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1944 startGVStub(0, SL.Size, SL.Alignment);
1945 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1946 finishGVStub();
1947
1948 return Stub;
1949 }
1950
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001951#if defined(USE_DISASSEMBLER)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001952 const llvm::MCAsmInfo* mpAsmInfo;
1953 const llvm::MCDisassembler* mpDisassmbler;
1954 llvm::MCInstPrinter* mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001955
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001956 class BufferMemoryObject : public llvm::MemoryObject {
1957 private:
1958 const uint8_t* mBytes;
1959 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001960
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001961 public:
1962 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1963 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001964
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001965 uint64_t getBase() const { return 0; }
1966 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001967
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001968 int readByte(uint64_t Addr, uint8_t *Byte) const {
1969 if(Addr > getExtent())
1970 return -1;
1971 *Byte = mBytes[Addr];
1972 return 0;
1973 }
1974 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001975
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001976 void Disassemble(const llvm::StringRef& Name, uint8_t* Start,
1977 size_t Length, bool IsStub) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001978 llvm::raw_fd_ostream* OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001979#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001980 std::string ErrorInfo;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001981 OS = new llvm::raw_fd_ostream(
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001982 "/data/local/tmp/out.S", ErrorInfo, llvm::raw_fd_ostream::F_Append);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001983 if(!ErrorInfo.empty()) { // some errors occurred
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001984 //LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001985 delete OS;
1986 return;
1987 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001988#else
1989 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001990#endif
1991
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001992
1993 *OS << "JIT: Disassembled code: " << Name
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001994 << ((IsStub) ? " (stub)" : "") << "\n";
1995
1996 if(mpAsmInfo == NULL)
1997 mpAsmInfo = mpTarget->createAsmInfo(Triple);
1998 if(mpDisassmbler == NULL)
1999 mpDisassmbler = mpTarget->createMCDisassembler();
2000 if(mpIP == NULL)
2001 mpIP = mpTarget->createMCInstPrinter(
2002 mpAsmInfo->getAssemblerDialect(), *mpAsmInfo);
2003
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002004 const BufferMemoryObject* BufferMObj =
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002005 new BufferMemoryObject(Start, Length);
2006 uint64_t Size;
2007 uint64_t Index;
2008
2009 for(Index=0;Index<Length;Index+=Size) {
2010 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002011
2012 if(mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
2013 /* REMOVED */ llvm::nulls()))
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002014 {
2015 OS->indent(4).write("0x", 2).
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002016 write_hex((uint32_t) Start + Index).write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002017 mpIP->printInst(&Inst, *OS);
2018 *OS << "\n";
2019 } else {
2020 if (Size == 0)
2021 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002022 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002023 }
2024
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002025 *OS << "\n";
2026 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002027
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002028#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002029 /* If you want the disassemble results write to file, uncomment this */
2030 OS->close();
2031 delete OS;
2032#endif
2033
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002034 return;
2035 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002036#else
2037 void Disassemble(const std::string& Name, uint8_t* Start,
2038 size_t Length, bool IsStub) {
2039 return;
2040 }
2041#endif /* defined(USE_DISASSEMBLER) */
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002042
2043 public:
2044 /* Will take the ownership of @MemMgr */
2045 CodeEmitter(CodeMemoryManager* pMemMgr) :
2046 mpMemMgr(pMemMgr),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002047 mpTarget(NULL),
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002048 mpTJI(NULL),
2049 mpTD(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002050#if defined(USE_DISASSEMBLER)
2051 mpAsmInfo(NULL),
2052 mpDisassmbler(NULL),
2053 mpIP(NULL),
2054#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002055 mpCurEmitFunction(NULL),
2056 mpConstantPool(NULL),
2057 mpJumpTable(NULL),
2058 mpMMI(NULL),
2059 mpSymbolLookupFn(NULL),
2060 mpSymbolLookupContext(NULL)
2061 {
2062 return;
2063 }
2064
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002065 inline global_addresses_const_iterator global_address_begin() const {
2066 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002067 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002068 inline global_addresses_const_iterator global_address_end() const {
2069 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002070 }
2071
2072 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid* pContext) {
2073 mpSymbolLookupFn = pFn;
2074 mpSymbolLookupContext = pContext;
2075 return;
2076 }
2077
2078 void setTargetMachine(llvm::TargetMachine& TM) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002079 /* set Target */
2080 mpTarget = &TM.getTarget();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002081 /* set TargetJITInfo */
2082 mpTJI = TM.getJITInfo();
2083 /* set TargetData */
2084 mpTD = TM.getTargetData();
2085
2086 /*
2087 if(mpTJI->needsGOT())
2088 mpMemMgr->AllocateGOT(); // however,
2089 // both X86 and ARM target don't need GOT
2090 // (mpTJI->needsGOT() always returns false)
2091 */
2092 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
2093
2094 return;
2095 }
2096
2097 /*
2098 * startFunction - This callback is invoked when the specified function is
2099 * about to be code generated. This initializes the BufferBegin/End/Ptr
2100 * fields.
2101 */
2102 void startFunction(llvm::MachineFunction &F) {
2103 uintptr_t ActualSize = 0;
2104
2105 mpMemMgr->setMemoryWritable();
2106
2107 /*
2108 * BufferBegin, BufferEnd and CurBufferPtr
2109 * are all inherited from class MachineCodeEmitter,
2110 * which is the super class of the class JITCodeEmitter.
2111 *
2112 * BufferBegin/BufferEnd - Pointers to the start and end of the memory
2113 * allocated for this code buffer.
2114 *
2115 * CurBufferPtr - Pointer to the next byte of memory to fill when emitting
2116 * code.
2117 * This is guranteed to be in the range [BufferBegin,BufferEnd]. If
2118 * this pointer is at BufferEnd, it will never move due to code emission,
2119 * and
2120 * all code emission requests will be ignored (this is
2121 * the buffer overflow condition).
2122 */
2123 BufferBegin = CurBufferPtr = mpMemMgr
2124 ->startFunctionBody(F.getFunction(), ActualSize);
2125 BufferEnd = BufferBegin + ActualSize;
2126
2127 if(mpCurEmitFunction == NULL)
2128 mpCurEmitFunction = new EmittedFunctionCode();
2129 mpCurEmitFunction->FunctionBody = BufferBegin;
2130
2131 /* Ensure the constant pool/jump table info is at least 4-byte aligned. */
2132 emitAlignment(16);
2133
2134 emitConstantPool(F.getConstantPool());
2135 if(llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
2136 initJumpTableInfo(MJTI);
2137
2138 /* About to start emitting the machine code for the function. */
2139 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
2140
2141 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
2142
2143 mpCurEmitFunction->Code = CurBufferPtr;
2144
2145 mMBBLocations.clear();
2146
2147 return;
2148 }
2149
2150 /*
2151 * finishFunction - This callback is invoked
2152 * when the specified function has
2153 * finished code generation.
2154 * If a buffer overflow has occurred, this method
2155 * returns true (the callee is required to try again), otherwise it returns
2156 * false.
2157 */
2158 bool finishFunction(llvm::MachineFunction &F) {
2159 if(CurBufferPtr == BufferEnd) {
2160 /* No enough memory */
2161 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2162 return false;
2163 }
2164
2165 if(llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
2166 emitJumpTableInfo(MJTI);
2167
2168 /*
2169 * FnStart is the start of the text,
2170 * not the start of the constant pool and other per-function data.
2171 */
2172 uint8_t* FnStart = (uint8_t*) GetPointerToGlobalIfAvailable
2173 (F.getFunction());
2174
2175 /* FnEnd is the end of the function's machine code. */
2176 uint8_t* FnEnd = CurBufferPtr;
2177
2178 if(!mRelocations.empty()) {
2179 /* Resolve the relocations to concrete pointers. */
2180 for(int i=0;i<mRelocations.size();i++) {
2181 llvm::MachineRelocation& MR = mRelocations[i];
2182 void* ResultPtr = NULL;
2183
2184 if(!MR.letTargetResolve()) {
2185 if(MR.isExternalSymbol()) {
2186 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
2187 if(MR.mayNeedFarStub())
2188 ResultPtr = GetExternalFunctionStub(ResultPtr);
2189 } else if(MR.isGlobalValue()) {
2190 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2191 BufferBegin
2192 + MR.getMachineCodeOffset(),
2193 MR.mayNeedFarStub());
2194 } else if(MR.isIndirectSymbol()) {
2195 ResultPtr = GetPointerToGVIndirectSym
2196 (MR.getGlobalValue(),
2197 BufferBegin + MR.getMachineCodeOffset()
2198 );
2199 } else if(MR.isBasicBlock()) {
2200 ResultPtr =
2201 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
2202 } else if(MR.isConstantPoolIndex()) {
2203 ResultPtr =
2204 (void*) getConstantPoolEntryAddress
2205 (MR.getConstantPoolIndex());
2206 } else {
2207 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2208 ResultPtr =
2209 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2210 }
2211
2212 MR.setResultPointer(ResultPtr);
2213 }
2214 }
2215
2216 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2217 mpMemMgr->getGOTBase());
2218 }
2219
2220 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
2221 /*
2222 * CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2223 * global variables that were referenced in the relocations.
2224 */
2225 if(CurBufferPtr == BufferEnd)
2226 return false;
2227
2228 /* Now that we've succeeded in emitting the function */
2229 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2230 BufferBegin = CurBufferPtr = 0;
2231
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002232 if(F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002233 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2234 mpCurEmitFunction = NULL;
2235
2236 mRelocations.clear();
2237 mConstPoolAddresses.clear();
2238
2239 /* Mark code region readable and executable if it's not so already. */
2240 mpMemMgr->setMemoryExecutable();
2241
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002242 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002243
2244 if(mpMMI)
2245 mpMMI->EndFunction();
2246
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002247 updateFunctionStub(F.getFunction());
2248
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002249 return false;
2250 }
2251
2252 void startGVStub(const llvm::GlobalValue* GV, unsigned StubSize,
2253 unsigned Alignment) {
2254 mpSavedBufferBegin = BufferBegin;
2255 mpSavedBufferEnd = BufferEnd;
2256 mpSavedCurBufferPtr = CurBufferPtr;
2257
2258 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2259 Alignment);
2260 BufferEnd = BufferBegin + StubSize + 1;
2261
2262 return;
2263 }
2264
2265 void startGVStub(void* Buffer, unsigned StubSize) {
2266 mpSavedBufferBegin = BufferBegin;
2267 mpSavedBufferEnd = BufferEnd;
2268 mpSavedCurBufferPtr = CurBufferPtr;
2269
2270 BufferBegin = CurBufferPtr = (uint8_t *) Buffer;
2271 BufferEnd = BufferBegin + StubSize + 1;
2272
2273 return;
2274 }
2275
2276 void finishGVStub() {
2277 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2278
2279 /* restore */
2280 BufferBegin = mpSavedBufferBegin;
2281 BufferEnd = mpSavedBufferEnd;
2282 CurBufferPtr = mpSavedCurBufferPtr;
2283
2284 return;
2285 }
2286
2287 /*
2288 * allocIndirectGV - Allocates and fills storage for an indirect
2289 * GlobalValue, and returns the address.
2290 */
2291 void* allocIndirectGV(const llvm::GlobalValue *GV,
2292 const uint8_t *Buffer, size_t Size,
2293 unsigned Alignment) {
2294 uint8_t* IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
2295 memcpy(IndGV, Buffer, Size);
2296 return IndGV;
2297 }
2298
2299 /* emitLabel - Emits a label */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002300 void emitLabel(llvm::MCSymbol *Label) {
2301 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002302 return;
2303 }
2304
2305 /*
2306 * allocateGlobal - Allocate memory for a global. Unlike allocateSpace,
2307 * this method does not allocate memory in the current output buffer,
2308 * because a global may live longer than the current function.
2309 */
2310 void* allocateGlobal(uintptr_t Size, unsigned Alignment) {
2311 /* Delegate this call through the memory manager. */
2312 return mpMemMgr->allocateGlobal(Size, Alignment);
2313 }
2314
2315 /*
2316 * StartMachineBasicBlock - This should be called by the target when a new
2317 * basic block is about to be emitted. This way the MCE knows where the
2318 * start of the block is, and can implement getMachineBasicBlockAddress.
2319 */
2320 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
2321 if(mMBBLocations.size() <= (unsigned) MBB->getNumber())
2322 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2323 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2324 return;
2325 }
2326
2327 /*
2328 * addRelocation - Whenever a relocatable address is needed, it should be
2329 * noted with this interface.
2330 */
2331 void addRelocation(const llvm::MachineRelocation &MR) {
2332 mRelocations.push_back(MR);
2333 return;
2334 }
2335
2336 /*
2337 * getConstantPoolEntryAddress - Return the address of the 'Index' entry in
2338 * the constant pool that was last emitted with
2339 * the emitConstantPool method.
2340 */
2341 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2342 assert(Index < mpConstantPool->getConstants().size() &&
2343 "Invalid constant pool index!");
2344 return mConstPoolAddresses[Index];
2345 }
2346
2347 /*
2348 * getJumpTableEntryAddress - Return the address of the jump table
2349 * with index
2350 * 'Index' in the function that last called initJumpTableInfo.
2351 */
2352 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
2353 const std::vector<llvm::MachineJumpTableEntry>& JT =
2354 mpJumpTable->getJumpTables();
2355
2356 assert(Index < JT.size() && "Invalid jump table index!");
2357
2358 unsigned int Offset = 0;
2359 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2360
2361 for(int i=0;i<Index;i++)
2362 Offset += JT[i].MBBs.size();
2363 Offset *= EntrySize;
2364
2365 return (uintptr_t)((char *) mpJumpTableBase + Offset);
2366 }
2367
2368 /*
2369 * getMachineBasicBlockAddress - Return the address of the specified
2370 * MachineBasicBlock, only usable after the label for the MBB has been
2371 * emitted.
2372 */
2373 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2374 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
2375 mMBBLocations[MBB->getNumber()] && "MBB not emitted!");
2376 return mMBBLocations[MBB->getNumber()];
2377 }
2378
2379 /*
2380 * getLabelAddress - Return the address of the specified LabelID,
2381 * only usable after the LabelID has been emitted.
2382 */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002383 uintptr_t getLabelAddress(llvm::MCSymbol* Label) const {
2384 assert(mLabelLocations.count(Label) && "Label not emitted!");
2385 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002386 }
2387
2388 /*
2389 * Specifies the MachineModuleInfo object.
2390 * This is used for exception handling
2391 * purposes.
2392 */
2393 void setModuleInfo(llvm::MachineModuleInfo* Info) {
2394 mpMMI = Info;
2395 return;
2396 }
2397
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002398 void updateFunctionStub(const llvm::Function* F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002399 /* Get the empty stub we generated earlier. */
2400 void* Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002401 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002402 if(I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002403 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002404 else
2405 return;
2406
2407 void* Addr = GetPointerToGlobalIfAvailable(F);
2408
2409 assert(Addr != Stub &&
2410 "Function must have non-stub address to be updated.");
2411
2412 /*
2413 * Tell the target jit info to rewrite the stub at the specified address,
2414 * rather than creating a new one.
2415 */
2416 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2417 startGVStub(Stub, SL.Size);
2418 mpTJI->emitFunctionStub(F, Addr, *this);
2419 finishGVStub();
2420
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002421 Disassemble(F->getName(), (uint8_t*) Stub, SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002422
2423 PendingFunctions.erase(I);
2424
2425 return;
2426 }
2427
2428 /*
2429 * Once you finish the compilation on a translation unit,
2430 * you can call this function to recycle the memory
2431 * (which is used at compilation time and not needed for runtime).
2432 *
2433 * NOTE: You should not call this funtion until the code-gen passes
2434 * for a given module is done.
2435 * Otherwise, the results is undefined and may cause the system crash!
2436 */
2437 void releaseUnnecessary() {
2438 mMBBLocations.clear();
2439 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002440 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002441 mFunctionToLazyStubMap.clear();
2442 GlobalToIndirectSymMap.clear();
2443 ExternalFnToStubMap.clear();
2444 PendingFunctions.clear();
2445
2446 return;
2447 }
2448
2449 void reset() {
2450 releaseUnnecessary();
2451
2452 mpSymbolLookupFn = NULL;
2453 mpSymbolLookupContext = NULL;
2454
2455 mpTJI = NULL;
2456 mpTD = NULL;
2457
2458 for(EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin();
2459 I != mEmittedFunctions.end();
2460 I++)
2461 if(I->second != NULL)
2462 delete I->second;
2463 mEmittedFunctions.clear();
2464
2465 mpMemMgr->reset();
2466
2467 return;
2468 }
2469
2470 void* lookup(const char* Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002471 return lookup( llvm::StringRef(Name) );
2472 }
2473
2474 void* lookup(const llvm::StringRef& Name) {
2475 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(Name.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002476 if(I == mEmittedFunctions.end())
2477 return NULL;
2478 else
2479 return I->second->Code;
2480 }
2481
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002482 void getFunctionNames(BCCsizei* actualFunctionCount,
2483 BCCsizei maxFunctionCount,
2484 BCCchar** functions) {
2485 int functionCount = mEmittedFunctions.size();
2486
2487 if(actualFunctionCount)
2488 *actualFunctionCount = functionCount;
2489 if(functionCount > maxFunctionCount)
2490 functionCount = maxFunctionCount;
2491 if(functions)
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002492 for(EmittedFunctionsMapTy::const_iterator it =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002493 mEmittedFunctions.begin();
2494 functionCount > 0;
2495 functionCount--, it++)
2496 *functions++ = (BCCchar*) it->first.c_str();
2497
2498 return;
2499 }
2500
2501 void getFunctionBinary(BCCchar* label,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002502 BCCvoid** base,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002503 BCCsizei* length) {
2504 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002505 if(I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002506 *base = NULL;
2507 *length = 0;
2508 } else {
2509 *base = I->second->Code;
2510 *length = I->second->Size;
2511 }
2512 return;
2513 }
2514
2515 ~CodeEmitter() {
2516 if(mpMemMgr)
2517 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002518#if defined(USE_DISASSEMBLER)
2519 if(mpAsmInfo)
2520 delete mpAsmInfo;
2521 if(mpDisassmbler)
2522 delete mpDisassmbler;
2523 if(mpIP)
2524 delete mpIP;
2525#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002526 return;
2527 }
2528 /* }}} */
2529 }; /* End of Class CodeEmitter */
2530
2531 /* The CodeEmitter */
2532 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
2533 CodeEmitter* createCodeEmitter() {
2534 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2535 return mCodeEmitter.get();
2536 }
2537
2538 BCCSymbolLookupFn mpSymbolLookupFn;
2539 void* mpSymbolLookupContext;
2540
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002541 llvm::LLVMContext* mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002542 llvm::Module* mModule;
2543
2544 bool mTypeInformationPrepared;
2545 std::vector<const llvm::Type*> mTypes;
2546
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002547 public:
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002548 Compiler() :
2549 mpSymbolLookupFn(NULL),
2550 mpSymbolLookupContext(NULL),
2551 mContext(NULL),
2552 mModule(NULL)
2553 {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002554 llvm::remove_fatal_error_handler();
2555 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002556 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002557 return;
2558 }
2559
2560 /* interface for BCCscript::registerSymbolCallback() */
2561 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid* pContext) {
2562 mpSymbolLookupFn = pFn;
2563 mpSymbolLookupContext = pContext;
2564 return;
2565 }
2566
2567 int loadModule(const char* bitcode, size_t bitcodeSize) {
2568 llvm::MemoryBuffer* SB = NULL;
2569
2570 if(bitcode == NULL || bitcodeSize <= 0)
2571 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002572
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002573 GlobalInitialization();
2574
2575 /* Package input to object MemoryBuffer */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002576 SB = llvm::MemoryBuffer::getMemBuffer(
2577 llvm::StringRef(bitcode, bitcodeSize));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002578 if(SB == NULL) {
2579 setError("Error reading input Bitcode into memory");
2580 goto on_bcc_load_module_error;
2581 }
2582
2583 /* Read the input Bitcode as a Module */
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002584 mModule = llvm::ParseBitcodeFile(SB, *mContext, &mError);
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002585
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002586on_bcc_load_module_error:
2587 if (SB)
2588 delete SB;
2589
2590 return hasError();
2591 }
2592
2593 /* interace for bccCompileScript() */
2594 int compile() {
2595 llvm::TargetData* TD = NULL;
2596
2597 llvm::TargetMachine* TM = NULL;
2598 const llvm::Target* Target;
2599 std::string FeaturesStr;
2600
2601 llvm::FunctionPassManager* CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002602
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002603 const llvm::NamedMDNode* PragmaMetadata;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002604 const llvm::NamedMDNode* ExportVarMetadata;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002605 const llvm::NamedMDNode* ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002606
2607 if(mModule == NULL) /* No module was loaded */
2608 return 0;
2609
2610 /* Create TargetMachine */
2611 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
2612 if(hasError())
2613 goto on_bcc_compile_error;
2614
2615 if(!CPU.empty() || !Features.empty()) {
2616 llvm::SubtargetFeatures F;
2617 F.setCPU(CPU);
2618 for(std::vector<std::string>::const_iterator it = Features.begin();
2619 it != Features.end();
2620 it++)
2621 F.AddFeature(*it);
2622 FeaturesStr = F.getString();
2623 }
2624
2625 TM = Target->createTargetMachine(Triple, FeaturesStr);
2626 if(TM == NULL) {
2627 setError("Failed to create target machine implementation for the"
2628 " specified triple '" + Triple + "'");
2629 goto on_bcc_compile_error;
2630 }
2631
2632 /* Create memory manager for creation of code emitter later */
2633 if(!mCodeMemMgr.get() && !createCodeMemoryManager()) {
2634 setError("Failed to startup memory management for further compilation");
2635 goto on_bcc_compile_error;
2636 }
2637
2638 /* Create code emitter */
2639 if(!mCodeEmitter.get()) {
2640 if(!createCodeEmitter()) {
2641 setError("Failed to create machine code emitter to complete"
2642 " the compilation");
2643 goto on_bcc_compile_error;
2644 }
2645 } else {
2646 /* reuse the code emitter */
2647 mCodeEmitter->reset();
2648 }
2649
2650 mCodeEmitter->setTargetMachine(*TM);
2651 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2652 mpSymbolLookupContext);
2653
2654 /* Get target data from Module */
2655 TD = new llvm::TargetData(mModule);
2656 /* Create code-gen pass to run the code emitter */
2657 CodeGenPasses = new llvm::FunctionPassManager(mModule);
2658 CodeGenPasses->add(TD); // Will take the ownership of TD
2659
2660 if(TM->addPassesToEmitMachineCode(*CodeGenPasses,
2661 *mCodeEmitter, CodeGenOptLevel)) {
2662 setError("The machine code emission is not supported by BCC on target '"
2663 + Triple + "'");
2664 goto on_bcc_compile_error;
2665 }
2666
2667 /*
2668 * Run the pass (the code emitter) on every non-declaration function
2669 * in the module
2670 */
2671 CodeGenPasses->doInitialization();
2672 for(llvm::Module::iterator I = mModule->begin();
2673 I != mModule->end();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002674 I++)
2675 if(!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002676 CodeGenPasses->run(*I);
2677
2678 CodeGenPasses->doFinalization();
2679
2680 /* Copy the global address mapping from code emitter and remapping */
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002681 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
2682 if(ExportVarMetadata) {
2683 for(int i=0;i<ExportVarMetadata->getNumOperands();i++) {
2684 llvm::MDNode* ExportVar = ExportVarMetadata->getOperand(i);
2685 if(ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2686 llvm::Value* ExportVarNameMDS = ExportVar->getOperand(0);
2687 if(ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
2688 llvm::StringRef ExportVarName =
2689 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
2690 CodeEmitter::global_addresses_const_iterator I;
2691 for(I = mCodeEmitter->global_address_begin();
2692 I != mCodeEmitter->global_address_end();
2693 I++)
2694 {
2695 if(I->first->getValueID() != llvm::Value::GlobalVariableVal)
2696 continue;
2697 if(ExportVarName == I->first->getName()) {
2698 mExportVars.push_back(I->second);
2699 break;
2700 }
2701 }
2702 if(I != mCodeEmitter->global_address_end())
2703 continue; // found
2704 }
2705 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002706 // if here, the global variable record in metadata is not
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002707 // found, make an empty slot
2708 mExportVars.push_back(NULL);
2709 }
2710 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
2711 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002712 }
2713
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002714 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
2715 if(ExportFuncMetadata) {
2716 for(int i=0;i<ExportFuncMetadata->getNumOperands();i++) {
2717 llvm::MDNode* ExportFunc = ExportFuncMetadata->getOperand(i);
2718 if(ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2719 llvm::Value* ExportFuncNameMDS = ExportFunc->getOperand(0);
2720 if(ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
2721 llvm::StringRef ExportFuncName =
2722 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2723 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
2724 }
2725 }
2726 }
2727 }
2728
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002729 /*
2730 * Tell code emitter now can release the memory using
2731 * during the JIT since we have done the code emission
2732 */
2733 mCodeEmitter->releaseUnnecessary();
2734
2735 /*
2736 * Finally, read pragma information from the metadata node
2737 * of the @Module if any
2738 */
2739 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
2740 if(PragmaMetadata)
2741 for(int i=0;i<PragmaMetadata->getNumOperands();i++) {
2742 llvm::MDNode* Pragma = PragmaMetadata->getOperand(i);
2743 if(Pragma != NULL &&
2744 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
2745 llvm::Value* PragmaNameMDS = Pragma->getOperand(0);
2746 llvm::Value* PragmaValueMDS = Pragma->getOperand(1);
2747
2748 if((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
2749 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
2750 llvm::StringRef PragmaName =
2751 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
2752 llvm::StringRef PragmaValue =
2753 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
2754
2755 mPragmas.push_back( make_pair( std::string(PragmaName.data(),
2756 PragmaName.size()),
2757 std::string(PragmaValue.data(),
2758 PragmaValue.size())
2759 )
2760 );
2761 }
2762 }
2763 }
2764
2765 on_bcc_compile_error:
2766 if (CodeGenPasses) {
2767 delete CodeGenPasses;
2768 } else if (TD) {
2769 delete TD;
2770 }
2771 if (TM)
2772 delete TM;
2773
2774 return hasError();
2775 }
2776
2777 /* interface for bccGetScriptInfoLog() */
2778 char* getErrorMessage() {
2779 return const_cast<char*>(mError.c_str());
2780 }
2781
2782 /* interface for bccGetScriptLabel() */
2783 void* lookup(const char* name) {
2784 void* addr = NULL;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002785 if(mCodeEmitter.get())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002786 /* Find function pointer */
2787 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002788 return addr;
2789 }
2790
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002791 /* Interface for bccGetExportVars() */
2792 void getExportVars(BCCsizei* actualVarCount,
2793 BCCsizei maxVarCount,
2794 BCCvoid** vars) {
2795 int varCount = mExportVars.size();
2796
2797 if(actualVarCount)
2798 *actualVarCount = varCount;
2799 if(varCount > maxVarCount)
2800 varCount = maxVarCount;
2801 if(vars)
2802 for(ExportVarList::const_iterator it = mExportVars.begin();
2803 it != mExportVars.end();
2804 it++)
2805 {
2806 *vars++ = *it;
2807 }
2808
2809 return;
2810 }
2811
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002812 /* Interface for bccGetExportFuncs() */
2813 void getExportFuncs(BCCsizei* actualFuncCount,
2814 BCCsizei maxFuncCount,
2815 BCCvoid** funcs) {
2816 int funcCount = mExportFuncs.size();
2817
2818 if(actualFuncCount)
2819 *actualFuncCount = funcCount;
2820 if(funcCount > maxFuncCount)
2821 funcCount = maxFuncCount;
2822 if(funcs)
2823 for(ExportFuncList::const_iterator it = mExportFuncs.begin();
2824 it != mExportFuncs.end();
2825 it++)
2826 {
2827 *funcs++ = *it;
2828 }
2829
2830 return;
2831 }
2832
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002833 /* Interface for bccGetPragmas() */
2834 void getPragmas(BCCsizei* actualStringCount,
2835 BCCsizei maxStringCount,
2836 BCCchar** strings) {
2837 int stringCount = mPragmas.size() * 2;
2838
2839 if(actualStringCount)
2840 *actualStringCount = stringCount;
2841 if(stringCount > maxStringCount)
2842 stringCount = maxStringCount;
2843 if(strings)
2844 for(PragmaList::const_iterator it = mPragmas.begin();
2845 stringCount > 0;
2846 stringCount-=2, it++)
2847 {
2848 *strings++ = (BCCchar*) it->first.c_str();
2849 *strings++ = (BCCchar*) it->second.c_str();
2850 }
2851
2852 return;
2853 }
2854
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002855 /* Interface for bccGetFunctions() */
2856 void getFunctions(BCCsizei* actualFunctionCount,
2857 BCCsizei maxFunctionCount,
2858 BCCchar** functions) {
2859 if(mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002860 mCodeEmitter->getFunctionNames(actualFunctionCount,
2861 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002862 functions);
2863 else
2864 *actualFunctionCount = 0;
2865
2866 return;
2867 }
2868
2869 /* Interface for bccGetFunctionBinary() */
2870 void getFunctionBinary(BCCchar* function,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002871 BCCvoid** base,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002872 BCCsizei* length) {
2873 if(mCodeEmitter.get()) {
2874 mCodeEmitter->getFunctionBinary(function, base, length);
2875 } else {
2876 *base = NULL;
2877 *length = 0;
2878 }
2879 return;
2880 }
2881
2882 inline const llvm::Module* getModule() const {
2883 return mModule;
2884 }
2885
2886 inline const std::vector<const llvm::Type*>& getTypes() const {
2887 return mTypes;
2888 }
2889
2890 ~Compiler() {
2891 delete mModule;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -07002892 //llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002893 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002894 return;
2895 }
2896}; /* End of Class Compiler */
2897
2898bool Compiler::GlobalInitialized = false;
2899
2900/* Code generation optimization level for the compiler */
2901llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
2902
2903std::string Compiler::Triple;
2904
2905std::string Compiler::CPU;
2906
2907std::vector<std::string> Compiler::Features;
2908
2909/*
2910 * The named of metadata node that pragma resides
2911 * (should be synced with slang.cpp)
2912 */
2913const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
2914
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002915/*
2916 * The named of metadata node that export variable name resides
2917 * (should be synced with slang.cpp)
2918 */
2919const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
2920
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002921/*
2922 * The named of metadata node that export function name resides
2923 * (should be synced with slang.cpp)
2924 */
2925const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
2926
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002927struct BCCscript {
2928 /*
2929 * Part I. Compiler
2930 */
2931
2932 Compiler compiler;
2933
2934 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid* pContext) {
2935 compiler.registerSymbolCallback(pFn, pContext);
2936 }
2937
2938 /*
2939 * Part II. Logistics & Error handling
2940 */
2941
2942 BCCscript() {
2943 bccError = BCC_NO_ERROR;
2944 }
2945
2946 ~BCCscript() {
2947 }
2948
2949 void setError(BCCenum error) {
2950 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
2951 bccError = error;
2952 }
2953 }
2954
2955 BCCenum getError() {
2956 BCCenum result = bccError;
2957 bccError = BCC_NO_ERROR;
2958 return result;
2959 }
2960
2961 BCCenum bccError;
2962};
2963
2964
2965extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002966BCCscript* bccCreateScript()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002967{
2968 return new BCCscript();
2969}
2970
2971extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002972BCCenum bccGetError( BCCscript* script )
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002973{
2974 return script->getError();
2975}
2976
2977extern "C"
2978void bccDeleteScript(BCCscript* script) {
2979 delete script;
2980}
2981
2982extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002983void bccRegisterSymbolCallback(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002984 BCCSymbolLookupFn pFn,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002985 BCCvoid* pContext)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002986{
2987 script->registerSymbolCallback(pFn, pContext);
2988}
2989
2990extern "C"
2991void bccScriptBitcode(BCCscript* script,
2992 const BCCchar* bitcode,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002993 BCCint size)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002994{
2995 script->compiler.loadModule(bitcode, size);
2996}
2997
2998extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002999void bccCompileScript(BCCscript* script)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003000{
3001 int result = script->compiler.compile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003002 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003003 script->setError(BCC_INVALID_OPERATION);
3004}
3005
3006extern "C"
3007void bccGetScriptInfoLog(BCCscript* script,
3008 BCCsizei maxLength,
3009 BCCsizei* length,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003010 BCCchar* infoLog)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003011{
3012 char* message = script->compiler.getErrorMessage();
3013 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003014 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003015 *length = messageLength;
3016
3017 if (infoLog && maxLength > 0) {
3018 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
3019 memcpy(infoLog, message, trimmedLength);
3020 infoLog[trimmedLength] = 0;
3021 }
3022}
3023
3024extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003025void bccGetScriptLabel(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003026 const BCCchar * name,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003027 BCCvoid ** address)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003028{
3029 void* value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003030 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003031 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003032 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003033 script->setError(BCC_INVALID_VALUE);
3034}
3035
3036extern "C"
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07003037void bccGetExportVars(BCCscript* script,
3038 BCCsizei* actualVarCount,
3039 BCCsizei maxVarCount,
3040 BCCvoid** vars)
3041{
3042 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
3043}
3044
3045extern "C"
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07003046void bccGetExportFuncs(BCCscript* script,
3047 BCCsizei* actualFuncCount,
3048 BCCsizei maxFuncCount,
3049 BCCvoid** funcs)
3050{
3051 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
3052}
3053
3054extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003055void bccGetPragmas(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003056 BCCsizei* actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003057 BCCsizei maxStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003058 BCCchar** strings)
3059{
3060 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
3061}
3062
3063extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003064void bccGetFunctions(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003065 BCCsizei* actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003066 BCCsizei maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003067 BCCchar** functions)
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003068{
3069 script->compiler.getFunctions(actualFunctionCount,
3070 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003071 functions);
3072}
3073
3074extern "C"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003075void bccGetFunctionBinary(BCCscript* script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003076 BCCchar* function,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07003077 BCCvoid** base,
3078 BCCsizei* length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003079{
3080 script->compiler.getFunctionBinary(function, base, length);
3081}
3082
3083struct BCCtype {
3084 const Compiler* compiler;
3085 const llvm::Type* t;
3086};
3087
3088} /* End of namespace bcc */