blob: 9d5bc3cf0193da8808d2806bd4f11ea3cfe72a29 [file] [log] [blame]
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001/*
Zonr Chang932648d2010-10-13 22:23:56 +08002 * Copyright 2010, The Android Open Source Project
Shih-wei Liao77ed6142010-04-07 12:21:42 -07003 *
Zonr Chang932648d2010-10-13 22:23:56 +08004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Shih-wei Liao77ed6142010-04-07 12:21:42 -070015 */
16
Zonr Chang932648d2010-10-13 22:23:56 +080017// Bitcode compiler (bcc) for Android:
18// This is an eager-compilation JIT running on Android.
19
Shih-wei Liao77ed6142010-04-07 12:21:42 -070020#define LOG_TAG "bcc"
21#include <cutils/log.h>
22
23#include <ctype.h>
24#include <errno.h>
25#include <limits.h>
26#include <stdarg.h>
27#include <stdint.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -070032#include <sys/mman.h>
Shih-wei Liao77ed6142010-04-07 12:21:42 -070033
34#include <cutils/hashmap.h>
35
Shih-wei Liao77ed6142010-04-07 12:21:42 -070036#if defined(__arm__)
Zonr Chang932648d2010-10-13 22:23:56 +080037# define DEFAULT_ARM_CODEGEN
38# define PROVIDE_ARM_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070039#elif defined(__i386__)
Zonr Chang932648d2010-10-13 22:23:56 +080040# define DEFAULT_X86_CODEGEN
41# define PROVIDE_X86_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070042#elif defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +080043# define DEFAULT_X64_CODEGEN
44# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070045#endif
46
47#if defined(FORCE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080048# define DEFAULT_ARM_CODEGEN
49# undef DEFAULT_X86_CODEGEN
50# undef DEFAULT_X64_CODEGEN
51# define PROVIDE_ARM_CODEGEN
52# undef PROVIDE_X86_CODEGEN
53# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070054#elif defined(FORCE_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080055# undef DEFAULT_ARM_CODEGEN
56# define DEFAULT_X86_CODEGEN
57# undef DEFAULT_X64_CODEGEN
58# undef PROVIDE_ARM_CODEGEN
59# define PROVIDE_X86_CODEGEN
60# undef PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070061#elif defined(FORCE_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080062# undef DEFAULT_ARM_CODEGEN
63# undef DEFAULT_X86_CODEGEN
64# define DEFAULT_X64_CODEGEN
65# undef PROVIDE_ARM_CODEGEN
66# undef PROVIDE_X86_CODEGEN
67# define PROVIDE_X64_CODEGEN
Shih-wei Liao77ed6142010-04-07 12:21:42 -070068#endif
69
70#if defined(DEFAULT_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080071# define TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070072#elif defined(DEFAULT_X86_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080073# define TARGET_TRIPLE_STRING "i686-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070074#elif defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +080075# define TARGET_TRIPLE_STRING "x86_64-unknown-linux"
Shih-wei Liao77ed6142010-04-07 12:21:42 -070076#endif
77
78#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
Zonr Chang932648d2010-10-13 22:23:56 +080079# define ARM_USE_VFP
Shih-wei Liao77ed6142010-04-07 12:21:42 -070080#endif
81
82#include <bcc/bcc.h>
83#include "bcc_runtime.h"
84
Zonr Chang932648d2010-10-13 22:23:56 +080085#define LOG_API(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070086// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
87
Zonr Chang932648d2010-10-13 22:23:56 +080088#define LOG_STACK(...) do {} while (0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070089// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
90
91// #define PROVIDE_TRACE_CODEGEN
92
93#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +080094# include "llvm/MC/MCInst.h"
95# include "llvm/MC/MCAsmInfo.h"
96# include "llvm/MC/MCInstPrinter.h"
97# include "llvm/MC/MCDisassembler.h"
Shih-wei Liao3cf39d12010-04-29 19:30:51 -070098// If you want the disassemble results written to file, define this:
99# define USE_DISASSEMBLER_FILE
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700100#endif
101
102#include <set>
103#include <map>
104#include <list>
105#include <cmath>
106#include <string>
107#include <cstring>
Zonr Chang932648d2010-10-13 22:23:56 +0800108#include <algorithm> // for std::reverse
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700109
Zonr Chang932648d2010-10-13 22:23:56 +0800110// VMCore
111#include "llvm/Use.h"
112#include "llvm/User.h"
113#include "llvm/Module.h"
114#include "llvm/Function.h"
115#include "llvm/Constant.h"
116#include "llvm/Constants.h"
117#include "llvm/Instruction.h"
118#include "llvm/PassManager.h"
119#include "llvm/LLVMContext.h"
120#include "llvm/GlobalValue.h"
121#include "llvm/Instructions.h"
122#include "llvm/OperandTraits.h"
123#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700124
125// System
Zonr Chang932648d2010-10-13 22:23:56 +0800126#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700127
128// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800129#include "llvm/ADT/APInt.h"
130#include "llvm/ADT/APFloat.h"
131#include "llvm/ADT/DenseMap.h"
132#include "llvm/ADT/ValueMap.h"
133#include "llvm/ADT/StringMap.h"
134#include "llvm/ADT/OwningPtr.h"
135#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700136
137// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800138#include "llvm/Target/TargetData.h"
139#include "llvm/Target/TargetSelect.h"
140#include "llvm/Target/TargetOptions.h"
141#include "llvm/Target/TargetMachine.h"
142#include "llvm/Target/TargetJITInfo.h"
143#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700144#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700145
146// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800147#include "llvm/Support/Casting.h"
148#include "llvm/Support/raw_ostream.h"
149#include "llvm/Support/ValueHandle.h"
150#include "llvm/Support/MemoryBuffer.h"
151#include "llvm/Support/MemoryObject.h"
152#include "llvm/Support/ManagedStatic.h"
153#include "llvm/Support/ErrorHandling.h"
154#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700155#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700156
157// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800158#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700159
160// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800161#include "llvm/CodeGen/Passes.h"
162#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700163#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700164#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700165#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700166#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700167#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700168#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700169#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700170#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700171
172// ExecutionEngine
173#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700174#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700175
176
Zonr Chang932648d2010-10-13 22:23:56 +0800177//
178// Compilation class that suits Android's needs.
179// (Support: no argument passed, ...)
180//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700181namespace bcc {
182
183class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800184 // This part is designed to be orthogonal to those exported bcc*() functions
185 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700186
Zonr Chang932648d2010-10-13 22:23:56 +0800187 //////////////////////////////////////////////////////////////////////////////
188 // The variable section below (e.g., Triple, CodeGenOptLevel)
189 // is initialized in GlobalInitialization()
190 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700191 static bool GlobalInitialized;
192
Zonr Chang932648d2010-10-13 22:23:56 +0800193 // If given, this will be the name of the target triple to compile for.
194 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700195 static std::string Triple;
196
197 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700198
Zonr Chang932648d2010-10-13 22:23:56 +0800199 // End of section of GlobalInitializing variables
200 //////////////////////////////////////////////////////////////////////////////
201
202 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700203 static std::string CPU;
204
Zonr Chang932648d2010-10-13 22:23:56 +0800205 // The list of target specific features to enable or disable -- this should
206 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700207 static std::vector<std::string> Features;
208
209 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800210 const char *mName;
211 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700212 };
213 static struct Runtime Runtimes[];
214
215 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800216 if (GlobalInitialized)
217 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700218
Zonr Chang932648d2010-10-13 22:23:56 +0800219 // if (!llvm::llvm_is_multithreaded())
220 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700221
Zonr Chang932648d2010-10-13 22:23:56 +0800222 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700223 Triple = TARGET_TRIPLE_STRING;
224
Zonr Chang932648d2010-10-13 22:23:56 +0800225 // TODO(zonr): NEON for JIT
226 // Features.push_back("+neon");
227 // Features.push_back("+vmlx");
228 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700229 Features.push_back("+vfp3");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700230
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700231#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
232 LLVMInitializeARMTargetInfo();
233 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700234#if defined(USE_DISASSEMBLER)
235 LLVMInitializeARMDisassembler();
236 LLVMInitializeARMAsmPrinter();
237#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700238#endif
239
240#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
241 LLVMInitializeX86TargetInfo();
242 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700243#if defined(USE_DISASSEMBLER)
244 LLVMInitializeX86Disassembler();
245 LLVMInitializeX86AsmPrinter();
246#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700247#endif
248
249#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
250 LLVMInitializeX86TargetInfo();
251 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700252#if defined(USE_DISASSEMBLER)
253 LLVMInitializeX86Disassembler();
254 LLVMInitializeX86AsmPrinter();
255#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700256#endif
257
Zonr Chang932648d2010-10-13 22:23:56 +0800258 // -O0: llvm::CodeGenOpt::None
259 // -O1: llvm::CodeGenOpt::Less
260 // -O2: llvm::CodeGenOpt::Default
261 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700262 CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
263
Zonr Chang932648d2010-10-13 22:23:56 +0800264 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700265
Zonr Chang932648d2010-10-13 22:23:56 +0800266 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700267 llvm::NoFramePointerElim = false;
268
Zonr Chang932648d2010-10-13 22:23:56 +0800269 // Use hardfloat ABI
270 //
271 // FIXME: Need to detect the CPU capability and decide whether to use
272 // softfp. To use softfp, change following 2 lines to
273 //
274 // llvm::FloatABIType = llvm::FloatABI::Soft;
275 // llvm::UseSoftFloat = true;
276 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700277 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700278 llvm::UseSoftFloat = false;
279
Zonr Chang932648d2010-10-13 22:23:56 +0800280 // BCC needs all unknown symbols resolved at JIT/compilation time.
281 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700282 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
283
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700284#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800285 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700286 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
287#else
Zonr Chang932648d2010-10-13 22:23:56 +0800288 // This is set for the linker (specify how large of the virtual addresses
289 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700290 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
291#endif
292
Zonr Chang932648d2010-10-13 22:23:56 +0800293 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700294 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
295
Zonr Chang932648d2010-10-13 22:23:56 +0800296 // Register allocation policy:
297 // createFastRegisterAllocator: fast but bad quality
298 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700299 llvm::RegisterRegAlloc::setDefault
300 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700301 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700302 llvm::createLinearScanRegisterAllocator);
303
304 GlobalInitialized = true;
305 return;
306 }
307
308 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800309 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700310 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700311 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800312 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700313 }
314
315 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700316 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700317 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700318
319 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700320 std::string mError;
321
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700322 inline bool hasError() const {
323 return !mError.empty();
324 }
Zonr Chang932648d2010-10-13 22:23:56 +0800325 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700326 mError.assign(Error); // Copying
327 return;
328 }
Zonr Chang932648d2010-10-13 22:23:56 +0800329 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700330 mError = Error;
331 return;
332 }
333
334 typedef std::list< std::pair<std::string, std::string> > PragmaList;
335 PragmaList mPragmas;
336
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700337 typedef std::list<void*> ExportVarList;
338 ExportVarList mExportVars;
339
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700340 typedef std::list<void*> ExportFuncList;
341 ExportFuncList mExportFuncs;
342
Zonr Chang932648d2010-10-13 22:23:56 +0800343 //////////////////////////////////////////////////////////////////////////////
344 // Memory manager for the code reside in memory
345 //
346 // The memory for our code emitter is very simple and is conforming to the
347 // design decisions of Android RenderScript's Exection Environment:
348 // The code, data, and symbol sizes are limited (currently 100KB.)
349 //
350 // It's very different from typical compiler, which has no limitation
351 // on the code size. How does code emitter know the size of the code
352 // it is about to emit? It does not know beforehand. We want to solve
353 // this without complicating the code emitter too much.
354 //
355 // We solve this by pre-allocating a certain amount of memory,
356 // and then start the code emission. Once the buffer overflows, the emitter
357 // simply discards all the subsequent emission but still has a counter
358 // on how many bytes have been emitted.
359 //
360 // So once the whole emission is done, if there's a buffer overflow,
361 // it re-allocates the buffer with enough size (based on the
362 // counter from previous emission) and re-emit again.
363 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700364 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700365 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800366 // 128 KiB for code
367 static const unsigned int MaxCodeSize = 128 * 1024;
368 // 1 KiB for global offset table (GOT)
369 static const unsigned int MaxGOTSize = 1 * 1024;
370 // 128 KiB for global variable
371 static const unsigned int MaxGlobalVarSize = 128 * 1024;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700372
Zonr Chang932648d2010-10-13 22:23:56 +0800373 //
374 // Our memory layout is as follows:
375 //
376 // The direction of arrows (-> and <-) shows memory's growth direction
377 // when more space is needed.
378 //
379 // @mpCodeMem:
380 // +--------------------------------------------------------------+
381 // | Function Memory ... -> <- ... Stub/GOT |
382 // +--------------------------------------------------------------+
383 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
384 //
385 // Where size of GOT is @MaxGOTSize KiB.
386 //
387 // @mpGVMem:
388 // +--------------------------------------------------------------+
389 // | Global variable ... -> |
390 // +--------------------------------------------------------------+
391 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
392 //
393 //
394 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
395 // of function code's memory usage
396 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
397 // of stub/GOT's memory usage
398 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
399 // of global variable's memory usage
400 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700401 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700402 uintptr_t mCurSGMemIdx;
403 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800404 void *mpCodeMem;
405 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700406
Zonr Chang932648d2010-10-13 22:23:56 +0800407 // GOT Base
408 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700409
410 typedef std::map<const llvm::Function*, pair<void* /* start address */,
411 void* /* end address */>
412 > FunctionMapTy;
413 FunctionMapTy mFunctionMap;
414
Zonr Chang932648d2010-10-13 22:23:56 +0800415 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700416 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700417 }
Zonr Chang932648d2010-10-13 22:23:56 +0800418 inline uint8_t *getCodeMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700419 return reinterpret_cast<uint8_t*>(mpCodeMem);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700420 }
421
Zonr Chang932648d2010-10-13 22:23:56 +0800422 uint8_t *allocateSGMemory(uintptr_t Size,
423 unsigned Alignment = 1 /* no alignment */) {
424 intptr_t FreeMemSize = getFreeCodeMemSize();
425 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
426 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700427 return NULL;
428
Zonr Chang932648d2010-10-13 22:23:56 +0800429 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700430 Alignment = 1;
431
Zonr Chang932648d2010-10-13 22:23:56 +0800432 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700433 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
434
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700435 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700436
437 return result;
438 }
439
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700440 inline uintptr_t getFreeGVMemSize() const {
441 return MaxGlobalVarSize - mCurGVMemIdx;
442 }
Zonr Chang932648d2010-10-13 22:23:56 +0800443 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700444 return reinterpret_cast<uint8_t*>(mpGVMem);
445 }
446
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700447 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700448 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700449 reset();
450 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700451
Shih-wei Liaoc7c9cd52010-09-27 11:23:25 -0700452 mpCodeMem = ::mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700453 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700454 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800455 llvm::report_fatal_error("Failed to allocate memory for emitting "
456 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700457
458 mpGVMem = ::mmap(mpCodeMem, MaxGlobalVarSize,
Shih-wei Liaoc7c9cd52010-09-27 11:23:25 -0700459 PROT_READ | PROT_WRITE,
Ying Wang78db12e2010-09-25 17:48:59 -0700460 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700461 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800462 llvm::report_fatal_error("Failed to allocate memory for emitting "
463 "global variables\n" + ErrMsg);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700464
465 return;
466 }
467
Zonr Chang932648d2010-10-13 22:23:56 +0800468 // setMemoryWritable - When code generation is in progress, the code pages
469 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700470 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700471 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700472 return;
473 }
474
Zonr Chang932648d2010-10-13 22:23:56 +0800475 // When code generation is done and we're ready to start execution, the
476 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700477 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700478 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700479 return;
480 }
481
Zonr Chang932648d2010-10-13 22:23:56 +0800482 // Setting this flag to true makes the memory manager garbage values over
483 // freed memory. This is useful for testing and debugging, and is to be
484 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700485 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800486 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700487 return;
488 }
489
Zonr Chang932648d2010-10-13 22:23:56 +0800490 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700491
Zonr Chang932648d2010-10-13 22:23:56 +0800492 // If the current table requires a Global Offset Table, this method is
493 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700494 void AllocateGOT() {
495 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700496 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700497 HasGOT = true;
498 return;
499 }
500
Zonr Chang932648d2010-10-13 22:23:56 +0800501 // If this is managing a Global Offset Table, this method should return a
502 // pointer to its base.
503 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700504 return mpGOTBase;
505 }
506
Zonr Chang932648d2010-10-13 22:23:56 +0800507 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700508
Zonr Chang932648d2010-10-13 22:23:56 +0800509 // When we start JITing a function, the JIT calls this method to allocate a
510 // block of free RWX memory, which returns a pointer to it. If the JIT wants
511 // to request a block of memory of at least a certain size, it passes that
512 // value as ActualSize, and this method returns a block with at least that
513 // much space. If the JIT doesn't know ahead of time how much space it will
514 // need to emit the function, it passes 0 for the ActualSize. In either
515 // case, this method is required to pass back the size of the allocated
516 // block through ActualSize. The JIT will be careful to not write more than
517 // the returned ActualSize bytes of memory.
518 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
519 intptr_t FreeMemSize = getFreeCodeMemSize();
520 if ((FreeMemSize < 0) ||
521 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
522 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700523 return NULL;
524
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700525 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700526 return (getCodeMemBase() + mCurFuncMemIdx);
527 }
528
Zonr Chang932648d2010-10-13 22:23:56 +0800529 // This method is called by the JIT to allocate space for a function stub
530 // (used to handle limited branch displacements) while it is JIT compiling a
531 // function. For example, if foo calls bar, and if bar either needs to be
532 // lazily compiled or is a native function that exists too far away from the
533 // call site to work, this method will be used to make a thunk for it. The
534 // stub should be "close" to the current function body, but should not be
535 // included in the 'actualsize' returned by startFunctionBody.
536 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700537 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700538 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700539 }
540
Zonr Chang932648d2010-10-13 22:23:56 +0800541 // This method is called when the JIT is done codegen'ing the specified
542 // function. At this point we know the size of the JIT compiled function.
543 // This passes in FunctionStart (which was returned by the startFunctionBody
544 // method) and FunctionEnd which is a pointer to the actual end of the
545 // function. This method should mark the space allocated and remember where
546 // it is in case the client wants to deallocate it.
547 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
548 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700549 assert(FunctionEnd > FunctionStart);
550 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
551 "Mismatched function start/end!");
552
Zonr Chang932648d2010-10-13 22:23:56 +0800553 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700554 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700555 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700556 "Code size excess the limitation!");
557 mCurFuncMemIdx += FunctionCodeSize;
558
Zonr Chang932648d2010-10-13 22:23:56 +0800559 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700560 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
561 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800562 mFunctionMap.insert(
563 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
564 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700565
566 return;
567 }
568
Zonr Chang932648d2010-10-13 22:23:56 +0800569 // Allocate a (function code) memory block of the given size. This method
570 // cannot be called between calls to startFunctionBody and endFunctionBody.
571 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
572 if (getFreeCodeMemSize() < Size)
573 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700574 return NULL;
575
Zonr Chang932648d2010-10-13 22:23:56 +0800576 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700577 Alignment = 1;
578
Zonr Chang932648d2010-10-13 22:23:56 +0800579 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700580 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800581 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700582
583 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
584
585 return result;
586 }
587
Zonr Chang932648d2010-10-13 22:23:56 +0800588 // Allocate memory for a global variable.
589 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700590 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800591 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700592 LOGE("No Global Memory");
593 return NULL;
594 }
595
Zonr Chang932648d2010-10-13 22:23:56 +0800596 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700597 Alignment = 1;
598
Zonr Chang932648d2010-10-13 22:23:56 +0800599 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700600 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800601 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700602
603 mCurGVMemIdx = (result + Size) - getGVMemBase();
604
605 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700606 }
607
Zonr Chang932648d2010-10-13 22:23:56 +0800608 // Free the specified function body. The argument must be the return value
609 // from a call to startFunctionBody() that hasn't been deallocated yet. This
610 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700611 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800612 // linear search
613 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
614 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
615 E = mFunctionMap.end();
616 I != E;
617 I++)
618 if (I->second.first == Body) {
619 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
620 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700621 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800622 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700623
Zonr Chang932648d2010-10-13 22:23:56 +0800624 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700625
Zonr Chang932648d2010-10-13 22:23:56 +0800626 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700627 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
628
629 assert(SizeNeedMove >= 0 &&
630 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
631 " be correctly calculated!");
632
Zonr Chang932648d2010-10-13 22:23:56 +0800633 if (SizeNeedMove > 0)
634 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700635 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
636 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
637
638 return;
639 }
640
Zonr Chang932648d2010-10-13 22:23:56 +0800641 // When we finished JITing the function, if exception handling is set, we
642 // emit the exception table.
643 uint8_t *startExceptionTable(const llvm::Function *F,
644 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700645 assert(false && "Exception is not allowed in our language specification");
646 return NULL;
647 }
648
Zonr Chang932648d2010-10-13 22:23:56 +0800649 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700650 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800651 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700652 assert(false && "Exception is not allowed in our language specification");
653 return;
654 }
655
Zonr Chang932648d2010-10-13 22:23:56 +0800656 // Free the specified exception table's memory. The argument must be the
657 // return value from a call to startExceptionTable() that hasn't been
658 // deallocated yet. This is never called when the JIT is currently emitting
659 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700660 void deallocateExceptionTable(void *ET) {
661 assert(false && "Exception is not allowed in our language specification");
662 return;
663 }
664
Zonr Chang932648d2010-10-13 22:23:56 +0800665 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700666 void reset() {
667 mpGOTBase = NULL;
668 HasGOT = false;
669
670 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700671 mCurSGMemIdx = MaxCodeSize - 1;
672 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700673
674 mFunctionMap.clear();
675
676 return;
677 }
678
679 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800680 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700681 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800682 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700683 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700684 return;
685 }
Zonr Chang932648d2010-10-13 22:23:56 +0800686 };
687 // End of class CodeMemoryManager
688 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700689
Zonr Chang932648d2010-10-13 22:23:56 +0800690 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700691 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800692 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700693 mCodeMemMgr.reset(new CodeMemoryManager());
694 return mCodeMemMgr.get();
695 }
696
Zonr Chang932648d2010-10-13 22:23:56 +0800697 //////////////////////////////////////////////////////////////////////////////
698 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700699 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700700 public:
701 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
702 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
703
704 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800705 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700706
Zonr Chang932648d2010-10-13 22:23:56 +0800707 // The JITInfo for the target we are compiling to
708 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700709
Zonr Chang932648d2010-10-13 22:23:56 +0800710 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700711
Zonr Chang932648d2010-10-13 22:23:56 +0800712 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700713
714 class EmittedFunctionCode {
715 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800716 // Beginning of the function's allocation.
717 void *FunctionBody;
718
719 // The address the function's code actually starts at.
720 void *Code;
721
722 // The size of the function code
723 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700724
725 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
726 };
Zonr Chang932648d2010-10-13 22:23:56 +0800727 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700728
Zonr Chang932648d2010-10-13 22:23:56 +0800729 typedef std::map<const std::string,
730 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700731 EmittedFunctionsMapTy mEmittedFunctions;
732
Zonr Chang932648d2010-10-13 22:23:56 +0800733 // This vector is a mapping from MBB ID's to their address. It is filled in
734 // by the StartMachineBasicBlock callback and queried by the
735 // getMachineBasicBlockAddress callback.
736 std::vector<uintptr_t> mMBBLocations;
737
738 // The constant pool for the current function.
739 llvm::MachineConstantPool *mpConstantPool;
740
741 // A pointer to the first entry in the constant pool.
742 void *mpConstantPoolBase;
743
744 // Addresses of individual constant pool entries.
745 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
746
747 // The jump tables for the current function.
748 llvm::MachineJumpTableInfo *mpJumpTable;
749
750 // A pointer to the first entry in the jump table.
751 void *mpJumpTableBase;
752
753 // When outputting a function stub in the context of some other function, we
754 // save BufferBegin/BufferEnd/CurBufferPtr here.
755 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
756
757 // These are the relocations that the function needs, as emitted.
758 std::vector<llvm::MachineRelocation> mRelocations;
759
760 // This vector is a mapping from Label ID's to their address.
761 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
762
763 // Machine module info for exception informations
764 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700765
766 GlobalAddressMapTy mGlobalAddressMap;
767
Zonr Chang932648d2010-10-13 22:23:56 +0800768 // Replace an existing mapping for GV with a new address. This updates both
769 // maps as required. If Addr is null, the entry for the global is removed
770 // from the mappings.
771 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
772 if (Addr == NULL) {
773 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700774 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
775 void *OldVal;
776
Zonr Chang932648d2010-10-13 22:23:56 +0800777 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700778 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800779 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700780 OldVal = I->second;
781 mGlobalAddressMap.erase(I);
782 }
783
784 return OldVal;
785 }
786
Zonr Chang932648d2010-10-13 22:23:56 +0800787 void *&CurVal = mGlobalAddressMap[GV];
788 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700789
790 CurVal = Addr;
791
792 return OldVal;
793 }
794
Zonr Chang932648d2010-10-13 22:23:56 +0800795 // Tell the execution engine that the specified global is at the specified
796 // location. This is used internally as functions are JIT'd and as global
797 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700798 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800799 void *&CurVal = mGlobalAddressMap[GV];
800 assert((CurVal == 0 || Addr == 0) &&
801 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700802 CurVal = Addr;
803 return;
804 }
805
Zonr Chang932648d2010-10-13 22:23:56 +0800806 // This returns the address of the specified global value if it is has
807 // already been codegen'd, otherwise it returns null.
808 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700809 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700810 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
811 }
812
Zonr Chang932648d2010-10-13 22:23:56 +0800813 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
814 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700815 MCP->getConstants();
816
Zonr Chang932648d2010-10-13 22:23:56 +0800817 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700818 return 0;
819
820 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800821 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700822 llvm::MachineConstantPoolEntry CPE = Constants[i];
823 unsigned int AlignMask = CPE.getAlignment() - 1;
824 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800825 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700826 Size += mpTD->getTypeAllocSize(Ty);
827 }
828
829 return Size;
830 }
831
Zonr Chang932648d2010-10-13 22:23:56 +0800832 // This function converts a Constant* into a GenericValue. The interesting
833 // part is if C is a ConstantExpr.
834 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
835 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700836 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800837 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
838 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
839 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700840
Zonr Chang932648d2010-10-13 22:23:56 +0800841 switch (CE->getOpcode()) {
842 case llvm::Instruction::GetElementPtr: {
843 // Compute the index
844 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
845 CE->op_end());
846 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
847 &Indices[0],
848 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700849
Zonr Chang932648d2010-10-13 22:23:56 +0800850 GetConstantValue(Op0, Result);
851 Result.PointerVal =
852 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700853
Zonr Chang932648d2010-10-13 22:23:56 +0800854 return;
855 }
856 case llvm::Instruction::Trunc: {
857 uint32_t BitWidth =
858 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
859
860 GetConstantValue(Op0, Result);
861 Result.IntVal = Result.IntVal.trunc(BitWidth);
862
863 return;
864 }
865 case llvm::Instruction::ZExt: {
866 uint32_t BitWidth =
867 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
868
869 GetConstantValue(Op0, Result);
870 Result.IntVal = Result.IntVal.zext(BitWidth);
871
872 return;
873 }
874 case llvm::Instruction::SExt: {
875 uint32_t BitWidth =
876 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
877
878 GetConstantValue(Op0, Result);
879 Result.IntVal = Result.IntVal.sext(BitWidth);
880
881 return;
882 }
883 case llvm::Instruction::FPTrunc: {
884 // FIXME: long double
885 GetConstantValue(Op0, Result);
886 Result.FloatVal = static_cast<float>(Result.DoubleVal);
887 return;
888 }
889 case llvm::Instruction::FPExt: {
890 // FIXME: long double
891 GetConstantValue(Op0, Result);
892 Result.DoubleVal = static_cast<double>(Result.FloatVal);
893 return;
894 }
895 case llvm::Instruction::UIToFP: {
896 GetConstantValue(Op0, Result);
897 if (CE->getType()->isFloatTy())
898 Result.FloatVal =
899 static_cast<float>(Result.IntVal.roundToDouble());
900 else if (CE->getType()->isDoubleTy())
901 Result.DoubleVal = Result.IntVal.roundToDouble();
902 else if (CE->getType()->isX86_FP80Ty()) {
903 const uint64_t zero[] = { 0, 0 };
904 llvm::APFloat apf(llvm::APInt(80, 2, zero));
905 apf.convertFromAPInt(Result.IntVal,
906 false,
907 llvm::APFloat::rmNearestTiesToEven);
908 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700909 }
Zonr Chang932648d2010-10-13 22:23:56 +0800910 return;
911 }
912 case llvm::Instruction::SIToFP: {
913 GetConstantValue(Op0, Result);
914 if (CE->getType()->isFloatTy())
915 Result.FloatVal =
916 static_cast<float>(Result.IntVal.signedRoundToDouble());
917 else if (CE->getType()->isDoubleTy())
918 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
919 else if (CE->getType()->isX86_FP80Ty()) {
920 const uint64_t zero[] = { 0, 0 };
921 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
922 apf.convertFromAPInt(Result.IntVal,
923 true,
924 llvm::APFloat::rmNearestTiesToEven);
925 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700926 }
Zonr Chang932648d2010-10-13 22:23:56 +0800927 return;
928 }
929 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700930 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +0800931 case llvm::Instruction::FPToSI: {
932 uint32_t BitWidth =
933 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700934
Zonr Chang932648d2010-10-13 22:23:56 +0800935 GetConstantValue(Op0, Result);
936 if (Op0->getType()->isFloatTy())
937 Result.IntVal =
938 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
939 else if (Op0->getType()->isDoubleTy())
940 Result.IntVal =
941 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
942 BitWidth);
943 else if (Op0->getType()->isX86_FP80Ty()) {
944 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
945 uint64_t V;
946 bool Ignored;
947 apf.convertToInteger(&V,
948 BitWidth,
949 CE->getOpcode() == llvm::Instruction::FPToSI,
950 llvm::APFloat::rmTowardZero,
951 &Ignored);
952 Result.IntVal = V; // endian?
953 }
954 return;
955 }
956 case llvm::Instruction::PtrToInt: {
957 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
958
959 GetConstantValue(Op0, Result);
960 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
961 (Result.PointerVal));
962
963 return;
964 }
965 case llvm::Instruction::IntToPtr: {
966 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
967
968 GetConstantValue(Op0, Result);
969 if (PtrWidth != Result.IntVal.getBitWidth())
970 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
971 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
972
973 Result.PointerVal =
974 llvm::PointerTy(
975 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
976
977 return;
978 }
979 case llvm::Instruction::BitCast: {
980 GetConstantValue(Op0, Result);
981 const llvm::Type *DestTy = CE->getType();
982
983 switch (Op0->getType()->getTypeID()) {
984 case llvm::Type::IntegerTyID: {
985 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
986 if (DestTy->isFloatTy())
987 Result.FloatVal = Result.IntVal.bitsToFloat();
988 else if (DestTy->isDoubleTy())
989 Result.DoubleVal = Result.IntVal.bitsToDouble();
990 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700991 }
Zonr Chang932648d2010-10-13 22:23:56 +0800992 case llvm::Type::FloatTyID: {
993 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
994 Result.IntVal.floatToBits(Result.FloatVal);
995 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700996 }
Zonr Chang932648d2010-10-13 22:23:56 +0800997 case llvm::Type::DoubleTyID: {
998 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
999 Result.IntVal.doubleToBits(Result.DoubleVal);
1000 break;
1001 }
1002 case llvm::Type::PointerTyID: {
1003 assert(DestTy->isPointerTy() && "Invalid bitcast");
1004 break; // getConstantValue(Op0) above already converted it
1005 }
1006 default: {
1007 llvm_unreachable("Invalid bitcast operand");
1008 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001009 }
Zonr Chang932648d2010-10-13 22:23:56 +08001010 return;
1011 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001012 case llvm::Instruction::Add:
1013 case llvm::Instruction::FAdd:
1014 case llvm::Instruction::Sub:
1015 case llvm::Instruction::FSub:
1016 case llvm::Instruction::Mul:
1017 case llvm::Instruction::FMul:
1018 case llvm::Instruction::UDiv:
1019 case llvm::Instruction::SDiv:
1020 case llvm::Instruction::URem:
1021 case llvm::Instruction::SRem:
1022 case llvm::Instruction::And:
1023 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001024 case llvm::Instruction::Xor: {
1025 llvm::GenericValue LHS, RHS;
1026 GetConstantValue(Op0, LHS);
1027 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001028
Zonr Chang932648d2010-10-13 22:23:56 +08001029 switch (Op0->getType()->getTypeID()) {
1030 case llvm::Type::IntegerTyID: {
1031 switch (CE->getOpcode()) {
1032 case llvm::Instruction::Add: {
1033 Result.IntVal = LHS.IntVal + RHS.IntVal;
1034 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001035 }
Zonr Chang932648d2010-10-13 22:23:56 +08001036 case llvm::Instruction::Sub: {
1037 Result.IntVal = LHS.IntVal - RHS.IntVal;
1038 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001039 }
Zonr Chang932648d2010-10-13 22:23:56 +08001040 case llvm::Instruction::Mul: {
1041 Result.IntVal = LHS.IntVal * RHS.IntVal;
1042 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001043 }
Zonr Chang932648d2010-10-13 22:23:56 +08001044 case llvm::Instruction::UDiv: {
1045 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1046 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001047 }
Zonr Chang932648d2010-10-13 22:23:56 +08001048 case llvm::Instruction::SDiv: {
1049 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1050 break;
1051 }
1052 case llvm::Instruction::URem: {
1053 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1054 break;
1055 }
1056 case llvm::Instruction::SRem: {
1057 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1058 break;
1059 }
1060 case llvm::Instruction::And: {
1061 Result.IntVal = LHS.IntVal & RHS.IntVal;
1062 break;
1063 }
1064 case llvm::Instruction::Or: {
1065 Result.IntVal = LHS.IntVal | RHS.IntVal;
1066 break;
1067 }
1068 case llvm::Instruction::Xor: {
1069 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1070 break;
1071 }
1072 default: {
1073 llvm_unreachable("Invalid integer opcode");
1074 }
1075 }
1076 break;
1077 }
1078 case llvm::Type::FloatTyID: {
1079 switch (CE->getOpcode()) {
1080 case llvm::Instruction::FAdd: {
1081 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1082 break;
1083 }
1084 case llvm::Instruction::FSub: {
1085 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1086 break;
1087 }
1088 case llvm::Instruction::FMul: {
1089 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1090 break;
1091 }
1092 case llvm::Instruction::FDiv: {
1093 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1094 break;
1095 }
1096 case llvm::Instruction::FRem: {
1097 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1098 break;
1099 }
1100 default: {
1101 llvm_unreachable("Invalid float opcode");
1102 }
1103 }
1104 break;
1105 }
1106 case llvm::Type::DoubleTyID: {
1107 switch (CE->getOpcode()) {
1108 case llvm::Instruction::FAdd: {
1109 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1110 break;
1111 }
1112 case llvm::Instruction::FSub: {
1113 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1114 break;
1115 }
1116 case llvm::Instruction::FMul: {
1117 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1118 break;
1119 }
1120 case llvm::Instruction::FDiv: {
1121 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1122 break;
1123 }
1124 case llvm::Instruction::FRem: {
1125 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1126 break;
1127 }
1128 default: {
1129 llvm_unreachable("Invalid double opcode");
1130 }
1131 }
1132 break;
1133 }
1134 case llvm::Type::X86_FP80TyID:
1135 case llvm::Type::PPC_FP128TyID:
1136 case llvm::Type::FP128TyID: {
1137 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1138 switch (CE->getOpcode()) {
1139 case llvm::Instruction::FAdd: {
1140 apfLHS.add(llvm::APFloat(RHS.IntVal),
1141 llvm::APFloat::rmNearestTiesToEven);
1142 break;
1143 }
1144 case llvm::Instruction::FSub: {
1145 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1146 llvm::APFloat::rmNearestTiesToEven);
1147 break;
1148 }
1149 case llvm::Instruction::FMul: {
1150 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1151 llvm::APFloat::rmNearestTiesToEven);
1152 break;
1153 }
1154 case llvm::Instruction::FDiv: {
1155 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1156 llvm::APFloat::rmNearestTiesToEven);
1157 break;
1158 }
1159 case llvm::Instruction::FRem: {
1160 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1161 llvm::APFloat::rmNearestTiesToEven);
1162 break;
1163 }
1164 default: {
1165 llvm_unreachable("Invalid long double opcode");
1166 }
1167 }
1168 Result.IntVal = apfLHS.bitcastToAPInt();
1169 break;
1170 }
1171 default: {
1172 llvm_unreachable("Bad add type!");
1173 }
1174 } // End switch (Op0->getType()->getTypeID())
1175 return;
1176 }
1177 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001178 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001179 }
1180 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001181
1182 std::string msg;
1183 llvm::raw_string_ostream Msg(msg);
1184 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001185 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001186 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001187
1188 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001189 case llvm::Type::FloatTyID: {
1190 Result.FloatVal =
1191 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001192 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001193 }
1194 case llvm::Type::DoubleTyID: {
1195 Result.DoubleVal =
1196 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001197 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001198 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001199 case llvm::Type::X86_FP80TyID:
1200 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001201 case llvm::Type::PPC_FP128TyID: {
1202 Result.IntVal =
1203 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001204 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001205 }
1206 case llvm::Type::IntegerTyID: {
1207 Result.IntVal =
1208 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001209 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001210 }
1211 case llvm::Type::PointerTyID: {
1212 switch (C->getValueID()) {
1213 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001214 Result.PointerVal = NULL;
1215 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001216 }
1217 case llvm::Value::FunctionVal: {
1218 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1219 Result.PointerVal =
1220 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001221 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001222 }
1223 case llvm::Value::GlobalVariableVal: {
1224 const llvm::GlobalVariable *GV =
1225 static_cast<const llvm::GlobalVariable*>(C);
1226 Result.PointerVal =
1227 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001228 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001229 }
1230 case llvm::Value::BlockAddressVal: {
1231 assert(false && "JIT does not support address-of-label yet!");
1232 }
1233 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001234 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001235 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001236 }
1237 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001238 }
1239 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001240 std::string msg;
1241 llvm::raw_string_ostream Msg(msg);
1242 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001243 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001244 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001245 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001246 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001247 return;
1248 }
1249
Zonr Chang932648d2010-10-13 22:23:56 +08001250 // Stores the data in @Val of type @Ty at address @Addr.
1251 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001252 const llvm::Type *Ty) {
1253 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1254
Zonr Chang932648d2010-10-13 22:23:56 +08001255 switch (Ty->getTypeID()) {
1256 case llvm::Type::IntegerTyID: {
1257 const llvm::APInt &IntVal = Val.IntVal;
1258 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1259 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001260
Zonr Chang932648d2010-10-13 22:23:56 +08001261 const uint8_t *Src =
1262 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001263
Zonr Chang932648d2010-10-13 22:23:56 +08001264 if (llvm::sys::isLittleEndianHost()) {
1265 // Little-endian host - the source is ordered from LSB to MSB.
1266 // Order the destination from LSB to MSB: Do a straight copy.
1267 memcpy(Addr, Src, StoreBytes);
1268 } else {
1269 // Big-endian host - the source is an array of 64 bit words
1270 // ordered from LSW to MSW.
1271 //
1272 // Each word is ordered from MSB to LSB.
1273 //
1274 // Order the destination from MSB to LSB:
1275 // Reverse the word order, but not the bytes in a word.
1276 unsigned int i = StoreBytes;
1277 while (i > sizeof(uint64_t)) {
1278 i -= sizeof(uint64_t);
1279 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1280 Src,
1281 sizeof(uint64_t));
1282 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001283 }
Zonr Chang932648d2010-10-13 22:23:56 +08001284 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001285 }
1286 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001287 }
1288 case llvm::Type::FloatTyID: {
1289 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001290 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001291 }
1292 case llvm::Type::DoubleTyID: {
1293 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001294 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001295 }
1296 case llvm::Type::X86_FP80TyID: {
1297 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001298 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001299 }
1300 case llvm::Type::PointerTyID: {
1301 // Ensure 64 bit target pointers are fully initialized on 32 bit
1302 // hosts.
1303 if (StoreBytes != sizeof(llvm::PointerTy))
1304 memset(Addr, 0, StoreBytes);
1305 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001306 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001307 }
1308 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001309 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001310 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001311 }
1312
Zonr Chang932648d2010-10-13 22:23:56 +08001313 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1314 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1315 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001316
1317 return;
1318 }
1319
Zonr Chang932648d2010-10-13 22:23:56 +08001320 // Recursive function to apply a @Constant value into the specified memory
1321 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001322 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001323 switch (C->getValueID()) {
1324 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001325 // Nothing to do
1326 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001327 }
1328 case llvm::Value::ConstantVectorVal: {
1329 // dynamic cast may hurt performance
1330 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001331
Zonr Chang932648d2010-10-13 22:23:56 +08001332 unsigned int ElementSize = mpTD->getTypeAllocSize
1333 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001334
Zonr Chang932648d2010-10-13 22:23:56 +08001335 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1336 InitializeConstantToMemory(
1337 CP->getOperand(i),
1338 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001339 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001340 }
1341 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001342 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1343 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001344 }
1345 case llvm::Value::ConstantArrayVal: {
1346 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1347 unsigned int ElementSize = mpTD->getTypeAllocSize
1348 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001349
Zonr Chang932648d2010-10-13 22:23:56 +08001350 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1351 InitializeConstantToMemory(
1352 CPA->getOperand(i),
1353 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1354 break;
1355 }
1356 case llvm::Value::ConstantStructVal: {
1357 const llvm::ConstantStruct *CPS =
1358 static_cast<const llvm::ConstantStruct*>(C);
1359 const llvm::StructLayout *SL = mpTD->getStructLayout
1360 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001361
Zonr Chang932648d2010-10-13 22:23:56 +08001362 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1363 InitializeConstantToMemory(
1364 CPS->getOperand(i),
1365 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1366 break;
1367 }
1368 default: {
1369 if (C->getType()->isFirstClassType()) {
1370 llvm::GenericValue Val;
1371 GetConstantValue(C, Val);
1372 StoreValueToMemory(Val, Addr, C->getType());
1373 } else {
1374 llvm_unreachable("Unknown constant type to initialize memory "
1375 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001376 }
1377 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001378 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001379 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001380 return;
1381 }
1382
1383 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001384 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001385 return;
1386
Zonr Chang932648d2010-10-13 22:23:56 +08001387 // Constant pool address resolution is handled by the target itself in ARM
1388 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001389#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001390 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1391 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001392
Zonr Chang932648d2010-10-13 22:23:56 +08001393 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001394 return;
1395
1396 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1397 unsigned Align = MCP->getConstantPoolAlignment();
1398
1399 mpConstantPoolBase = allocateSpace(Size, Align);
1400 mpConstantPool = MCP;
1401
Zonr Chang932648d2010-10-13 22:23:56 +08001402 if (mpConstantPoolBase == NULL)
1403 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001404
1405 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001406 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001407 llvm::MachineConstantPoolEntry CPE = Constants[i];
1408 unsigned AlignMask = CPE.getAlignment() - 1;
1409 Offset = (Offset + AlignMask) & ~AlignMask;
1410
1411 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1412 mConstPoolAddresses.push_back(CAddr);
1413
Zonr Chang932648d2010-10-13 22:23:56 +08001414 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001415 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001416 ("Initialize memory with machine specific constant pool"
1417 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001418
1419 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1420
1421 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1422 Offset += mpTD->getTypeAllocSize(Ty);
1423 }
1424#endif
1425 return;
1426 }
1427
1428 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001429 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001430 return;
1431
Zonr Chang932648d2010-10-13 22:23:56 +08001432 const std::vector<llvm::MachineJumpTableEntry> &JT =
1433 MJTI->getJumpTables();
1434 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001435 return;
1436
1437 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001438 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001439 NumEntries += JT[i].MBBs.size();
1440
1441 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1442
Zonr Chang932648d2010-10-13 22:23:56 +08001443 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001444 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001445 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001446
1447 return;
1448 }
1449
1450 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001451 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001452 return;
1453
Zonr Chang932648d2010-10-13 22:23:56 +08001454 const std::vector<llvm::MachineJumpTableEntry> &JT =
1455 MJTI->getJumpTables();
1456 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001457 return;
1458
Zonr Chang932648d2010-10-13 22:23:56 +08001459 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1460 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1461 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001462
Zonr Chang932648d2010-10-13 22:23:56 +08001463 // For each jump table, map each target in the jump table to the
1464 // address of an emitted MachineBasicBlock.
1465 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1466 for (int i = 0, ie = JT.size(); i != ie; i++) {
1467 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1468 // Store the address of the basic block for this jump table slot in the
1469 // memory we allocated for the jump table in 'initJumpTableInfo'
1470 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001471 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1472 }
1473 }
1474
Zonr Chang932648d2010-10-13 22:23:56 +08001475 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1476 bool MayNeedFarStub) {
1477 switch (V->getValueID()) {
1478 case llvm::Value::FunctionVal: {
1479 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001480
Zonr Chang932648d2010-10-13 22:23:56 +08001481 // If we have code, go ahead and return that.
1482 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1483 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001484
Zonr Chang932648d2010-10-13 22:23:56 +08001485 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1486 // Return the function stub if it's already created.
1487 // We do this first so that:
1488 // we're returning the same address for the function as any
1489 // previous call.
1490 //
1491 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1492 // guaranteed to be close enough to call.
1493 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001494
Zonr Chang932648d2010-10-13 22:23:56 +08001495 // If we know the target can handle arbitrary-distance calls, try to
1496 // return a direct pointer.
1497 if (!MayNeedFarStub) {
1498 //
1499 // x86_64 architecture may encounter the bug:
1500 // http://llvm.org/bugs/show_bug.cgi?id=5201
1501 // which generate instruction "call" instead of "callq".
1502 //
1503 // And once the real address of stub is greater than 64-bit
1504 // long, the replacement will truncate to 32-bit resulting a
1505 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001506#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001507 // If this is an external function pointer, we can force the JIT
1508 // to 'compile' it, which really just adds it to the map.
1509 if (F->isDeclaration() || F->hasAvailableExternallyLinkage())
1510 return GetPointerToFunction(F, /* AbortOnFailure = */true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001511#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001512 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001513
Zonr Chang932648d2010-10-13 22:23:56 +08001514 // Otherwise, we may need a to emit a stub, and, conservatively, we
1515 // always do so.
1516 return GetLazyFunctionStub(F);
1517 break;
1518 }
1519 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001520 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1521 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001522 }
1523 case llvm::Value::GlobalAliasVal: {
1524 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1525 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001526
Zonr Chang932648d2010-10-13 22:23:56 +08001527 switch (GV->getValueID()) {
1528 case llvm::Value::FunctionVal: {
1529 // FIXME: is there's any possibility that the function is not
1530 // code-gen'd?
1531 return GetPointerToFunction(
1532 static_cast<const llvm::Function*>(GV),
1533 /* AbortOnFailure = */true);
1534 break;
1535 }
1536 case llvm::Value::GlobalVariableVal: {
1537 if (void *P = mGlobalAddressMap[GV])
1538 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001539
Zonr Chang932648d2010-10-13 22:23:56 +08001540 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1541 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001542
Zonr Chang932648d2010-10-13 22:23:56 +08001543 return mGlobalAddressMap[GV];
1544 break;
1545 }
1546 case llvm::Value::GlobalAliasVal: {
1547 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001548 }
1549 }
1550 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001551 }
1552 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001553 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001554 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001555 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001556 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001557 }
1558
Zonr Chang932648d2010-10-13 22:23:56 +08001559 // If the specified function has been code-gen'd, return a pointer to the
1560 // function. If not, compile it, or use a stub to implement lazy compilation
1561 // if available.
1562 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1563 // If we have already code generated the function, just return the
1564 // address.
1565 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001566 return Addr;
1567
Zonr Chang932648d2010-10-13 22:23:56 +08001568 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001569 return GetLazyFunctionStub(F);
1570 }
1571
Zonr Chang932648d2010-10-13 22:23:56 +08001572 typedef llvm::DenseMap<const llvm::Function*,
1573 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001574 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1575
Zonr Chang932648d2010-10-13 22:23:56 +08001576 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001577 return mFunctionToLazyStubMap.lookup(F);
1578 }
1579
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001580 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001581 void *GetLazyFunctionStub(llvm::Function *F) {
1582 // If we already have a lazy stub for this function, recycle it.
1583 void *&Stub = mFunctionToLazyStubMap[F];
1584 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001585 return Stub;
1586
Zonr Chang932648d2010-10-13 22:23:56 +08001587 // In any cases, we should NOT resolve function at runtime (though we are
1588 // able to). We resolve this right now.
1589 void *Actual = NULL;
1590 if (F->isDeclaration() || F->hasAvailableExternallyLinkage())
1591 Actual = GetPointerToFunction(F, /* AbortOnFailure = */true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001592
Zonr Chang932648d2010-10-13 22:23:56 +08001593 // Codegen a new stub, calling the actual address of the external
1594 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001595 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1596 startGVStub(F, SL.Size, SL.Alignment);
1597 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1598 finishGVStub();
1599
Zonr Chang932648d2010-10-13 22:23:56 +08001600 // We really want the address of the stub in the GlobalAddressMap for the
1601 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001602 UpdateGlobalMapping(F, Stub);
1603
Zonr Chang932648d2010-10-13 22:23:56 +08001604 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001605 PendingFunctions.insert(F);
1606 else
Zonr Chang932648d2010-10-13 22:23:56 +08001607 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1608 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001609
1610 return Stub;
1611 }
1612
Zonr Chang932648d2010-10-13 22:23:56 +08001613 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1614 void *Addr = GetPointerToGlobalIfAvailable(F);
1615 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001616 return Addr;
1617
1618 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1619 "Internal error: only external defined function routes here!");
1620
Zonr Chang932648d2010-10-13 22:23:56 +08001621 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001622 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001623 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001624
Zonr Chang932648d2010-10-13 22:23:56 +08001625 // If we resolved the symbol to a null address (eg. a weak external)
1626 // return a null pointer let the application handle it.
1627 if (Addr == NULL) {
1628 if (AbortOnFailure)
1629 llvm::report_fatal_error("Could not resolve external function "
1630 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001631 else
1632 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001633 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001634
1635 AddGlobalMapping(F, Addr);
1636
1637 return Addr;
1638 }
1639
Zonr Chang932648d2010-10-13 22:23:56 +08001640 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001641 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001642 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001643 return Addr;
1644
Zonr Chang932648d2010-10-13 22:23:56 +08001645 if (mpSymbolLookupFn)
1646 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001647 return Addr;
1648
Zonr Chang932648d2010-10-13 22:23:56 +08001649 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001650 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001651 "' which could not be resolved!");
1652
1653 return NULL;
1654 }
1655
Zonr Chang932648d2010-10-13 22:23:56 +08001656 // Return the address of the specified global variable, possibly emitting it
1657 // to memory if needed. This is used by the Emitter.
1658 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1659 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1660 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001661 return Ptr;
1662
Zonr Chang932648d2010-10-13 22:23:56 +08001663 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1664 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001665 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1666 AddGlobalMapping(GV, Ptr);
1667 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001668 // If the global hasn't been emitted to memory yet, allocate space and
1669 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001670 Ptr = GetMemoryForGV(GV);
1671 AddGlobalMapping(GV, Ptr);
1672 EmitGlobalVariable(GV);
1673 }
1674
1675 return Ptr;
1676 }
1677
Zonr Chang932648d2010-10-13 22:23:56 +08001678 // This method abstracts memory allocation of global variable so that the
1679 // JIT can allocate thread local variables depending on the target.
1680 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1681 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001682
Zonr Chang932648d2010-10-13 22:23:56 +08001683 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001684 size_t S = mpTD->getTypeAllocSize(GlobalType);
1685 size_t A = mpTD->getPreferredAlignment(GV);
1686
Zonr Chang932648d2010-10-13 22:23:56 +08001687 if (GV->isThreadLocal()) {
1688 // We can support TLS by
1689 //
1690 // Ptr = TJI.allocateThreadLocalMemory(S);
1691 //
1692 // But I tend not to.
1693 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001694 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001695 ("Compilation of Thread Local Storage (TLS) is disabled!");
1696
Zonr Chang932648d2010-10-13 22:23:56 +08001697 } else if (mpTJI->allocateSeparateGVMemory()) {
1698 if (A <= 8) {
1699 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001700 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001701 // Allocate (S + A) bytes of memory, then use an aligned pointer
1702 // within that space.
1703 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001704 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001705 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1706 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001707 }
1708 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001709 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001710 }
1711
1712 return Ptr;
1713 }
1714
1715 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001716 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001717
Zonr Chang932648d2010-10-13 22:23:56 +08001718 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001719 llvm::report_fatal_error
1720 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001721
Zonr Chang932648d2010-10-13 22:23:56 +08001722 if (GA == NULL) {
1723 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001724 GA = GetMemoryForGV(GV);
1725 AddGlobalMapping(GV, GA);
1726 }
1727
1728 InitializeConstantToMemory(GV->getInitializer(), GA);
1729
Zonr Chang932648d2010-10-13 22:23:56 +08001730 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001731 return;
1732 }
1733
1734 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1735 > GlobalToIndirectSymMapTy;
1736 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1737
Zonr Chang932648d2010-10-13 22:23:56 +08001738 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1739 // Make sure GV is emitted first, and create a stub containing the fully
1740 // resolved address.
1741 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001742
Zonr Chang932648d2010-10-13 22:23:56 +08001743 // If we already have a stub for this global variable, recycle it.
1744 void *&IndirectSym = GlobalToIndirectSymMap[V];
1745 // Otherwise, codegen a new indirect symbol.
1746 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001747 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1748
1749 return IndirectSym;
1750 }
1751
Zonr Chang932648d2010-10-13 22:23:56 +08001752 // This is the equivalent of FunctionToLazyStubMap for external functions.
1753 //
1754 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1755 // It's actually here to make it more likely that far calls
1756 // succeed, but no single stub can guarantee that. I'll
1757 // remove this in a subsequent checkin when I actually fix
1758 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001759 std::map<void*, void*> ExternalFnToStubMap;
1760
Zonr Chang932648d2010-10-13 22:23:56 +08001761 // Return a stub for the function at the specified address.
1762 void *GetExternalFunctionStub(void *FnAddr) {
1763 void *&Stub = ExternalFnToStubMap[FnAddr];
1764 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001765 return Stub;
1766
1767 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1768 startGVStub(0, SL.Size, SL.Alignment);
1769 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1770 finishGVStub();
1771
1772 return Stub;
1773 }
1774
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001775#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001776 const llvm::MCAsmInfo *mpAsmInfo;
1777 const llvm::MCDisassembler *mpDisassmbler;
1778 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001779
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001780 class BufferMemoryObject : public llvm::MemoryObject {
1781 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001782 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001783 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001784
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001785 public:
1786 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1787 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001788
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001789 uint64_t getBase() const { return 0; }
1790 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001791
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001792 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001793 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001794 return -1;
1795 *Byte = mBytes[Addr];
1796 return 0;
1797 }
1798 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001799
Zonr Chang932648d2010-10-13 22:23:56 +08001800 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001801 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001802 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001803#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001804 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001805 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1806 ErrorInfo,
1807 llvm::raw_fd_ostream::F_Append);
1808 if (!ErrorInfo.empty()) { // some errors occurred
1809 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001810 delete OS;
1811 return;
1812 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001813#else
1814 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001815#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001816 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1817 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001818
Zonr Chang932648d2010-10-13 22:23:56 +08001819 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001820 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001821 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001822 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001823 if (mpIP == NULL)
1824 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1825 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001826
Zonr Chang932648d2010-10-13 22:23:56 +08001827 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1828 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001829 uint64_t Size;
1830 uint64_t Index;
1831
Zonr Chang932648d2010-10-13 22:23:56 +08001832 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001833 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001834
Zonr Chang932648d2010-10-13 22:23:56 +08001835 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1836 /* REMOVED */ llvm::nulls())) {
1837 (*OS).indent(4)
1838 .write("0x", 2)
1839 .write_hex((uint32_t) Start + Index)
1840 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001841 mpIP->printInst(&Inst, *OS);
1842 *OS << "\n";
1843 } else {
1844 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08001845 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001846 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001847 }
1848
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001849 *OS << "\n";
1850 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001851
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001852#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08001853 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001854 OS->close();
1855 delete OS;
1856#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001857 return;
1858 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001859#else
Zonr Chang932648d2010-10-13 22:23:56 +08001860 inline void Disassemble(const std::string &Name, uint8_t *Start,
1861 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001862 return;
1863 }
Zonr Chang932648d2010-10-13 22:23:56 +08001864#endif // defined(USE_DISASSEMBLER)
1865
1866 // Resolver to undefined symbol in CodeEmitter
1867 BCCSymbolLookupFn mpSymbolLookupFn;
1868 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001869
1870 public:
Zonr Chang932648d2010-10-13 22:23:56 +08001871 // Will take the ownership of @MemMgr
1872 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
1873 : mpMemMgr(pMemMgr),
1874 mpTarget(NULL),
1875 mpTJI(NULL),
1876 mpTD(NULL),
1877 mpCurEmitFunction(NULL),
1878 mpConstantPool(NULL),
1879 mpJumpTable(NULL),
1880 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001881#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001882 mpAsmInfo(NULL),
1883 mpDisassmbler(NULL),
1884 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001885#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001886 mpSymbolLookupFn(NULL),
1887 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001888 return;
1889 }
1890
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001891 inline global_addresses_const_iterator global_address_begin() const {
1892 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001893 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001894 inline global_addresses_const_iterator global_address_end() const {
1895 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001896 }
1897
Zonr Chang932648d2010-10-13 22:23:56 +08001898 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001899 mpSymbolLookupFn = pFn;
1900 mpSymbolLookupContext = pContext;
1901 return;
1902 }
1903
Zonr Chang932648d2010-10-13 22:23:56 +08001904 void setTargetMachine(llvm::TargetMachine &TM) {
1905 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001906 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08001907 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001908 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08001909 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001910 mpTD = TM.getTargetData();
1911
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001912 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
1913
1914 return;
1915 }
1916
Zonr Chang932648d2010-10-13 22:23:56 +08001917 // This callback is invoked when the specified function is about to be code
1918 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001919 void startFunction(llvm::MachineFunction &F) {
1920 uintptr_t ActualSize = 0;
1921
1922 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08001923
1924 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
1925 // MachineCodeEmitter, which is the super class of the class
1926 // JITCodeEmitter.
1927 //
1928 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
1929 // allocated for this code buffer.
1930 //
1931 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
1932 // code. This is guranteed to be in the range
1933 // [BufferBegin, BufferEnd]. If this pointer is at
1934 // BufferEnd, it will never move due to code emission, and
1935 // all code emission requests will be ignored (this is the
1936 // buffer overflow condition).
1937 BufferBegin = CurBufferPtr =
1938 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001939 BufferEnd = BufferBegin + ActualSize;
1940
Zonr Chang932648d2010-10-13 22:23:56 +08001941 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001942 mpCurEmitFunction = new EmittedFunctionCode();
1943 mpCurEmitFunction->FunctionBody = BufferBegin;
1944
Zonr Chang932648d2010-10-13 22:23:56 +08001945 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001946 emitAlignment(16);
1947
1948 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08001949 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001950 initJumpTableInfo(MJTI);
1951
Zonr Chang932648d2010-10-13 22:23:56 +08001952 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001953 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
1954
1955 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
1956
1957 mpCurEmitFunction->Code = CurBufferPtr;
1958
1959 mMBBLocations.clear();
1960
1961 return;
1962 }
1963
Zonr Chang932648d2010-10-13 22:23:56 +08001964 // This callback is invoked when the specified function has finished code
1965 // generation. If a buffer overflow has occurred, this method returns true
1966 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001967 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08001968 if (CurBufferPtr == BufferEnd) {
1969 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001970 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
1971 return false;
1972 }
1973
Zonr Chang932648d2010-10-13 22:23:56 +08001974 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001975 emitJumpTableInfo(MJTI);
1976
Zonr Chang932648d2010-10-13 22:23:56 +08001977 // FnStart is the start of the text, not the start of the constant pool
1978 // and other per-function data.
1979 uint8_t *FnStart =
1980 reinterpret_cast<uint8_t*>(
1981 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001982
Zonr Chang932648d2010-10-13 22:23:56 +08001983 // FnEnd is the end of the function's machine code.
1984 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001985
Zonr Chang932648d2010-10-13 22:23:56 +08001986 if (!mRelocations.empty()) {
1987 // Resolve the relocations to concrete pointers.
1988 for (int i = 0, e = mRelocations.size(); i != e; i++) {
1989 llvm::MachineRelocation &MR = mRelocations[i];
1990 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001991
Zonr Chang932648d2010-10-13 22:23:56 +08001992 if (!MR.letTargetResolve()) {
1993 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001994 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Zonr Chang932648d2010-10-13 22:23:56 +08001995 if (MR.mayNeedFarStub())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001996 ResultPtr = GetExternalFunctionStub(ResultPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08001997 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001998 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
1999 BufferBegin
2000 + MR.getMachineCodeOffset(),
2001 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002002 } else if (MR.isIndirectSymbol()) {
2003 ResultPtr =
2004 GetPointerToGVIndirectSym(
2005 MR.getGlobalValue(),
2006 BufferBegin + MR.getMachineCodeOffset());
2007 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002008 ResultPtr =
2009 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002010 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002011 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002012 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002013 } else {
2014 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2015 ResultPtr =
2016 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2017 }
2018
2019 MR.setResultPointer(ResultPtr);
2020 }
2021 }
2022
2023 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2024 mpMemMgr->getGOTBase());
2025 }
2026
2027 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002028 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2029 // global variables that were referenced in the relocations.
2030 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002031 return false;
2032
Zonr Chang932648d2010-10-13 22:23:56 +08002033 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002034 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2035 BufferBegin = CurBufferPtr = 0;
2036
Zonr Chang932648d2010-10-13 22:23:56 +08002037 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002038 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2039 mpCurEmitFunction = NULL;
2040
2041 mRelocations.clear();
2042 mConstPoolAddresses.clear();
2043
Zonr Chang932648d2010-10-13 22:23:56 +08002044 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002045 mpMMI->EndFunction();
2046
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002047 updateFunctionStub(F.getFunction());
2048
Zonr Chang932648d2010-10-13 22:23:56 +08002049 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002050 mpMemMgr->setMemoryExecutable();
2051
2052 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2053
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002054 return false;
2055 }
2056
Zonr Chang932648d2010-10-13 22:23:56 +08002057 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002058 unsigned Alignment) {
2059 mpSavedBufferBegin = BufferBegin;
2060 mpSavedBufferEnd = BufferEnd;
2061 mpSavedCurBufferPtr = CurBufferPtr;
2062
2063 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2064 Alignment);
2065 BufferEnd = BufferBegin + StubSize + 1;
2066
2067 return;
2068 }
2069
Zonr Chang932648d2010-10-13 22:23:56 +08002070 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002071 mpSavedBufferBegin = BufferBegin;
2072 mpSavedBufferEnd = BufferEnd;
2073 mpSavedCurBufferPtr = CurBufferPtr;
2074
Zonr Chang932648d2010-10-13 22:23:56 +08002075 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002076 BufferEnd = BufferBegin + StubSize + 1;
2077
2078 return;
2079 }
2080
2081 void finishGVStub() {
2082 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2083
Zonr Chang932648d2010-10-13 22:23:56 +08002084 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002085 BufferBegin = mpSavedBufferBegin;
2086 BufferEnd = mpSavedBufferEnd;
2087 CurBufferPtr = mpSavedCurBufferPtr;
2088
2089 return;
2090 }
2091
Zonr Chang932648d2010-10-13 22:23:56 +08002092 // Allocates and fills storage for an indirect GlobalValue, and returns the
2093 // address.
2094 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002095 const uint8_t *Buffer, size_t Size,
2096 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002097 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002098 memcpy(IndGV, Buffer, Size);
2099 return IndGV;
2100 }
2101
Zonr Chang932648d2010-10-13 22:23:56 +08002102 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002103 void emitLabel(llvm::MCSymbol *Label) {
2104 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002105 return;
2106 }
2107
Zonr Chang932648d2010-10-13 22:23:56 +08002108 // Allocate memory for a global. Unlike allocateSpace, this method does not
2109 // allocate memory in the current output buffer, because a global may live
2110 // longer than the current function.
2111 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2112 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002113 return mpMemMgr->allocateGlobal(Size, Alignment);
2114 }
2115
Zonr Chang932648d2010-10-13 22:23:56 +08002116 // This should be called by the target when a new basic block is about to be
2117 // emitted. This way the MCE knows where the start of the block is, and can
2118 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002119 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002120 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002121 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2122 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2123 return;
2124 }
2125
Zonr Chang932648d2010-10-13 22:23:56 +08002126 // Whenever a relocatable address is needed, it should be noted with this
2127 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002128 void addRelocation(const llvm::MachineRelocation &MR) {
2129 mRelocations.push_back(MR);
2130 return;
2131 }
2132
Zonr Chang932648d2010-10-13 22:23:56 +08002133 // Return the address of the @Index entry in the constant pool that was
2134 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002135 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2136 assert(Index < mpConstantPool->getConstants().size() &&
2137 "Invalid constant pool index!");
2138 return mConstPoolAddresses[Index];
2139 }
2140
Zonr Chang932648d2010-10-13 22:23:56 +08002141 // Return the address of the jump table with index @Index in the function
2142 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002143 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002144 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002145 mpJumpTable->getJumpTables();
2146
Zonr Chang932648d2010-10-13 22:23:56 +08002147 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002148
2149 unsigned int Offset = 0;
2150 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2151
Zonr Chang932648d2010-10-13 22:23:56 +08002152 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002153 Offset += JT[i].MBBs.size();
2154 Offset *= EntrySize;
2155
Zonr Chang932648d2010-10-13 22:23:56 +08002156 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002157 }
2158
Zonr Chang932648d2010-10-13 22:23:56 +08002159 // Return the address of the specified MachineBasicBlock, only usable after
2160 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002161 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2162 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002163 mMBBLocations[MBB->getNumber()] &&
2164 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002165 return mMBBLocations[MBB->getNumber()];
2166 }
2167
Zonr Chang932648d2010-10-13 22:23:56 +08002168 // Return the address of the specified LabelID, only usable after the
2169 // LabelID has been emitted.
2170 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002171 assert(mLabelLocations.count(Label) && "Label not emitted!");
2172 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002173 }
2174
Zonr Chang932648d2010-10-13 22:23:56 +08002175 // Specifies the MachineModuleInfo object. This is used for exception
2176 // handling purposes.
2177 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002178 mpMMI = Info;
2179 return;
2180 }
2181
Zonr Chang932648d2010-10-13 22:23:56 +08002182 void updateFunctionStub(const llvm::Function *F) {
2183 // Get the empty stub we generated earlier.
2184 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002185 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002186 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002187 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002188 else
2189 return;
2190
Zonr Chang932648d2010-10-13 22:23:56 +08002191 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002192
2193 assert(Addr != Stub &&
2194 "Function must have non-stub address to be updated.");
2195
Zonr Chang932648d2010-10-13 22:23:56 +08002196 // Tell the target jit info to rewrite the stub at the specified address,
2197 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002198 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2199 startGVStub(Stub, SL.Size);
2200 mpTJI->emitFunctionStub(F, Addr, *this);
2201 finishGVStub();
2202
Zonr Chang932648d2010-10-13 22:23:56 +08002203 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2204 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002205
2206 PendingFunctions.erase(I);
2207
2208 return;
2209 }
2210
Zonr Chang932648d2010-10-13 22:23:56 +08002211 // Once you finish the compilation on a translation unit, you can call this
2212 // function to recycle the memory (which is used at compilation time and not
2213 // needed for runtime).
2214 //
2215 // NOTE: You should not call this funtion until the code-gen passes for a
2216 // given module is done. Otherwise, the results is undefined and may
2217 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002218 void releaseUnnecessary() {
2219 mMBBLocations.clear();
2220 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002221 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002222 mFunctionToLazyStubMap.clear();
2223 GlobalToIndirectSymMap.clear();
2224 ExternalFnToStubMap.clear();
2225 PendingFunctions.clear();
2226
2227 return;
2228 }
2229
2230 void reset() {
2231 releaseUnnecessary();
2232
2233 mpSymbolLookupFn = NULL;
2234 mpSymbolLookupContext = NULL;
2235
2236 mpTJI = NULL;
2237 mpTD = NULL;
2238
Zonr Chang932648d2010-10-13 22:23:56 +08002239 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2240 E = mEmittedFunctions.end();
2241 I != E;
2242 I++)
2243 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002244 delete I->second;
2245 mEmittedFunctions.clear();
2246
2247 mpMemMgr->reset();
2248
2249 return;
2250 }
2251
Zonr Chang932648d2010-10-13 22:23:56 +08002252 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002253 return lookup( llvm::StringRef(Name) );
2254 }
2255
Zonr Chang932648d2010-10-13 22:23:56 +08002256 void *lookup(const llvm::StringRef &Name) {
2257 EmittedFunctionsMapTy::const_iterator I =
2258 mEmittedFunctions.find(Name.str());
2259 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002260 return NULL;
2261 else
2262 return I->second->Code;
2263 }
2264
Zonr Chang932648d2010-10-13 22:23:56 +08002265 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002266 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002267 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002268 int functionCount = mEmittedFunctions.size();
2269
Zonr Chang932648d2010-10-13 22:23:56 +08002270 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002271 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002272 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002273 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002274 if (functions)
2275 for (EmittedFunctionsMapTy::const_iterator
2276 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2277 (I != E) && (functionCount > 0);
2278 I++, functionCount--)
2279 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002280
2281 return;
2282 }
2283
Zonr Chang932648d2010-10-13 22:23:56 +08002284 void getFunctionBinary(BCCchar *label,
2285 BCCvoid **base,
2286 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002287 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002288 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002289 *base = NULL;
2290 *length = 0;
2291 } else {
2292 *base = I->second->Code;
2293 *length = I->second->Size;
2294 }
2295 return;
2296 }
2297
2298 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002299 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002300#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002301 delete mpAsmInfo;
2302 delete mpDisassmbler;
2303 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002304#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002305 return;
2306 }
Zonr Chang932648d2010-10-13 22:23:56 +08002307 };
2308 // End of Class CodeEmitter
2309 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002310
Zonr Chang932648d2010-10-13 22:23:56 +08002311 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002312 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002313 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002314 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2315 return mCodeEmitter.get();
2316 }
2317
2318 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002319 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002320
Zonr Chang932648d2010-10-13 22:23:56 +08002321 llvm::LLVMContext *mContext;
2322 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002323
2324 bool mTypeInformationPrepared;
2325 std::vector<const llvm::Type*> mTypes;
2326
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002327 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002328 Compiler()
2329 : mpSymbolLookupFn(NULL),
2330 mpSymbolLookupContext(NULL),
2331 mContext(NULL),
2332 mModule(NULL) {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002333 llvm::remove_fatal_error_handler();
2334 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002335 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002336 return;
2337 }
2338
Zonr Chang932648d2010-10-13 22:23:56 +08002339 // interface for BCCscript::registerSymbolCallback()
2340 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002341 mpSymbolLookupFn = pFn;
2342 mpSymbolLookupContext = pContext;
2343 return;
2344 }
2345
Zonr Chang932648d2010-10-13 22:23:56 +08002346 int loadModule(const char *bitcode, size_t bitcodeSize) {
2347 llvm::MemoryBuffer *SB = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002348
Zonr Chang932648d2010-10-13 22:23:56 +08002349 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002350 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002351
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002352 GlobalInitialization();
2353
Zonr Chang932648d2010-10-13 22:23:56 +08002354 // Package input to object MemoryBuffer
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002355 SB = llvm::MemoryBuffer::getMemBuffer(
2356 llvm::StringRef(bitcode, bitcodeSize));
Zonr Chang932648d2010-10-13 22:23:56 +08002357 if (SB == NULL) {
Shih-wei Liao7a0e42a2010-05-11 03:41:56 -07002358 LOGE("Error reading input Bitcode into memory");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002359 setError("Error reading input Bitcode into memory");
2360 goto on_bcc_load_module_error;
2361 }
2362
Zonr Chang932648d2010-10-13 22:23:56 +08002363 // Read the input Bitcode as a Module
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002364 mModule = llvm::ParseBitcodeFile(SB, *mContext, &mError);
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002365
Zonr Chang932648d2010-10-13 22:23:56 +08002366 on_bcc_load_module_error:
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002367 if (SB)
2368 delete SB;
2369
2370 return hasError();
2371 }
2372
Zonr Chang932648d2010-10-13 22:23:56 +08002373 // interace for bccCompileScript()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002374 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002375 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002376
Zonr Chang932648d2010-10-13 22:23:56 +08002377 llvm::TargetMachine *TM = NULL;
2378 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002379 std::string FeaturesStr;
2380
Zonr Chang932648d2010-10-13 22:23:56 +08002381 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002382
Zonr Chang932648d2010-10-13 22:23:56 +08002383 const llvm::NamedMDNode *PragmaMetadata;
2384 const llvm::NamedMDNode *ExportVarMetadata;
2385 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002386
Zonr Chang932648d2010-10-13 22:23:56 +08002387 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002388 return 0;
2389
Zonr Chang932648d2010-10-13 22:23:56 +08002390 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002391 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002392 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002393 goto on_bcc_compile_error;
2394
Zonr Chang932648d2010-10-13 22:23:56 +08002395 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002396 llvm::SubtargetFeatures F;
2397 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002398 for (std::vector<std::string>::const_iterator I = Features.begin(),
2399 E = Features.end();
2400 I != E;
2401 I++)
2402 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002403 FeaturesStr = F.getString();
2404 }
2405
2406 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002407 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002408 setError("Failed to create target machine implementation for the"
2409 " specified triple '" + Triple + "'");
2410 goto on_bcc_compile_error;
2411 }
2412
Zonr Chang932648d2010-10-13 22:23:56 +08002413 // Create memory manager for creation of code emitter later.
2414 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002415 setError("Failed to startup memory management for further compilation");
2416 goto on_bcc_compile_error;
2417 }
2418
Zonr Chang932648d2010-10-13 22:23:56 +08002419 // Create code emitter
2420 if (!mCodeEmitter.get()) {
2421 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002422 setError("Failed to create machine code emitter to complete"
2423 " the compilation");
2424 goto on_bcc_compile_error;
2425 }
2426 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002427 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002428 mCodeEmitter->reset();
2429 }
2430
2431 mCodeEmitter->setTargetMachine(*TM);
2432 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2433 mpSymbolLookupContext);
2434
Zonr Chang932648d2010-10-13 22:23:56 +08002435 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002436 TD = new llvm::TargetData(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08002437 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002438 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08002439 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002440
Zonr Chang932648d2010-10-13 22:23:56 +08002441 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
2442 *mCodeEmitter,
2443 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002444 setError("The machine code emission is not supported by BCC on target '"
2445 + Triple + "'");
2446 goto on_bcc_compile_error;
2447 }
2448
Zonr Chang932648d2010-10-13 22:23:56 +08002449 // Run the pass (the code emitter) on every non-declaration function in the
2450 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002451 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08002452 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
2453 I != E;
2454 I++)
2455 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002456 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002457
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002458 CodeGenPasses->doFinalization();
2459
Zonr Chang932648d2010-10-13 22:23:56 +08002460 // Copy the global address mapping from code emitter and remapping
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002461 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
Zonr Chang932648d2010-10-13 22:23:56 +08002462 if (ExportVarMetadata) {
2463 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2464 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2465 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2466 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2467 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002468 llvm::StringRef ExportVarName =
2469 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08002470 CodeEmitter::global_addresses_const_iterator I, E;
2471 for (I = mCodeEmitter->global_address_begin(),
2472 E = mCodeEmitter->global_address_end();
2473 I != E;
2474 I++) {
2475 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002476 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08002477 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002478 mExportVars.push_back(I->second);
2479 break;
2480 }
2481 }
Zonr Chang932648d2010-10-13 22:23:56 +08002482 if (I != mCodeEmitter->global_address_end())
2483 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002484 }
2485 }
Zonr Chang932648d2010-10-13 22:23:56 +08002486 // if here, the global variable record in metadata is not found, make an
2487 // empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002488 mExportVars.push_back(NULL);
2489 }
2490 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
2491 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002492 }
2493
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002494 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
Zonr Chang932648d2010-10-13 22:23:56 +08002495 if (ExportFuncMetadata) {
2496 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2497 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2498 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2499 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2500 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002501 llvm::StringRef ExportFuncName =
2502 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2503 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
2504 }
2505 }
2506 }
2507 }
2508
Zonr Chang932648d2010-10-13 22:23:56 +08002509 // Tell code emitter now can release the memory using during the JIT since
2510 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002511 mCodeEmitter->releaseUnnecessary();
2512
Zonr Chang932648d2010-10-13 22:23:56 +08002513 // Finally, read pragma information from the metadata node of the @Module if
2514 // any.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002515 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
Zonr Chang932648d2010-10-13 22:23:56 +08002516 if (PragmaMetadata)
2517 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
2518 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
2519 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002520 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08002521 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
2522 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002523
Zonr Chang932648d2010-10-13 22:23:56 +08002524 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002525 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
2526 llvm::StringRef PragmaName =
2527 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
2528 llvm::StringRef PragmaValue =
2529 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
2530
Zonr Chang932648d2010-10-13 22:23:56 +08002531 mPragmas.push_back(
2532 std::make_pair(std::string(PragmaName.data(),
2533 PragmaName.size()),
2534 std::string(PragmaValue.data(),
2535 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002536 }
2537 }
2538 }
2539
2540 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08002541 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002542 if (CodeGenPasses) {
2543 delete CodeGenPasses;
2544 } else if (TD) {
2545 delete TD;
2546 }
2547 if (TM)
2548 delete TM;
2549
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002550 if (mError.empty()) {
2551 return false;
2552 }
2553
Zonr Chang932648d2010-10-13 22:23:56 +08002554 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002555 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002556 }
2557
Zonr Chang932648d2010-10-13 22:23:56 +08002558 // interface for bccGetScriptInfoLog()
2559 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002560 return const_cast<char*>(mError.c_str());
2561 }
2562
Zonr Chang932648d2010-10-13 22:23:56 +08002563 // interface for bccGetScriptLabel()
2564 void *lookup(const char *name) {
2565 void *addr = NULL;
2566 if (mCodeEmitter.get())
2567 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002568 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002569 return addr;
2570 }
2571
Zonr Chang932648d2010-10-13 22:23:56 +08002572 // Interface for bccGetExportVars()
2573 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002574 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002575 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002576 int varCount = mExportVars.size();
2577
Zonr Chang932648d2010-10-13 22:23:56 +08002578 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002579 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002580 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002581 varCount = maxVarCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002582 if (vars)
2583 for (ExportVarList::const_iterator I = mExportVars.begin(),
2584 E = mExportVars.end();
2585 I != E;
2586 I++)
2587 *vars++ = *I;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002588
2589 return;
2590 }
2591
Zonr Chang932648d2010-10-13 22:23:56 +08002592 // Interface for bccGetExportFuncs()
2593 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002594 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002595 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002596 int funcCount = mExportFuncs.size();
2597
Zonr Chang932648d2010-10-13 22:23:56 +08002598 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002599 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002600 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002601 funcCount = maxFuncCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002602 if (funcs)
2603 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
2604 E = mExportFuncs.end();
2605 I != E;
2606 I++)
2607 *funcs++ = *I;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002608
2609 return;
2610 }
2611
Zonr Chang932648d2010-10-13 22:23:56 +08002612 // Interface for bccGetPragmas()
2613 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002614 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002615 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002616 int stringCount = mPragmas.size() * 2;
2617
Zonr Chang932648d2010-10-13 22:23:56 +08002618 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002619 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002620 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002621 stringCount = maxStringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002622 if (strings)
2623 for (PragmaList::const_iterator it = mPragmas.begin();
2624 stringCount > 0;
2625 stringCount -= 2, it++) {
2626 *strings++ = const_cast<BCCchar*>(it->first.c_str());
2627 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002628 }
2629
2630 return;
2631 }
2632
Zonr Chang932648d2010-10-13 22:23:56 +08002633 // Interface for bccGetFunctions()
2634 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002635 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002636 BCCchar **functions) {
2637 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002638 mCodeEmitter->getFunctionNames(actualFunctionCount,
2639 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002640 functions);
2641 else
2642 *actualFunctionCount = 0;
2643
2644 return;
2645 }
2646
Zonr Chang932648d2010-10-13 22:23:56 +08002647 // Interface for bccGetFunctionBinary()
2648 void getFunctionBinary(BCCchar *function,
2649 BCCvoid **base,
2650 BCCsizei *length) {
2651 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002652 mCodeEmitter->getFunctionBinary(function, base, length);
2653 } else {
2654 *base = NULL;
2655 *length = 0;
2656 }
2657 return;
2658 }
2659
Zonr Chang932648d2010-10-13 22:23:56 +08002660 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002661 return mModule;
2662 }
2663
Zonr Chang932648d2010-10-13 22:23:56 +08002664 inline const std::vector<const llvm::Type*> &getTypes() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002665 return mTypes;
2666 }
2667
2668 ~Compiler() {
2669 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08002670 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002671 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002672 return;
2673 }
Zonr Chang932648d2010-10-13 22:23:56 +08002674};
2675// End of Class Compiler
2676////////////////////////////////////////////////////////////////////////////////
2677
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002678
2679bool Compiler::GlobalInitialized = false;
2680
Zonr Chang932648d2010-10-13 22:23:56 +08002681// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002682llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
2683
2684std::string Compiler::Triple;
2685
2686std::string Compiler::CPU;
2687
2688std::vector<std::string> Compiler::Features;
2689
Zonr Chang932648d2010-10-13 22:23:56 +08002690// The named of metadata node that pragma resides (should be synced with
2691// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002692const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
2693
Zonr Chang932648d2010-10-13 22:23:56 +08002694// The named of metadata node that export variable name resides (should be
2695// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002696const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
2697
Zonr Chang932648d2010-10-13 22:23:56 +08002698// The named of metadata node that export function name resides (should be
2699// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002700const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
2701
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002702struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08002703 //////////////////////////////////////////////////////////////////////////////
2704 // Part I. Compiler
2705 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002706 Compiler compiler;
2707
Zonr Chang932648d2010-10-13 22:23:56 +08002708 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002709 compiler.registerSymbolCallback(pFn, pContext);
2710 }
2711
Zonr Chang932648d2010-10-13 22:23:56 +08002712 //////////////////////////////////////////////////////////////////////////////
2713 // Part II. Logistics & Error handling
2714 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002715 BCCscript() {
2716 bccError = BCC_NO_ERROR;
2717 }
2718
2719 ~BCCscript() {
2720 }
2721
2722 void setError(BCCenum error) {
2723 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
2724 bccError = error;
2725 }
2726 }
2727
2728 BCCenum getError() {
2729 BCCenum result = bccError;
2730 bccError = BCC_NO_ERROR;
2731 return result;
2732 }
2733
2734 BCCenum bccError;
2735};
2736
2737
2738extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002739BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002740 return new BCCscript();
2741}
2742
2743extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002744BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002745 return script->getError();
2746}
2747
2748extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002749void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002750 delete script;
2751}
2752
2753extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002754void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002755 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08002756 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002757 script->registerSymbolCallback(pFn, pContext);
2758}
2759
2760extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002761void bccScriptBitcode(BCCscript *script,
2762 const BCCchar *bitcode,
2763 BCCint size) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002764 script->compiler.loadModule(bitcode, size);
2765}
2766
2767extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002768void bccCompileScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002769 int result = script->compiler.compile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002770 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002771 script->setError(BCC_INVALID_OPERATION);
2772}
2773
2774extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002775void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002776 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08002777 BCCsizei *length,
2778 BCCchar *infoLog) {
2779 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002780 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002781 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002782 *length = messageLength;
2783
2784 if (infoLog && maxLength > 0) {
2785 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
2786 memcpy(infoLog, message, trimmedLength);
2787 infoLog[trimmedLength] = 0;
2788 }
2789}
2790
2791extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002792void bccGetScriptLabel(BCCscript *script,
2793 const BCCchar *name,
2794 BCCvoid **address) {
2795 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002796 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002797 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002798 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002799 script->setError(BCC_INVALID_VALUE);
2800}
2801
2802extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002803void bccGetExportVars(BCCscript *script,
2804 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002805 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002806 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002807 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
2808}
2809
2810extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002811void bccGetExportFuncs(BCCscript *script,
2812 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002813 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002814 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002815 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
2816}
2817
2818extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002819void bccGetPragmas(BCCscript *script,
2820 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002821 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002822 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002823 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
2824}
2825
2826extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002827void bccGetFunctions(BCCscript *script,
2828 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002829 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002830 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002831 script->compiler.getFunctions(actualFunctionCount,
2832 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002833 functions);
2834}
2835
2836extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002837void bccGetFunctionBinary(BCCscript *script,
2838 BCCchar *function,
2839 BCCvoid **base,
2840 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002841 script->compiler.getFunctionBinary(function, base, length);
2842}
2843
2844struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08002845 const Compiler *compiler;
2846 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002847};
2848
Zonr Chang932648d2010-10-13 22:23:56 +08002849} // namespace bcc