blob: 48734ff896a9948c82faa04de520dce256c097ff [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"
Zonr Chang97f5e612010-10-22 20:38:26 +0800113#include "llvm/Linker.h"
Zonr Chang932648d2010-10-13 22:23:56 +0800114#include "llvm/Module.h"
115#include "llvm/Function.h"
116#include "llvm/Constant.h"
117#include "llvm/Constants.h"
118#include "llvm/Instruction.h"
119#include "llvm/PassManager.h"
120#include "llvm/LLVMContext.h"
121#include "llvm/GlobalValue.h"
122#include "llvm/Instructions.h"
123#include "llvm/OperandTraits.h"
124#include "llvm/TypeSymbolTable.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700125
126// System
Zonr Chang932648d2010-10-13 22:23:56 +0800127#include "llvm/System/Host.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700128
129// ADT
Zonr Chang932648d2010-10-13 22:23:56 +0800130#include "llvm/ADT/APInt.h"
131#include "llvm/ADT/APFloat.h"
132#include "llvm/ADT/DenseMap.h"
133#include "llvm/ADT/ValueMap.h"
134#include "llvm/ADT/StringMap.h"
135#include "llvm/ADT/OwningPtr.h"
136#include "llvm/ADT/SmallString.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700137
138// Target
Zonr Chang932648d2010-10-13 22:23:56 +0800139#include "llvm/Target/TargetData.h"
140#include "llvm/Target/TargetSelect.h"
141#include "llvm/Target/TargetOptions.h"
142#include "llvm/Target/TargetMachine.h"
143#include "llvm/Target/TargetJITInfo.h"
144#include "llvm/Target/TargetRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700145#include "llvm/Target/SubtargetFeature.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700146
147// Support
Zonr Chang932648d2010-10-13 22:23:56 +0800148#include "llvm/Support/Casting.h"
149#include "llvm/Support/raw_ostream.h"
150#include "llvm/Support/ValueHandle.h"
151#include "llvm/Support/MemoryBuffer.h"
152#include "llvm/Support/MemoryObject.h"
153#include "llvm/Support/ManagedStatic.h"
154#include "llvm/Support/ErrorHandling.h"
155#include "llvm/Support/StandardPasses.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700156#include "llvm/Support/FormattedStream.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700157
158// Bitcode
Zonr Chang932648d2010-10-13 22:23:56 +0800159#include "llvm/Bitcode/ReaderWriter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700160
161// CodeGen
Zonr Chang932648d2010-10-13 22:23:56 +0800162#include "llvm/CodeGen/Passes.h"
163#include "llvm/CodeGen/JITCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700164#include "llvm/CodeGen/MachineFunction.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700165#include "llvm/CodeGen/RegAllocRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700166#include "llvm/CodeGen/SchedulerRegistry.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700167#include "llvm/CodeGen/MachineRelocation.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700168#include "llvm/CodeGen/MachineModuleInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700169#include "llvm/CodeGen/MachineCodeEmitter.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700170#include "llvm/CodeGen/MachineConstantPool.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700171#include "llvm/CodeGen/MachineJumpTableInfo.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700172
173// ExecutionEngine
174#include "llvm/ExecutionEngine/GenericValue.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700175#include "llvm/ExecutionEngine/JITMemoryManager.h"
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700176
177
Zonr Chang932648d2010-10-13 22:23:56 +0800178//
179// Compilation class that suits Android's needs.
180// (Support: no argument passed, ...)
181//
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700182namespace bcc {
183
184class Compiler {
Zonr Chang932648d2010-10-13 22:23:56 +0800185 // This part is designed to be orthogonal to those exported bcc*() functions
186 // implementation and internal struct BCCscript.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700187
Zonr Chang932648d2010-10-13 22:23:56 +0800188 //////////////////////////////////////////////////////////////////////////////
189 // The variable section below (e.g., Triple, CodeGenOptLevel)
190 // is initialized in GlobalInitialization()
191 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700192 static bool GlobalInitialized;
193
Zonr Chang932648d2010-10-13 22:23:56 +0800194 // If given, this will be the name of the target triple to compile for.
195 // If not given, the initial values defined in this file will be used.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700196 static std::string Triple;
197
198 static llvm::CodeGenOpt::Level CodeGenOptLevel;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700199
Zonr Chang932648d2010-10-13 22:23:56 +0800200 // End of section of GlobalInitializing variables
201 //////////////////////////////////////////////////////////////////////////////
202
203 // If given, the name of the target CPU to generate code for.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700204 static std::string CPU;
205
Zonr Chang932648d2010-10-13 22:23:56 +0800206 // The list of target specific features to enable or disable -- this should
207 // be a list of strings starting with '+' (enable) or '-' (disable).
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700208 static std::vector<std::string> Features;
209
210 struct Runtime {
Zonr Chang932648d2010-10-13 22:23:56 +0800211 const char *mName;
212 void *mPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700213 };
214 static struct Runtime Runtimes[];
215
216 static void GlobalInitialization() {
Zonr Chang932648d2010-10-13 22:23:56 +0800217 if (GlobalInitialized)
218 return;
Shih-wei Liaobe5c5312010-05-09 05:30:09 -0700219
Zonr Chang932648d2010-10-13 22:23:56 +0800220 // if (!llvm::llvm_is_multithreaded())
221 // llvm::llvm_start_multithreaded();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700222
Zonr Chang932648d2010-10-13 22:23:56 +0800223 // Set Triple, CPU and Features here
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700224 Triple = TARGET_TRIPLE_STRING;
225
Zonr Chang932648d2010-10-13 22:23:56 +0800226 // TODO(zonr): NEON for JIT
227 // Features.push_back("+neon");
228 // Features.push_back("+vmlx");
229 // Features.push_back("+neonfp");
Shih-wei Liao3cf39d12010-04-29 19:30:51 -0700230 Features.push_back("+vfp3");
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700231
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700232#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
233 LLVMInitializeARMTargetInfo();
234 LLVMInitializeARMTarget();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700235#if defined(USE_DISASSEMBLER)
236 LLVMInitializeARMDisassembler();
237 LLVMInitializeARMAsmPrinter();
238#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700239#endif
240
241#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
242 LLVMInitializeX86TargetInfo();
243 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700244#if defined(USE_DISASSEMBLER)
245 LLVMInitializeX86Disassembler();
246 LLVMInitializeX86AsmPrinter();
247#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700248#endif
249
250#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
251 LLVMInitializeX86TargetInfo();
252 LLVMInitializeX86Target();
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700253#if defined(USE_DISASSEMBLER)
254 LLVMInitializeX86Disassembler();
255 LLVMInitializeX86AsmPrinter();
256#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700257#endif
258
Zonr Chang932648d2010-10-13 22:23:56 +0800259 // -O0: llvm::CodeGenOpt::None
260 // -O1: llvm::CodeGenOpt::Less
261 // -O2: llvm::CodeGenOpt::Default
262 // -O3: llvm::CodeGenOpt::Aggressive
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700263 CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
264
Zonr Chang932648d2010-10-13 22:23:56 +0800265 // Below are the global settings to LLVM
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700266
Zonr Chang932648d2010-10-13 22:23:56 +0800267 // Disable frame pointer elimination optimization
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700268 llvm::NoFramePointerElim = false;
269
Zonr Chang932648d2010-10-13 22:23:56 +0800270 // Use hardfloat ABI
271 //
272 // FIXME: Need to detect the CPU capability and decide whether to use
273 // softfp. To use softfp, change following 2 lines to
274 //
275 // llvm::FloatABIType = llvm::FloatABI::Soft;
276 // llvm::UseSoftFloat = true;
277 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700278 llvm::FloatABIType = llvm::FloatABI::Soft;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700279 llvm::UseSoftFloat = false;
280
Zonr Chang932648d2010-10-13 22:23:56 +0800281 // BCC needs all unknown symbols resolved at JIT/compilation time.
282 // So we don't need any dynamic relocation model.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700283 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
284
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700285#if defined(DEFAULT_X64_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +0800286 // Data address in X86_64 architecture may reside in a far-away place
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700287 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
288#else
Zonr Chang932648d2010-10-13 22:23:56 +0800289 // This is set for the linker (specify how large of the virtual addresses
290 // we can access for all unknown symbols.)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700291 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small);
292#endif
293
Zonr Chang932648d2010-10-13 22:23:56 +0800294 // Register the scheduler
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700295 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
296
Zonr Chang932648d2010-10-13 22:23:56 +0800297 // Register allocation policy:
298 // createFastRegisterAllocator: fast but bad quality
299 // createLinearScanRegisterAllocator: not so fast but good quality
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700300 llvm::RegisterRegAlloc::setDefault
301 ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
Shih-wei Liao16016012010-09-10 17:55:03 -0700302 llvm::createFastRegisterAllocator :
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700303 llvm::createLinearScanRegisterAllocator);
304
305 GlobalInitialized = true;
306 return;
307 }
308
309 static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Zonr Chang932648d2010-10-13 22:23:56 +0800310 std::string *Error = static_cast<std::string*>(UserData);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -0700311 Error->assign(Message);
Nick Kralevichfc97e9f2010-05-17 14:59:16 -0700312 LOGE("%s", Message.c_str());
Zonr Chang932648d2010-10-13 22:23:56 +0800313 exit(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700314 }
315
316 static const llvm::StringRef PragmaMetadataName;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700317 static const llvm::StringRef ExportVarMetadataName;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700318 static const llvm::StringRef ExportFuncMetadataName;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700319
320 private:
Shih-wei Liaoc5611992010-05-09 06:37:55 -0700321 std::string mError;
322
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700323 inline bool hasError() const {
324 return !mError.empty();
325 }
Zonr Chang932648d2010-10-13 22:23:56 +0800326 inline void setError(const char *Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700327 mError.assign(Error); // Copying
328 return;
329 }
Zonr Chang932648d2010-10-13 22:23:56 +0800330 inline void setError(const std::string &Error) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700331 mError = Error;
332 return;
333 }
334
335 typedef std::list< std::pair<std::string, std::string> > PragmaList;
336 PragmaList mPragmas;
337
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700338 typedef std::list<void*> ExportVarList;
339 ExportVarList mExportVars;
340
Shih-wei Liao6bfd5422010-05-07 05:20:22 -0700341 typedef std::list<void*> ExportFuncList;
342 ExportFuncList mExportFuncs;
343
Zonr Chang932648d2010-10-13 22:23:56 +0800344 //////////////////////////////////////////////////////////////////////////////
345 // Memory manager for the code reside in memory
346 //
347 // The memory for our code emitter is very simple and is conforming to the
348 // design decisions of Android RenderScript's Exection Environment:
349 // The code, data, and symbol sizes are limited (currently 100KB.)
350 //
351 // It's very different from typical compiler, which has no limitation
352 // on the code size. How does code emitter know the size of the code
353 // it is about to emit? It does not know beforehand. We want to solve
354 // this without complicating the code emitter too much.
355 //
356 // We solve this by pre-allocating a certain amount of memory,
357 // and then start the code emission. Once the buffer overflows, the emitter
358 // simply discards all the subsequent emission but still has a counter
359 // on how many bytes have been emitted.
360 //
361 // So once the whole emission is done, if there's a buffer overflow,
362 // it re-allocates the buffer with enough size (based on the
363 // counter from previous emission) and re-emit again.
364 //
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700365 class CodeMemoryManager : public llvm::JITMemoryManager {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700366 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800367 // 128 KiB for code
368 static const unsigned int MaxCodeSize = 128 * 1024;
369 // 1 KiB for global offset table (GOT)
370 static const unsigned int MaxGOTSize = 1 * 1024;
371 // 128 KiB for global variable
372 static const unsigned int MaxGlobalVarSize = 128 * 1024;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700373
Zonr Chang932648d2010-10-13 22:23:56 +0800374 //
375 // Our memory layout is as follows:
376 //
377 // The direction of arrows (-> and <-) shows memory's growth direction
378 // when more space is needed.
379 //
380 // @mpCodeMem:
381 // +--------------------------------------------------------------+
382 // | Function Memory ... -> <- ... Stub/GOT |
383 // +--------------------------------------------------------------+
384 // |<------------------ Total: @MaxCodeSize KiB ----------------->|
385 //
386 // Where size of GOT is @MaxGOTSize KiB.
387 //
388 // @mpGVMem:
389 // +--------------------------------------------------------------+
390 // | Global variable ... -> |
391 // +--------------------------------------------------------------+
392 // |<--------------- Total: @MaxGlobalVarSize KiB --------------->|
393 //
394 //
395 // @mCurFuncMemIdx: The current index (starting from 0) of the last byte
396 // of function code's memory usage
397 // @mCurSGMemIdx: The current index (starting from tail) of the last byte
398 // of stub/GOT's memory usage
399 // @mCurGVMemIdx: The current index (starting from tail) of the last byte
400 // of global variable's memory usage
401 //
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700402 uintptr_t mCurFuncMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700403 uintptr_t mCurSGMemIdx;
404 uintptr_t mCurGVMemIdx;
Zonr Chang932648d2010-10-13 22:23:56 +0800405 void *mpCodeMem;
406 void *mpGVMem;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700407
Zonr Chang932648d2010-10-13 22:23:56 +0800408 // GOT Base
409 uint8_t *mpGOTBase;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700410
411 typedef std::map<const llvm::Function*, pair<void* /* start address */,
412 void* /* end address */>
413 > FunctionMapTy;
414 FunctionMapTy mFunctionMap;
415
Zonr Chang932648d2010-10-13 22:23:56 +0800416 inline intptr_t getFreeCodeMemSize() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700417 return mCurSGMemIdx - mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700418 }
Zonr Chang932648d2010-10-13 22:23:56 +0800419 inline uint8_t *getCodeMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700420 return reinterpret_cast<uint8_t*>(mpCodeMem);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700421 }
422
Zonr Chang932648d2010-10-13 22:23:56 +0800423 uint8_t *allocateSGMemory(uintptr_t Size,
424 unsigned Alignment = 1 /* no alignment */) {
425 intptr_t FreeMemSize = getFreeCodeMemSize();
426 if ((FreeMemSize < 0) || (static_cast<uintptr_t>(FreeMemSize) < Size))
427 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700428 return NULL;
429
Zonr Chang932648d2010-10-13 22:23:56 +0800430 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700431 Alignment = 1;
432
Zonr Chang932648d2010-10-13 22:23:56 +0800433 uint8_t *result = getCodeMemBase() + mCurSGMemIdx - Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700434 result = (uint8_t*) (((intptr_t) result) & ~(intptr_t) (Alignment - 1));
435
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700436 mCurSGMemIdx = result - getCodeMemBase();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700437
438 return result;
439 }
440
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700441 inline uintptr_t getFreeGVMemSize() const {
442 return MaxGlobalVarSize - mCurGVMemIdx;
443 }
Zonr Chang932648d2010-10-13 22:23:56 +0800444 inline uint8_t *getGVMemBase() const {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700445 return reinterpret_cast<uint8_t*>(mpGVMem);
446 }
447
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700448 public:
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700449 CodeMemoryManager() : mpCodeMem(NULL), mpGVMem(NULL), mpGOTBase(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700450 reset();
451 std::string ErrMsg;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700452
Shih-wei Liaoc7c9cd52010-09-27 11:23:25 -0700453 mpCodeMem = ::mmap(NULL, MaxCodeSize, PROT_READ | PROT_EXEC,
Ying Wang78db12e2010-09-25 17:48:59 -0700454 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700455 if (mpCodeMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800456 llvm::report_fatal_error("Failed to allocate memory for emitting "
457 "function codes\n" + ErrMsg);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700458
459 mpGVMem = ::mmap(mpCodeMem, MaxGlobalVarSize,
Shih-wei Liaoc7c9cd52010-09-27 11:23:25 -0700460 PROT_READ | PROT_WRITE,
Ying Wang78db12e2010-09-25 17:48:59 -0700461 MAP_PRIVATE | MAP_ANON, -1, 0);
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700462 if (mpGVMem == MAP_FAILED)
Zonr Chang932648d2010-10-13 22:23:56 +0800463 llvm::report_fatal_error("Failed to allocate memory for emitting "
464 "global variables\n" + ErrMsg);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700465
466 return;
467 }
468
Zonr Chang932648d2010-10-13 22:23:56 +0800469 // setMemoryWritable - When code generation is in progress, the code pages
470 // may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700471 void setMemoryWritable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700472 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700473 return;
474 }
475
Zonr Chang932648d2010-10-13 22:23:56 +0800476 // When code generation is done and we're ready to start execution, the
477 // code pages may need permissions changed.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700478 void setMemoryExecutable() {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700479 ::mprotect(mpCodeMem, MaxCodeSize, PROT_READ | PROT_EXEC);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700480 return;
481 }
482
Zonr Chang932648d2010-10-13 22:23:56 +0800483 // Setting this flag to true makes the memory manager garbage values over
484 // freed memory. This is useful for testing and debugging, and is to be
485 // turned on by default in debug mode.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700486 void setPoisonMemory(bool poison) {
Zonr Chang932648d2010-10-13 22:23:56 +0800487 // no effect
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700488 return;
489 }
490
Zonr Chang932648d2010-10-13 22:23:56 +0800491 // Global Offset Table Management
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700492
Zonr Chang932648d2010-10-13 22:23:56 +0800493 // If the current table requires a Global Offset Table, this method is
494 // invoked to allocate it. This method is required to set HasGOT to true.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700495 void AllocateGOT() {
496 assert(mpGOTBase != NULL && "Cannot allocate the GOT multiple times");
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700497 mpGOTBase = allocateSGMemory(MaxGOTSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700498 HasGOT = true;
499 return;
500 }
501
Zonr Chang932648d2010-10-13 22:23:56 +0800502 // If this is managing a Global Offset Table, this method should return a
503 // pointer to its base.
504 uint8_t *getGOTBase() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700505 return mpGOTBase;
506 }
507
Zonr Chang932648d2010-10-13 22:23:56 +0800508 // Main Allocation Functions
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700509
Zonr Chang932648d2010-10-13 22:23:56 +0800510 // When we start JITing a function, the JIT calls this method to allocate a
511 // block of free RWX memory, which returns a pointer to it. If the JIT wants
512 // to request a block of memory of at least a certain size, it passes that
513 // value as ActualSize, and this method returns a block with at least that
514 // much space. If the JIT doesn't know ahead of time how much space it will
515 // need to emit the function, it passes 0 for the ActualSize. In either
516 // case, this method is required to pass back the size of the allocated
517 // block through ActualSize. The JIT will be careful to not write more than
518 // the returned ActualSize bytes of memory.
519 uint8_t *startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) {
520 intptr_t FreeMemSize = getFreeCodeMemSize();
521 if ((FreeMemSize < 0) ||
522 (static_cast<uintptr_t>(FreeMemSize) < ActualSize))
523 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700524 return NULL;
525
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700526 ActualSize = getFreeCodeMemSize();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700527 return (getCodeMemBase() + mCurFuncMemIdx);
528 }
529
Zonr Chang932648d2010-10-13 22:23:56 +0800530 // This method is called by the JIT to allocate space for a function stub
531 // (used to handle limited branch displacements) while it is JIT compiling a
532 // function. For example, if foo calls bar, and if bar either needs to be
533 // lazily compiled or is a native function that exists too far away from the
534 // call site to work, this method will be used to make a thunk for it. The
535 // stub should be "close" to the current function body, but should not be
536 // included in the 'actualsize' returned by startFunctionBody.
537 uint8_t *allocateStub(const llvm::GlobalValue *F, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700538 unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700539 return allocateSGMemory(StubSize, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700540 }
541
Zonr Chang932648d2010-10-13 22:23:56 +0800542 // This method is called when the JIT is done codegen'ing the specified
543 // function. At this point we know the size of the JIT compiled function.
544 // This passes in FunctionStart (which was returned by the startFunctionBody
545 // method) and FunctionEnd which is a pointer to the actual end of the
546 // function. This method should mark the space allocated and remember where
547 // it is in case the client wants to deallocate it.
548 void endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
549 uint8_t *FunctionEnd) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700550 assert(FunctionEnd > FunctionStart);
551 assert(FunctionStart == (getCodeMemBase() + mCurFuncMemIdx) &&
552 "Mismatched function start/end!");
553
Zonr Chang932648d2010-10-13 22:23:56 +0800554 // Advance the pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700555 intptr_t FunctionCodeSize = FunctionEnd - FunctionStart;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700556 assert(FunctionCodeSize <= getFreeCodeMemSize() &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700557 "Code size excess the limitation!");
558 mCurFuncMemIdx += FunctionCodeSize;
559
Zonr Chang932648d2010-10-13 22:23:56 +0800560 // Record there's a function in our memory start from @FunctionStart
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700561 assert(mFunctionMap.find(F) == mFunctionMap.end() &&
562 "Function already emitted!");
Zonr Chang932648d2010-10-13 22:23:56 +0800563 mFunctionMap.insert(
564 std::make_pair<const llvm::Function*, std::pair<void*, void*> >(
565 F, std::make_pair(FunctionStart, FunctionEnd)));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700566
567 return;
568 }
569
Zonr Chang932648d2010-10-13 22:23:56 +0800570 // Allocate a (function code) memory block of the given size. This method
571 // cannot be called between calls to startFunctionBody and endFunctionBody.
572 uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
573 if (getFreeCodeMemSize() < Size)
574 // The code size excesses our limit
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700575 return NULL;
576
Zonr Chang932648d2010-10-13 22:23:56 +0800577 if (Alignment == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700578 Alignment = 1;
579
Zonr Chang932648d2010-10-13 22:23:56 +0800580 uint8_t *result = getCodeMemBase() + mCurFuncMemIdx;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700581 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800582 ~(intptr_t) (Alignment - 1));
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700583
584 mCurFuncMemIdx = (result + Size) - getCodeMemBase();
585
586 return result;
587 }
588
Zonr Chang932648d2010-10-13 22:23:56 +0800589 // Allocate memory for a global variable.
590 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700591 if (getFreeGVMemSize() < Size) {
Zonr Chang932648d2010-10-13 22:23:56 +0800592 // The code size excesses our limit
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700593 LOGE("No Global Memory");
594 return NULL;
595 }
596
Zonr Chang932648d2010-10-13 22:23:56 +0800597 if (Alignment == 0)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700598 Alignment = 1;
599
Zonr Chang932648d2010-10-13 22:23:56 +0800600 uint8_t *result = getGVMemBase() + mCurGVMemIdx;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700601 result = (uint8_t*) (((intptr_t) result + Alignment - 1) &
Zonr Chang932648d2010-10-13 22:23:56 +0800602 ~(intptr_t) (Alignment - 1));
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700603
604 mCurGVMemIdx = (result + Size) - getGVMemBase();
605
606 return result;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700607 }
608
Zonr Chang932648d2010-10-13 22:23:56 +0800609 // Free the specified function body. The argument must be the return value
610 // from a call to startFunctionBody() that hasn't been deallocated yet. This
611 // is never called when the JIT is currently emitting a function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700612 void deallocateFunctionBody(void *Body) {
Zonr Chang932648d2010-10-13 22:23:56 +0800613 // linear search
614 uint8_t *FunctionStart = NULL, *FunctionEnd = NULL;
615 for (FunctionMapTy::iterator I = mFunctionMap.begin(),
616 E = mFunctionMap.end();
617 I != E;
618 I++)
619 if (I->second.first == Body) {
620 FunctionStart = reinterpret_cast<uint8_t*>(I->second.first);
621 FunctionEnd = reinterpret_cast<uint8_t*>(I->second.second);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700622 break;
Zonr Chang932648d2010-10-13 22:23:56 +0800623 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700624
Zonr Chang932648d2010-10-13 22:23:56 +0800625 assert((FunctionStart == NULL) && "Memory is never allocated!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700626
Zonr Chang932648d2010-10-13 22:23:56 +0800627 // free the memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700628 intptr_t SizeNeedMove = (getCodeMemBase() + mCurFuncMemIdx) - FunctionEnd;
629
630 assert(SizeNeedMove >= 0 &&
631 "Internal error: CodeMemoryManager::mCurFuncMemIdx may not"
632 " be correctly calculated!");
633
Zonr Chang932648d2010-10-13 22:23:56 +0800634 if (SizeNeedMove > 0)
635 // there's data behind deallocating function
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700636 ::memmove(FunctionStart, FunctionEnd, SizeNeedMove);
637 mCurFuncMemIdx -= (FunctionEnd - FunctionStart);
638
639 return;
640 }
641
Zonr Chang932648d2010-10-13 22:23:56 +0800642 // When we finished JITing the function, if exception handling is set, we
643 // emit the exception table.
644 uint8_t *startExceptionTable(const llvm::Function *F,
645 uintptr_t &ActualSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700646 assert(false && "Exception is not allowed in our language specification");
647 return NULL;
648 }
649
Zonr Chang932648d2010-10-13 22:23:56 +0800650 // This method is called when the JIT is done emitting the exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700651 void endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
Zonr Chang932648d2010-10-13 22:23:56 +0800652 uint8_t *TableEnd, uint8_t *FrameRegister) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700653 assert(false && "Exception is not allowed in our language specification");
654 return;
655 }
656
Zonr Chang932648d2010-10-13 22:23:56 +0800657 // Free the specified exception table's memory. The argument must be the
658 // return value from a call to startExceptionTable() that hasn't been
659 // deallocated yet. This is never called when the JIT is currently emitting
660 // an exception table.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700661 void deallocateExceptionTable(void *ET) {
662 assert(false && "Exception is not allowed in our language specification");
663 return;
664 }
665
Zonr Chang932648d2010-10-13 22:23:56 +0800666 // Below are the methods we create
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700667 void reset() {
668 mpGOTBase = NULL;
669 HasGOT = false;
670
671 mCurFuncMemIdx = 0;
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700672 mCurSGMemIdx = MaxCodeSize - 1;
673 mCurGVMemIdx = 0;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700674
675 mFunctionMap.clear();
676
677 return;
678 }
679
680 ~CodeMemoryManager() {
Zonr Chang932648d2010-10-13 22:23:56 +0800681 if (mpCodeMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700682 ::munmap(mpCodeMem, MaxCodeSize);
Zonr Chang932648d2010-10-13 22:23:56 +0800683 if (mpGVMem != NULL)
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -0700684 ::munmap(mpGVMem, MaxGlobalVarSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700685 return;
686 }
Zonr Chang932648d2010-10-13 22:23:56 +0800687 };
688 // End of class CodeMemoryManager
689 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700690
Zonr Chang932648d2010-10-13 22:23:56 +0800691 // The memory manager for code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700692 llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
Zonr Chang932648d2010-10-13 22:23:56 +0800693 CodeMemoryManager *createCodeMemoryManager() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700694 mCodeMemMgr.reset(new CodeMemoryManager());
695 return mCodeMemMgr.get();
696 }
697
Zonr Chang932648d2010-10-13 22:23:56 +0800698 //////////////////////////////////////////////////////////////////////////////
699 // Code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700700 class CodeEmitter : public llvm::JITCodeEmitter {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700701 public:
702 typedef llvm::DenseMap<const llvm::GlobalValue*, void*> GlobalAddressMapTy;
703 typedef GlobalAddressMapTy::const_iterator global_addresses_const_iterator;
704
705 private:
Zonr Chang932648d2010-10-13 22:23:56 +0800706 CodeMemoryManager *mpMemMgr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700707
Zonr Chang932648d2010-10-13 22:23:56 +0800708 // The JITInfo for the target we are compiling to
709 const llvm::Target *mpTarget;
Shih-wei Liaocd61af32010-04-29 00:02:57 -0700710
Zonr Chang932648d2010-10-13 22:23:56 +0800711 llvm::TargetJITInfo *mpTJI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700712
Zonr Chang932648d2010-10-13 22:23:56 +0800713 const llvm::TargetData *mpTD;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700714
715 class EmittedFunctionCode {
716 public:
Zonr Chang932648d2010-10-13 22:23:56 +0800717 // Beginning of the function's allocation.
718 void *FunctionBody;
719
720 // The address the function's code actually starts at.
721 void *Code;
722
723 // The size of the function code
724 int Size;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700725
726 EmittedFunctionCode() : FunctionBody(NULL), Code(NULL) { return; }
727 };
Zonr Chang932648d2010-10-13 22:23:56 +0800728 EmittedFunctionCode *mpCurEmitFunction;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700729
Zonr Chang932648d2010-10-13 22:23:56 +0800730 typedef std::map<const std::string,
731 EmittedFunctionCode*> EmittedFunctionsMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700732 EmittedFunctionsMapTy mEmittedFunctions;
733
Zonr Chang932648d2010-10-13 22:23:56 +0800734 // This vector is a mapping from MBB ID's to their address. It is filled in
735 // by the StartMachineBasicBlock callback and queried by the
736 // getMachineBasicBlockAddress callback.
737 std::vector<uintptr_t> mMBBLocations;
738
739 // The constant pool for the current function.
740 llvm::MachineConstantPool *mpConstantPool;
741
742 // A pointer to the first entry in the constant pool.
743 void *mpConstantPoolBase;
744
745 // Addresses of individual constant pool entries.
746 llvm::SmallVector<uintptr_t, 8> mConstPoolAddresses;
747
748 // The jump tables for the current function.
749 llvm::MachineJumpTableInfo *mpJumpTable;
750
751 // A pointer to the first entry in the jump table.
752 void *mpJumpTableBase;
753
754 // When outputting a function stub in the context of some other function, we
755 // save BufferBegin/BufferEnd/CurBufferPtr here.
756 uint8_t *mpSavedBufferBegin, *mpSavedBufferEnd, *mpSavedCurBufferPtr;
757
758 // These are the relocations that the function needs, as emitted.
759 std::vector<llvm::MachineRelocation> mRelocations;
760
761 // This vector is a mapping from Label ID's to their address.
762 llvm::DenseMap<llvm::MCSymbol*, uintptr_t> mLabelLocations;
763
764 // Machine module info for exception informations
765 llvm::MachineModuleInfo *mpMMI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700766
767 GlobalAddressMapTy mGlobalAddressMap;
768
Zonr Chang932648d2010-10-13 22:23:56 +0800769 // Replace an existing mapping for GV with a new address. This updates both
770 // maps as required. If Addr is null, the entry for the global is removed
771 // from the mappings.
772 void *UpdateGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
773 if (Addr == NULL) {
774 // Removing mapping
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700775 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
776 void *OldVal;
777
Zonr Chang932648d2010-10-13 22:23:56 +0800778 if (I == mGlobalAddressMap.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700779 OldVal = NULL;
Zonr Chang932648d2010-10-13 22:23:56 +0800780 } else {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700781 OldVal = I->second;
782 mGlobalAddressMap.erase(I);
783 }
784
785 return OldVal;
786 }
787
Zonr Chang932648d2010-10-13 22:23:56 +0800788 void *&CurVal = mGlobalAddressMap[GV];
789 void *OldVal = CurVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700790
791 CurVal = Addr;
792
793 return OldVal;
794 }
795
Zonr Chang932648d2010-10-13 22:23:56 +0800796 // Tell the execution engine that the specified global is at the specified
797 // location. This is used internally as functions are JIT'd and as global
798 // variables are laid out in memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700799 void AddGlobalMapping(const llvm::GlobalValue *GV, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +0800800 void *&CurVal = mGlobalAddressMap[GV];
801 assert((CurVal == 0 || Addr == 0) &&
802 "GlobalMapping already established!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700803 CurVal = Addr;
804 return;
805 }
806
Zonr Chang932648d2010-10-13 22:23:56 +0800807 // This returns the address of the specified global value if it is has
808 // already been codegen'd, otherwise it returns null.
809 void *GetPointerToGlobalIfAvailable(const llvm::GlobalValue *GV) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -0700810 GlobalAddressMapTy::iterator I = mGlobalAddressMap.find(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700811 return ((I != mGlobalAddressMap.end()) ? I->second : NULL);
812 }
813
Zonr Chang932648d2010-10-13 22:23:56 +0800814 unsigned int GetConstantPoolSizeInBytes(llvm::MachineConstantPool *MCP) {
815 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700816 MCP->getConstants();
817
Zonr Chang932648d2010-10-13 22:23:56 +0800818 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700819 return 0;
820
821 unsigned int Size = 0;
Zonr Chang932648d2010-10-13 22:23:56 +0800822 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700823 llvm::MachineConstantPoolEntry CPE = Constants[i];
824 unsigned int AlignMask = CPE.getAlignment() - 1;
825 Size = (Size + AlignMask) & ~AlignMask;
Zonr Chang932648d2010-10-13 22:23:56 +0800826 const llvm::Type *Ty = CPE.getType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700827 Size += mpTD->getTypeAllocSize(Ty);
828 }
829
830 return Size;
831 }
832
Zonr Chang932648d2010-10-13 22:23:56 +0800833 // This function converts a Constant* into a GenericValue. The interesting
834 // part is if C is a ConstantExpr.
835 void GetConstantValue(const llvm::Constant *C, llvm::GenericValue &Result) {
836 if (C->getValueID() == llvm::Value::UndefValueVal)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700837 return;
Zonr Chang932648d2010-10-13 22:23:56 +0800838 else if (C->getValueID() == llvm::Value::ConstantExprVal) {
839 const llvm::ConstantExpr *CE = (llvm::ConstantExpr*) C;
840 const llvm::Constant *Op0 = CE->getOperand(0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700841
Zonr Chang932648d2010-10-13 22:23:56 +0800842 switch (CE->getOpcode()) {
843 case llvm::Instruction::GetElementPtr: {
844 // Compute the index
845 llvm::SmallVector<llvm::Value*, 8> Indices(CE->op_begin() + 1,
846 CE->op_end());
847 uint64_t Offset = mpTD->getIndexedOffset(Op0->getType(),
848 &Indices[0],
849 Indices.size());
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700850
Zonr Chang932648d2010-10-13 22:23:56 +0800851 GetConstantValue(Op0, Result);
852 Result.PointerVal =
853 static_cast<uint8_t*>(Result.PointerVal) + Offset;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700854
Zonr Chang932648d2010-10-13 22:23:56 +0800855 return;
856 }
857 case llvm::Instruction::Trunc: {
858 uint32_t BitWidth =
859 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
860
861 GetConstantValue(Op0, Result);
862 Result.IntVal = Result.IntVal.trunc(BitWidth);
863
864 return;
865 }
866 case llvm::Instruction::ZExt: {
867 uint32_t BitWidth =
868 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
869
870 GetConstantValue(Op0, Result);
871 Result.IntVal = Result.IntVal.zext(BitWidth);
872
873 return;
874 }
875 case llvm::Instruction::SExt: {
876 uint32_t BitWidth =
877 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
878
879 GetConstantValue(Op0, Result);
880 Result.IntVal = Result.IntVal.sext(BitWidth);
881
882 return;
883 }
884 case llvm::Instruction::FPTrunc: {
885 // FIXME: long double
886 GetConstantValue(Op0, Result);
887 Result.FloatVal = static_cast<float>(Result.DoubleVal);
888 return;
889 }
890 case llvm::Instruction::FPExt: {
891 // FIXME: long double
892 GetConstantValue(Op0, Result);
893 Result.DoubleVal = static_cast<double>(Result.FloatVal);
894 return;
895 }
896 case llvm::Instruction::UIToFP: {
897 GetConstantValue(Op0, Result);
898 if (CE->getType()->isFloatTy())
899 Result.FloatVal =
900 static_cast<float>(Result.IntVal.roundToDouble());
901 else if (CE->getType()->isDoubleTy())
902 Result.DoubleVal = Result.IntVal.roundToDouble();
903 else if (CE->getType()->isX86_FP80Ty()) {
904 const uint64_t zero[] = { 0, 0 };
905 llvm::APFloat apf(llvm::APInt(80, 2, zero));
906 apf.convertFromAPInt(Result.IntVal,
907 false,
908 llvm::APFloat::rmNearestTiesToEven);
909 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700910 }
Zonr Chang932648d2010-10-13 22:23:56 +0800911 return;
912 }
913 case llvm::Instruction::SIToFP: {
914 GetConstantValue(Op0, Result);
915 if (CE->getType()->isFloatTy())
916 Result.FloatVal =
917 static_cast<float>(Result.IntVal.signedRoundToDouble());
918 else if (CE->getType()->isDoubleTy())
919 Result.DoubleVal = Result.IntVal.signedRoundToDouble();
920 else if (CE->getType()->isX86_FP80Ty()) {
921 const uint64_t zero[] = { 0, 0 };
922 llvm::APFloat apf = llvm::APFloat(llvm::APInt(80, 2, zero));
923 apf.convertFromAPInt(Result.IntVal,
924 true,
925 llvm::APFloat::rmNearestTiesToEven);
926 Result.IntVal = apf.bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700927 }
Zonr Chang932648d2010-10-13 22:23:56 +0800928 return;
929 }
930 // double->APInt conversion handles sign
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700931 case llvm::Instruction::FPToUI:
Zonr Chang932648d2010-10-13 22:23:56 +0800932 case llvm::Instruction::FPToSI: {
933 uint32_t BitWidth =
934 llvm::cast<llvm::IntegerType>(CE->getType())->getBitWidth();
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700935
Zonr Chang932648d2010-10-13 22:23:56 +0800936 GetConstantValue(Op0, Result);
937 if (Op0->getType()->isFloatTy())
938 Result.IntVal =
939 llvm::APIntOps::RoundFloatToAPInt(Result.FloatVal, BitWidth);
940 else if (Op0->getType()->isDoubleTy())
941 Result.IntVal =
942 llvm::APIntOps::RoundDoubleToAPInt(Result.DoubleVal,
943 BitWidth);
944 else if (Op0->getType()->isX86_FP80Ty()) {
945 llvm::APFloat apf = llvm::APFloat(Result.IntVal);
946 uint64_t V;
947 bool Ignored;
948 apf.convertToInteger(&V,
949 BitWidth,
950 CE->getOpcode() == llvm::Instruction::FPToSI,
951 llvm::APFloat::rmTowardZero,
952 &Ignored);
953 Result.IntVal = V; // endian?
954 }
955 return;
956 }
957 case llvm::Instruction::PtrToInt: {
958 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
959
960 GetConstantValue(Op0, Result);
961 Result.IntVal = llvm::APInt(PtrWidth, uintptr_t
962 (Result.PointerVal));
963
964 return;
965 }
966 case llvm::Instruction::IntToPtr: {
967 uint32_t PtrWidth = mpTD->getPointerSizeInBits();
968
969 GetConstantValue(Op0, Result);
970 if (PtrWidth != Result.IntVal.getBitWidth())
971 Result.IntVal = Result.IntVal.zextOrTrunc(PtrWidth);
972 assert(Result.IntVal.getBitWidth() <= 64 && "Bad pointer width");
973
974 Result.PointerVal =
975 llvm::PointerTy(
976 static_cast<uintptr_t>(Result.IntVal.getZExtValue()));
977
978 return;
979 }
980 case llvm::Instruction::BitCast: {
981 GetConstantValue(Op0, Result);
982 const llvm::Type *DestTy = CE->getType();
983
984 switch (Op0->getType()->getTypeID()) {
985 case llvm::Type::IntegerTyID: {
986 assert(DestTy->isFloatingPointTy() && "invalid bitcast");
987 if (DestTy->isFloatTy())
988 Result.FloatVal = Result.IntVal.bitsToFloat();
989 else if (DestTy->isDoubleTy())
990 Result.DoubleVal = Result.IntVal.bitsToDouble();
991 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700992 }
Zonr Chang932648d2010-10-13 22:23:56 +0800993 case llvm::Type::FloatTyID: {
994 assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
995 Result.IntVal.floatToBits(Result.FloatVal);
996 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700997 }
Zonr Chang932648d2010-10-13 22:23:56 +0800998 case llvm::Type::DoubleTyID: {
999 assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
1000 Result.IntVal.doubleToBits(Result.DoubleVal);
1001 break;
1002 }
1003 case llvm::Type::PointerTyID: {
1004 assert(DestTy->isPointerTy() && "Invalid bitcast");
1005 break; // getConstantValue(Op0) above already converted it
1006 }
1007 default: {
1008 llvm_unreachable("Invalid bitcast operand");
1009 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001010 }
Zonr Chang932648d2010-10-13 22:23:56 +08001011 return;
1012 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001013 case llvm::Instruction::Add:
1014 case llvm::Instruction::FAdd:
1015 case llvm::Instruction::Sub:
1016 case llvm::Instruction::FSub:
1017 case llvm::Instruction::Mul:
1018 case llvm::Instruction::FMul:
1019 case llvm::Instruction::UDiv:
1020 case llvm::Instruction::SDiv:
1021 case llvm::Instruction::URem:
1022 case llvm::Instruction::SRem:
1023 case llvm::Instruction::And:
1024 case llvm::Instruction::Or:
Zonr Chang932648d2010-10-13 22:23:56 +08001025 case llvm::Instruction::Xor: {
1026 llvm::GenericValue LHS, RHS;
1027 GetConstantValue(Op0, LHS);
1028 GetConstantValue(CE->getOperand(1), RHS);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001029
Zonr Chang932648d2010-10-13 22:23:56 +08001030 switch (Op0->getType()->getTypeID()) {
1031 case llvm::Type::IntegerTyID: {
1032 switch (CE->getOpcode()) {
1033 case llvm::Instruction::Add: {
1034 Result.IntVal = LHS.IntVal + RHS.IntVal;
1035 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001036 }
Zonr Chang932648d2010-10-13 22:23:56 +08001037 case llvm::Instruction::Sub: {
1038 Result.IntVal = LHS.IntVal - RHS.IntVal;
1039 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001040 }
Zonr Chang932648d2010-10-13 22:23:56 +08001041 case llvm::Instruction::Mul: {
1042 Result.IntVal = LHS.IntVal * RHS.IntVal;
1043 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001044 }
Zonr Chang932648d2010-10-13 22:23:56 +08001045 case llvm::Instruction::UDiv: {
1046 Result.IntVal = LHS.IntVal.udiv(RHS.IntVal);
1047 break;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001048 }
Zonr Chang932648d2010-10-13 22:23:56 +08001049 case llvm::Instruction::SDiv: {
1050 Result.IntVal = LHS.IntVal.sdiv(RHS.IntVal);
1051 break;
1052 }
1053 case llvm::Instruction::URem: {
1054 Result.IntVal = LHS.IntVal.urem(RHS.IntVal);
1055 break;
1056 }
1057 case llvm::Instruction::SRem: {
1058 Result.IntVal = LHS.IntVal.srem(RHS.IntVal);
1059 break;
1060 }
1061 case llvm::Instruction::And: {
1062 Result.IntVal = LHS.IntVal & RHS.IntVal;
1063 break;
1064 }
1065 case llvm::Instruction::Or: {
1066 Result.IntVal = LHS.IntVal | RHS.IntVal;
1067 break;
1068 }
1069 case llvm::Instruction::Xor: {
1070 Result.IntVal = LHS.IntVal ^ RHS.IntVal;
1071 break;
1072 }
1073 default: {
1074 llvm_unreachable("Invalid integer opcode");
1075 }
1076 }
1077 break;
1078 }
1079 case llvm::Type::FloatTyID: {
1080 switch (CE->getOpcode()) {
1081 case llvm::Instruction::FAdd: {
1082 Result.FloatVal = LHS.FloatVal + RHS.FloatVal;
1083 break;
1084 }
1085 case llvm::Instruction::FSub: {
1086 Result.FloatVal = LHS.FloatVal - RHS.FloatVal;
1087 break;
1088 }
1089 case llvm::Instruction::FMul: {
1090 Result.FloatVal = LHS.FloatVal * RHS.FloatVal;
1091 break;
1092 }
1093 case llvm::Instruction::FDiv: {
1094 Result.FloatVal = LHS.FloatVal / RHS.FloatVal;
1095 break;
1096 }
1097 case llvm::Instruction::FRem: {
1098 Result.FloatVal = ::fmodf(LHS.FloatVal, RHS.FloatVal);
1099 break;
1100 }
1101 default: {
1102 llvm_unreachable("Invalid float opcode");
1103 }
1104 }
1105 break;
1106 }
1107 case llvm::Type::DoubleTyID: {
1108 switch (CE->getOpcode()) {
1109 case llvm::Instruction::FAdd: {
1110 Result.DoubleVal = LHS.DoubleVal + RHS.DoubleVal;
1111 break;
1112 }
1113 case llvm::Instruction::FSub: {
1114 Result.DoubleVal = LHS.DoubleVal - RHS.DoubleVal;
1115 break;
1116 }
1117 case llvm::Instruction::FMul: {
1118 Result.DoubleVal = LHS.DoubleVal * RHS.DoubleVal;
1119 break;
1120 }
1121 case llvm::Instruction::FDiv: {
1122 Result.DoubleVal = LHS.DoubleVal / RHS.DoubleVal;
1123 break;
1124 }
1125 case llvm::Instruction::FRem: {
1126 Result.DoubleVal = ::fmod(LHS.DoubleVal, RHS.DoubleVal);
1127 break;
1128 }
1129 default: {
1130 llvm_unreachable("Invalid double opcode");
1131 }
1132 }
1133 break;
1134 }
1135 case llvm::Type::X86_FP80TyID:
1136 case llvm::Type::PPC_FP128TyID:
1137 case llvm::Type::FP128TyID: {
1138 llvm::APFloat apfLHS = llvm::APFloat(LHS.IntVal);
1139 switch (CE->getOpcode()) {
1140 case llvm::Instruction::FAdd: {
1141 apfLHS.add(llvm::APFloat(RHS.IntVal),
1142 llvm::APFloat::rmNearestTiesToEven);
1143 break;
1144 }
1145 case llvm::Instruction::FSub: {
1146 apfLHS.subtract(llvm::APFloat(RHS.IntVal),
1147 llvm::APFloat::rmNearestTiesToEven);
1148 break;
1149 }
1150 case llvm::Instruction::FMul: {
1151 apfLHS.multiply(llvm::APFloat(RHS.IntVal),
1152 llvm::APFloat::rmNearestTiesToEven);
1153 break;
1154 }
1155 case llvm::Instruction::FDiv: {
1156 apfLHS.divide(llvm::APFloat(RHS.IntVal),
1157 llvm::APFloat::rmNearestTiesToEven);
1158 break;
1159 }
1160 case llvm::Instruction::FRem: {
1161 apfLHS.mod(llvm::APFloat(RHS.IntVal),
1162 llvm::APFloat::rmNearestTiesToEven);
1163 break;
1164 }
1165 default: {
1166 llvm_unreachable("Invalid long double opcode");
1167 }
1168 }
1169 Result.IntVal = apfLHS.bitcastToAPInt();
1170 break;
1171 }
1172 default: {
1173 llvm_unreachable("Bad add type!");
1174 }
1175 } // End switch (Op0->getType()->getTypeID())
1176 return;
1177 }
1178 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001179 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001180 }
1181 } // End switch (CE->getOpcode())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001182
1183 std::string msg;
1184 llvm::raw_string_ostream Msg(msg);
1185 Msg << "ConstantExpr not handled: " << *CE;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001186 llvm::report_fatal_error(Msg.str());
Zonr Chang932648d2010-10-13 22:23:56 +08001187 } // C->getValueID() == llvm::Value::ConstantExprVal
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001188
1189 switch (C->getType()->getTypeID()) {
Zonr Chang932648d2010-10-13 22:23:56 +08001190 case llvm::Type::FloatTyID: {
1191 Result.FloatVal =
1192 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToFloat();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001193 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001194 }
1195 case llvm::Type::DoubleTyID: {
1196 Result.DoubleVal =
1197 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().convertToDouble();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001198 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001199 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001200 case llvm::Type::X86_FP80TyID:
1201 case llvm::Type::FP128TyID:
Zonr Chang932648d2010-10-13 22:23:56 +08001202 case llvm::Type::PPC_FP128TyID: {
1203 Result.IntVal =
1204 llvm::cast<llvm::ConstantFP>(C)->getValueAPF().bitcastToAPInt();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001205 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001206 }
1207 case llvm::Type::IntegerTyID: {
1208 Result.IntVal =
1209 llvm::cast<llvm::ConstantInt>(C)->getValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001210 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001211 }
1212 case llvm::Type::PointerTyID: {
1213 switch (C->getValueID()) {
1214 case llvm::Value::ConstantPointerNullVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001215 Result.PointerVal = NULL;
1216 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001217 }
1218 case llvm::Value::FunctionVal: {
1219 const llvm::Function *F = static_cast<const llvm::Function*>(C);
1220 Result.PointerVal =
1221 GetPointerToFunctionOrStub(const_cast<llvm::Function*>(F));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001222 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001223 }
1224 case llvm::Value::GlobalVariableVal: {
1225 const llvm::GlobalVariable *GV =
1226 static_cast<const llvm::GlobalVariable*>(C);
1227 Result.PointerVal =
1228 GetOrEmitGlobalVariable(const_cast<llvm::GlobalVariable*>(GV));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001229 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001230 }
1231 case llvm::Value::BlockAddressVal: {
1232 assert(false && "JIT does not support address-of-label yet!");
1233 }
1234 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001235 llvm_unreachable("Unknown constant pointer type!");
Zonr Chang932648d2010-10-13 22:23:56 +08001236 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001237 }
1238 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001239 }
1240 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001241 std::string msg;
1242 llvm::raw_string_ostream Msg(msg);
1243 Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001244 llvm::report_fatal_error(Msg.str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001245 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001246 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001247 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001248 return;
1249 }
1250
Zonr Chang932648d2010-10-13 22:23:56 +08001251 // Stores the data in @Val of type @Ty at address @Addr.
1252 void StoreValueToMemory(const llvm::GenericValue &Val, void *Addr,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001253 const llvm::Type *Ty) {
1254 const unsigned int StoreBytes = mpTD->getTypeStoreSize(Ty);
1255
Zonr Chang932648d2010-10-13 22:23:56 +08001256 switch (Ty->getTypeID()) {
1257 case llvm::Type::IntegerTyID: {
1258 const llvm::APInt &IntVal = Val.IntVal;
1259 assert(((IntVal.getBitWidth() + 7) / 8 >= StoreBytes) &&
1260 "Integer too small!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001261
Zonr Chang932648d2010-10-13 22:23:56 +08001262 const uint8_t *Src =
1263 reinterpret_cast<const uint8_t*>(IntVal.getRawData());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001264
Zonr Chang932648d2010-10-13 22:23:56 +08001265 if (llvm::sys::isLittleEndianHost()) {
1266 // Little-endian host - the source is ordered from LSB to MSB.
1267 // Order the destination from LSB to MSB: Do a straight copy.
1268 memcpy(Addr, Src, StoreBytes);
1269 } else {
1270 // Big-endian host - the source is an array of 64 bit words
1271 // ordered from LSW to MSW.
1272 //
1273 // Each word is ordered from MSB to LSB.
1274 //
1275 // Order the destination from MSB to LSB:
1276 // Reverse the word order, but not the bytes in a word.
1277 unsigned int i = StoreBytes;
1278 while (i > sizeof(uint64_t)) {
1279 i -= sizeof(uint64_t);
1280 ::memcpy(reinterpret_cast<uint8_t*>(Addr) + i,
1281 Src,
1282 sizeof(uint64_t));
1283 Src += sizeof(uint64_t);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001284 }
Zonr Chang932648d2010-10-13 22:23:56 +08001285 ::memcpy(Addr, Src + sizeof(uint64_t) - i, i);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001286 }
1287 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001288 }
1289 case llvm::Type::FloatTyID: {
1290 *reinterpret_cast<float*>(Addr) = Val.FloatVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001291 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001292 }
1293 case llvm::Type::DoubleTyID: {
1294 *reinterpret_cast<double*>(Addr) = Val.DoubleVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001295 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001296 }
1297 case llvm::Type::X86_FP80TyID: {
1298 memcpy(Addr, Val.IntVal.getRawData(), 10);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001299 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001300 }
1301 case llvm::Type::PointerTyID: {
1302 // Ensure 64 bit target pointers are fully initialized on 32 bit
1303 // hosts.
1304 if (StoreBytes != sizeof(llvm::PointerTy))
1305 memset(Addr, 0, StoreBytes);
1306 *((llvm::PointerTy*) Addr) = Val.PointerVal;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001307 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001308 }
1309 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001310 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001311 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001312 }
1313
Zonr Chang932648d2010-10-13 22:23:56 +08001314 if (llvm::sys::isLittleEndianHost() != mpTD->isLittleEndian())
1315 std::reverse(reinterpret_cast<uint8_t*>(Addr),
1316 reinterpret_cast<uint8_t*>(Addr) + StoreBytes);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001317
1318 return;
1319 }
1320
Zonr Chang932648d2010-10-13 22:23:56 +08001321 // Recursive function to apply a @Constant value into the specified memory
1322 // location @Addr.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001323 void InitializeConstantToMemory(const llvm::Constant *C, void *Addr) {
Zonr Chang932648d2010-10-13 22:23:56 +08001324 switch (C->getValueID()) {
1325 case llvm::Value::UndefValueVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001326 // Nothing to do
1327 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001328 }
1329 case llvm::Value::ConstantVectorVal: {
1330 // dynamic cast may hurt performance
1331 const llvm::ConstantVector *CP = (llvm::ConstantVector*) C;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001332
Zonr Chang932648d2010-10-13 22:23:56 +08001333 unsigned int ElementSize = mpTD->getTypeAllocSize
1334 (CP->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001335
Zonr Chang932648d2010-10-13 22:23:56 +08001336 for (int i = 0, e = CP->getNumOperands(); i != e;i++)
1337 InitializeConstantToMemory(
1338 CP->getOperand(i),
1339 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001340 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001341 }
1342 case llvm::Value::ConstantAggregateZeroVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001343 memset(Addr, 0, (size_t) mpTD->getTypeAllocSize(C->getType()));
1344 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001345 }
1346 case llvm::Value::ConstantArrayVal: {
1347 const llvm::ConstantArray *CPA = (llvm::ConstantArray*) C;
1348 unsigned int ElementSize = mpTD->getTypeAllocSize
1349 (CPA->getType()->getElementType());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001350
Zonr Chang932648d2010-10-13 22:23:56 +08001351 for (int i = 0, e = CPA->getNumOperands(); i != e; i++)
1352 InitializeConstantToMemory(
1353 CPA->getOperand(i),
1354 reinterpret_cast<uint8_t*>(Addr) + i * ElementSize);
1355 break;
1356 }
1357 case llvm::Value::ConstantStructVal: {
1358 const llvm::ConstantStruct *CPS =
1359 static_cast<const llvm::ConstantStruct*>(C);
1360 const llvm::StructLayout *SL = mpTD->getStructLayout
1361 (llvm::cast<llvm::StructType>(CPS->getType()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001362
Zonr Chang932648d2010-10-13 22:23:56 +08001363 for (int i = 0, e = CPS->getNumOperands(); i != e; i++)
1364 InitializeConstantToMemory(
1365 CPS->getOperand(i),
1366 reinterpret_cast<uint8_t*>(Addr) + SL->getElementOffset(i));
1367 break;
1368 }
1369 default: {
1370 if (C->getType()->isFirstClassType()) {
1371 llvm::GenericValue Val;
1372 GetConstantValue(C, Val);
1373 StoreValueToMemory(Val, Addr, C->getType());
1374 } else {
1375 llvm_unreachable("Unknown constant type to initialize memory "
1376 "with!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001377 }
1378 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001379 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001380 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001381 return;
1382 }
1383
1384 void emitConstantPool(llvm::MachineConstantPool *MCP) {
Zonr Chang932648d2010-10-13 22:23:56 +08001385 if (mpTJI->hasCustomConstantPool())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001386 return;
1387
Zonr Chang932648d2010-10-13 22:23:56 +08001388 // Constant pool address resolution is handled by the target itself in ARM
1389 // (TargetJITInfo::hasCustomConstantPool() returns true).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001390#if !defined(PROVIDE_ARM_CODEGEN)
Zonr Chang932648d2010-10-13 22:23:56 +08001391 const std::vector<llvm::MachineConstantPoolEntry> &Constants =
1392 MCP->getConstants();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001393
Zonr Chang932648d2010-10-13 22:23:56 +08001394 if (Constants.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001395 return;
1396
1397 unsigned Size = GetConstantPoolSizeInBytes(MCP);
1398 unsigned Align = MCP->getConstantPoolAlignment();
1399
1400 mpConstantPoolBase = allocateSpace(Size, Align);
1401 mpConstantPool = MCP;
1402
Zonr Chang932648d2010-10-13 22:23:56 +08001403 if (mpConstantPoolBase == NULL)
1404 return; // out of memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001405
1406 unsigned Offset = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001407 for (int i = 0, e = Constants.size(); i != e; i++) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001408 llvm::MachineConstantPoolEntry CPE = Constants[i];
1409 unsigned AlignMask = CPE.getAlignment() - 1;
1410 Offset = (Offset + AlignMask) & ~AlignMask;
1411
1412 uintptr_t CAddr = (uintptr_t) mpConstantPoolBase + Offset;
1413 mConstPoolAddresses.push_back(CAddr);
1414
Zonr Chang932648d2010-10-13 22:23:56 +08001415 if (CPE.isMachineConstantPoolEntry())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001416 llvm::report_fatal_error
Zonr Chang932648d2010-10-13 22:23:56 +08001417 ("Initialize memory with machine specific constant pool"
1418 " entry has not been implemented!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001419
1420 InitializeConstantToMemory(CPE.Val.ConstVal, (void*) CAddr);
1421
1422 const llvm::Type *Ty = CPE.Val.ConstVal->getType();
1423 Offset += mpTD->getTypeAllocSize(Ty);
1424 }
1425#endif
1426 return;
1427 }
1428
1429 void initJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001430 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001431 return;
1432
Zonr Chang932648d2010-10-13 22:23:56 +08001433 const std::vector<llvm::MachineJumpTableEntry> &JT =
1434 MJTI->getJumpTables();
1435 if (JT.empty())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001436 return;
1437
1438 unsigned NumEntries = 0;
Zonr Chang932648d2010-10-13 22:23:56 +08001439 for (int i = 0, e = JT.size(); i != e; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001440 NumEntries += JT[i].MBBs.size();
1441
1442 unsigned EntrySize = MJTI->getEntrySize(*mpTD);
1443
Zonr Chang932648d2010-10-13 22:23:56 +08001444 mpJumpTable = MJTI;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001445 mpJumpTableBase = allocateSpace(NumEntries * EntrySize,
Zonr Chang932648d2010-10-13 22:23:56 +08001446 MJTI->getEntryAlignment(*mpTD));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001447
1448 return;
1449 }
1450
1451 void emitJumpTableInfo(llvm::MachineJumpTableInfo *MJTI) {
Zonr Chang932648d2010-10-13 22:23:56 +08001452 if (mpTJI->hasCustomJumpTables())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001453 return;
1454
Zonr Chang932648d2010-10-13 22:23:56 +08001455 const std::vector<llvm::MachineJumpTableEntry> &JT =
1456 MJTI->getJumpTables();
1457 if (JT.empty() || mpJumpTableBase == 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001458 return;
1459
Zonr Chang932648d2010-10-13 22:23:56 +08001460 assert(llvm::TargetMachine::getRelocationModel() == llvm::Reloc::Static &&
1461 (MJTI->getEntrySize(*mpTD) == sizeof(mpTD /* a pointer type */)) &&
1462 "Cross JIT'ing?");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001463
Zonr Chang932648d2010-10-13 22:23:56 +08001464 // For each jump table, map each target in the jump table to the
1465 // address of an emitted MachineBasicBlock.
1466 intptr_t *SlotPtr = reinterpret_cast<intptr_t*>(mpJumpTableBase);
1467 for (int i = 0, ie = JT.size(); i != ie; i++) {
1468 const std::vector<llvm::MachineBasicBlock*> &MBBs = JT[i].MBBs;
1469 // Store the address of the basic block for this jump table slot in the
1470 // memory we allocated for the jump table in 'initJumpTableInfo'
1471 for (int j = 0, je = MBBs.size(); j != je; j++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001472 *SlotPtr++ = getMachineBasicBlockAddress(MBBs[j]);
1473 }
1474 }
1475
Zonr Chang932648d2010-10-13 22:23:56 +08001476 void *GetPointerToGlobal(llvm::GlobalValue *V, void *Reference,
1477 bool MayNeedFarStub) {
1478 switch (V->getValueID()) {
1479 case llvm::Value::FunctionVal: {
1480 llvm::Function *F = (llvm::Function*) V;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001481
Zonr Chang932648d2010-10-13 22:23:56 +08001482 // If we have code, go ahead and return that.
1483 if (void *ResultPtr = GetPointerToGlobalIfAvailable(F))
1484 return ResultPtr;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001485
Zonr Chang932648d2010-10-13 22:23:56 +08001486 if (void *FnStub = GetLazyFunctionStubIfAvailable(F))
1487 // Return the function stub if it's already created.
1488 // We do this first so that:
1489 // we're returning the same address for the function as any
1490 // previous call.
1491 //
1492 // TODO(llvm.org): Yes, this is wrong. The lazy stub isn't
1493 // guaranteed to be close enough to call.
1494 return FnStub;
Shih-wei Liao800e9c22010-04-18 16:08:16 -07001495
Zonr Chang932648d2010-10-13 22:23:56 +08001496 // If we know the target can handle arbitrary-distance calls, try to
1497 // return a direct pointer.
1498 if (!MayNeedFarStub) {
1499 //
1500 // x86_64 architecture may encounter the bug:
1501 // http://llvm.org/bugs/show_bug.cgi?id=5201
1502 // which generate instruction "call" instead of "callq".
1503 //
1504 // And once the real address of stub is greater than 64-bit
1505 // long, the replacement will truncate to 32-bit resulting a
1506 // serious problem.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001507#if !defined(__x86_64__)
Zonr Chang932648d2010-10-13 22:23:56 +08001508 // If this is an external function pointer, we can force the JIT
1509 // to 'compile' it, which really just adds it to the map.
1510 if (F->isDeclaration() || F->hasAvailableExternallyLinkage())
1511 return GetPointerToFunction(F, /* AbortOnFailure = */true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001512#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001513 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001514
Zonr Chang932648d2010-10-13 22:23:56 +08001515 // Otherwise, we may need a to emit a stub, and, conservatively, we
1516 // always do so.
1517 return GetLazyFunctionStub(F);
1518 break;
1519 }
1520 case llvm::Value::GlobalVariableVal: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001521 return GetOrEmitGlobalVariable((llvm::GlobalVariable*) V);
1522 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001523 }
1524 case llvm::Value::GlobalAliasVal: {
1525 llvm::GlobalAlias *GA = (llvm::GlobalAlias*) V;
1526 const llvm::GlobalValue *GV = GA->resolveAliasedGlobal(false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001527
Zonr Chang932648d2010-10-13 22:23:56 +08001528 switch (GV->getValueID()) {
1529 case llvm::Value::FunctionVal: {
1530 // FIXME: is there's any possibility that the function is not
1531 // code-gen'd?
1532 return GetPointerToFunction(
1533 static_cast<const llvm::Function*>(GV),
1534 /* AbortOnFailure = */true);
1535 break;
1536 }
1537 case llvm::Value::GlobalVariableVal: {
1538 if (void *P = mGlobalAddressMap[GV])
1539 return P;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001540
Zonr Chang932648d2010-10-13 22:23:56 +08001541 llvm::GlobalVariable *GVar = (llvm::GlobalVariable*) GV;
1542 EmitGlobalVariable(GVar);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001543
Zonr Chang932648d2010-10-13 22:23:56 +08001544 return mGlobalAddressMap[GV];
1545 break;
1546 }
1547 case llvm::Value::GlobalAliasVal: {
1548 assert(false && "Alias should be resolved ultimately!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001549 }
1550 }
1551 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001552 }
1553 default: {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001554 break;
Zonr Chang932648d2010-10-13 22:23:56 +08001555 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001556 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001557 llvm_unreachable("Unknown type of global value!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001558 }
1559
Zonr Chang932648d2010-10-13 22:23:56 +08001560 // If the specified function has been code-gen'd, return a pointer to the
1561 // function. If not, compile it, or use a stub to implement lazy compilation
1562 // if available.
1563 void *GetPointerToFunctionOrStub(llvm::Function *F) {
1564 // If we have already code generated the function, just return the
1565 // address.
1566 if (void *Addr = GetPointerToGlobalIfAvailable(F))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001567 return Addr;
1568
Zonr Chang932648d2010-10-13 22:23:56 +08001569 // Get a stub if the target supports it.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001570 return GetLazyFunctionStub(F);
1571 }
1572
Zonr Chang932648d2010-10-13 22:23:56 +08001573 typedef llvm::DenseMap<const llvm::Function*,
1574 void*> FunctionToLazyStubMapTy;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001575 FunctionToLazyStubMapTy mFunctionToLazyStubMap;
1576
Zonr Chang932648d2010-10-13 22:23:56 +08001577 void *GetLazyFunctionStubIfAvailable(llvm::Function *F) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001578 return mFunctionToLazyStubMap.lookup(F);
1579 }
1580
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001581 std::set<const llvm::Function*> PendingFunctions;
Zonr Chang932648d2010-10-13 22:23:56 +08001582 void *GetLazyFunctionStub(llvm::Function *F) {
1583 // If we already have a lazy stub for this function, recycle it.
1584 void *&Stub = mFunctionToLazyStubMap[F];
1585 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001586 return Stub;
1587
Zonr Chang932648d2010-10-13 22:23:56 +08001588 // In any cases, we should NOT resolve function at runtime (though we are
1589 // able to). We resolve this right now.
1590 void *Actual = NULL;
1591 if (F->isDeclaration() || F->hasAvailableExternallyLinkage())
1592 Actual = GetPointerToFunction(F, /* AbortOnFailure = */true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001593
Zonr Chang932648d2010-10-13 22:23:56 +08001594 // Codegen a new stub, calling the actual address of the external
1595 // function, if it was resolved.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001596 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1597 startGVStub(F, SL.Size, SL.Alignment);
1598 Stub = mpTJI->emitFunctionStub(F, Actual, *this);
1599 finishGVStub();
1600
Zonr Chang932648d2010-10-13 22:23:56 +08001601 // We really want the address of the stub in the GlobalAddressMap for the
1602 // JIT, not the address of the external function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001603 UpdateGlobalMapping(F, Stub);
1604
Zonr Chang932648d2010-10-13 22:23:56 +08001605 if (!Actual)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001606 PendingFunctions.insert(F);
1607 else
Zonr Chang932648d2010-10-13 22:23:56 +08001608 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
1609 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001610
1611 return Stub;
1612 }
1613
Zonr Chang932648d2010-10-13 22:23:56 +08001614 void *GetPointerToFunction(const llvm::Function *F, bool AbortOnFailure) {
1615 void *Addr = GetPointerToGlobalIfAvailable(F);
1616 if (Addr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001617 return Addr;
1618
1619 assert((F->isDeclaration() || F->hasAvailableExternallyLinkage()) &&
1620 "Internal error: only external defined function routes here!");
1621
Zonr Chang932648d2010-10-13 22:23:56 +08001622 // Handle the failure resolution by ourselves.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001623 Addr = GetPointerToNamedSymbol(F->getName().str().c_str(),
Zonr Chang932648d2010-10-13 22:23:56 +08001624 /* AbortOnFailure = */ false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001625
Zonr Chang932648d2010-10-13 22:23:56 +08001626 // If we resolved the symbol to a null address (eg. a weak external)
1627 // return a null pointer let the application handle it.
1628 if (Addr == NULL) {
1629 if (AbortOnFailure)
1630 llvm::report_fatal_error("Could not resolve external function "
1631 "address: " + F->getName());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001632 else
1633 return NULL;
Zonr Chang932648d2010-10-13 22:23:56 +08001634 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001635
1636 AddGlobalMapping(F, Addr);
1637
1638 return Addr;
1639 }
1640
Zonr Chang932648d2010-10-13 22:23:56 +08001641 void *GetPointerToNamedSymbol(const std::string &Name,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001642 bool AbortOnFailure) {
Zonr Chang932648d2010-10-13 22:23:56 +08001643 if (void *Addr = FindRuntimeFunction(Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001644 return Addr;
1645
Zonr Chang932648d2010-10-13 22:23:56 +08001646 if (mpSymbolLookupFn)
1647 if (void *Addr = mpSymbolLookupFn(mpSymbolLookupContext, Name.c_str()))
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001648 return Addr;
1649
Zonr Chang932648d2010-10-13 22:23:56 +08001650 if (AbortOnFailure)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001651 llvm::report_fatal_error("Program used external symbol '" + Name +
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001652 "' which could not be resolved!");
1653
1654 return NULL;
1655 }
1656
Zonr Chang932648d2010-10-13 22:23:56 +08001657 // Return the address of the specified global variable, possibly emitting it
1658 // to memory if needed. This is used by the Emitter.
1659 void *GetOrEmitGlobalVariable(const llvm::GlobalVariable *GV) {
1660 void *Ptr = GetPointerToGlobalIfAvailable(GV);
1661 if (Ptr)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001662 return Ptr;
1663
Zonr Chang932648d2010-10-13 22:23:56 +08001664 if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) {
1665 // If the global is external, just remember the address.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001666 Ptr = GetPointerToNamedSymbol(GV->getName().str(), true);
1667 AddGlobalMapping(GV, Ptr);
1668 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001669 // If the global hasn't been emitted to memory yet, allocate space and
1670 // emit it into memory.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001671 Ptr = GetMemoryForGV(GV);
1672 AddGlobalMapping(GV, Ptr);
1673 EmitGlobalVariable(GV);
1674 }
1675
1676 return Ptr;
1677 }
1678
Zonr Chang932648d2010-10-13 22:23:56 +08001679 // This method abstracts memory allocation of global variable so that the
1680 // JIT can allocate thread local variables depending on the target.
1681 void *GetMemoryForGV(const llvm::GlobalVariable *GV) {
1682 void *Ptr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001683
Zonr Chang932648d2010-10-13 22:23:56 +08001684 const llvm::Type *GlobalType = GV->getType()->getElementType();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001685 size_t S = mpTD->getTypeAllocSize(GlobalType);
1686 size_t A = mpTD->getPreferredAlignment(GV);
1687
Zonr Chang932648d2010-10-13 22:23:56 +08001688 if (GV->isThreadLocal()) {
1689 // We can support TLS by
1690 //
1691 // Ptr = TJI.allocateThreadLocalMemory(S);
1692 //
1693 // But I tend not to.
1694 // (should we disable this in the front-end (i.e., slang)?).
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001695 llvm::report_fatal_error
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001696 ("Compilation of Thread Local Storage (TLS) is disabled!");
1697
Zonr Chang932648d2010-10-13 22:23:56 +08001698 } else if (mpTJI->allocateSeparateGVMemory()) {
1699 if (A <= 8) {
1700 Ptr = malloc(S);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001701 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001702 // Allocate (S + A) bytes of memory, then use an aligned pointer
1703 // within that space.
1704 Ptr = malloc(S + A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001705 unsigned int MisAligned = ((intptr_t) Ptr & (A - 1));
Zonr Chang932648d2010-10-13 22:23:56 +08001706 Ptr = reinterpret_cast<uint8_t*>(Ptr) +
1707 (MisAligned ? (A - MisAligned) : 0);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001708 }
1709 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08001710 Ptr = allocateGlobal(S, A);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001711 }
1712
1713 return Ptr;
1714 }
1715
1716 void EmitGlobalVariable(const llvm::GlobalVariable *GV) {
Zonr Chang932648d2010-10-13 22:23:56 +08001717 void *GA = GetPointerToGlobalIfAvailable(GV);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001718
Zonr Chang932648d2010-10-13 22:23:56 +08001719 if (GV->isThreadLocal())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07001720 llvm::report_fatal_error
1721 ("We don't support Thread Local Storage (TLS)!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001722
Zonr Chang932648d2010-10-13 22:23:56 +08001723 if (GA == NULL) {
1724 // If it's not already specified, allocate memory for the global.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001725 GA = GetMemoryForGV(GV);
1726 AddGlobalMapping(GV, GA);
1727 }
1728
1729 InitializeConstantToMemory(GV->getInitializer(), GA);
1730
Zonr Chang932648d2010-10-13 22:23:56 +08001731 // You can do some statistics on global variable here.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001732 return;
1733 }
1734
1735 typedef std::map<llvm::AssertingVH<llvm::GlobalValue>, void*
1736 > GlobalToIndirectSymMapTy;
1737 GlobalToIndirectSymMapTy GlobalToIndirectSymMap;
1738
Zonr Chang932648d2010-10-13 22:23:56 +08001739 void *GetPointerToGVIndirectSym(llvm::GlobalValue *V, void *Reference) {
1740 // Make sure GV is emitted first, and create a stub containing the fully
1741 // resolved address.
1742 void *GVAddress = GetPointerToGlobal(V, Reference, false);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001743
Zonr Chang932648d2010-10-13 22:23:56 +08001744 // If we already have a stub for this global variable, recycle it.
1745 void *&IndirectSym = GlobalToIndirectSymMap[V];
1746 // Otherwise, codegen a new indirect symbol.
1747 if (!IndirectSym)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001748 IndirectSym = mpTJI->emitGlobalValueIndirectSym(V, GVAddress, *this);
1749
1750 return IndirectSym;
1751 }
1752
Zonr Chang932648d2010-10-13 22:23:56 +08001753 // This is the equivalent of FunctionToLazyStubMap for external functions.
1754 //
1755 // TODO(llvm.org): Of course, external functions don't need a lazy stub.
1756 // It's actually here to make it more likely that far calls
1757 // succeed, but no single stub can guarantee that. I'll
1758 // remove this in a subsequent checkin when I actually fix
1759 // far calls.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001760 std::map<void*, void*> ExternalFnToStubMap;
1761
Zonr Chang932648d2010-10-13 22:23:56 +08001762 // Return a stub for the function at the specified address.
1763 void *GetExternalFunctionStub(void *FnAddr) {
1764 void *&Stub = ExternalFnToStubMap[FnAddr];
1765 if (Stub)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001766 return Stub;
1767
1768 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
1769 startGVStub(0, SL.Size, SL.Alignment);
1770 Stub = mpTJI->emitFunctionStub(0, FnAddr, *this);
1771 finishGVStub();
1772
1773 return Stub;
1774 }
1775
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001776#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001777 const llvm::MCAsmInfo *mpAsmInfo;
1778 const llvm::MCDisassembler *mpDisassmbler;
1779 llvm::MCInstPrinter *mpIP;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001780
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001781 class BufferMemoryObject : public llvm::MemoryObject {
1782 private:
Zonr Chang932648d2010-10-13 22:23:56 +08001783 const uint8_t *mBytes;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001784 uint64_t mLength;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001785
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001786 public:
1787 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
1788 mBytes(Bytes), mLength(Length) { }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001789
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001790 uint64_t getBase() const { return 0; }
1791 uint64_t getExtent() const { return mLength; }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001792
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001793 int readByte(uint64_t Addr, uint8_t *Byte) const {
Zonr Chang932648d2010-10-13 22:23:56 +08001794 if (Addr > getExtent())
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001795 return -1;
1796 *Byte = mBytes[Addr];
1797 return 0;
1798 }
1799 };
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001800
Zonr Chang932648d2010-10-13 22:23:56 +08001801 void Disassemble(const llvm::StringRef &Name, uint8_t *Start,
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001802 size_t Length, bool IsStub) {
Zonr Chang932648d2010-10-13 22:23:56 +08001803 llvm::raw_fd_ostream *OS;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001804#if defined(USE_DISASSEMBLER_FILE)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001805 std::string ErrorInfo;
Zonr Chang932648d2010-10-13 22:23:56 +08001806 OS = new llvm::raw_fd_ostream("/data/local/tmp/out.S",
1807 ErrorInfo,
1808 llvm::raw_fd_ostream::F_Append);
1809 if (!ErrorInfo.empty()) { // some errors occurred
1810 // LOGE("Error in creating disassembly file");
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001811 delete OS;
1812 return;
1813 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001814#else
1815 OS = &llvm::outs();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001816#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001817 *OS << "JIT: Disassembled code: " << Name << ((IsStub) ? " (stub)" : "")
1818 << "\n";
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001819
Zonr Chang932648d2010-10-13 22:23:56 +08001820 if (mpAsmInfo == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001821 mpAsmInfo = mpTarget->createAsmInfo(Triple);
Zonr Chang932648d2010-10-13 22:23:56 +08001822 if (mpDisassmbler == NULL)
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001823 mpDisassmbler = mpTarget->createMCDisassembler();
Zonr Chang932648d2010-10-13 22:23:56 +08001824 if (mpIP == NULL)
1825 mpIP = mpTarget->createMCInstPrinter(mpAsmInfo->getAssemblerDialect(),
1826 *mpAsmInfo);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001827
Zonr Chang932648d2010-10-13 22:23:56 +08001828 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Start,
1829 Length);
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001830 uint64_t Size;
1831 uint64_t Index;
1832
Zonr Chang932648d2010-10-13 22:23:56 +08001833 for (Index = 0; Index < Length; Index += Size) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001834 llvm::MCInst Inst;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001835
Zonr Chang932648d2010-10-13 22:23:56 +08001836 if (mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
1837 /* REMOVED */ llvm::nulls())) {
1838 (*OS).indent(4)
1839 .write("0x", 2)
1840 .write_hex((uint32_t) Start + Index)
1841 .write(':');
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001842 mpIP->printInst(&Inst, *OS);
1843 *OS << "\n";
1844 } else {
1845 if (Size == 0)
Zonr Chang932648d2010-10-13 22:23:56 +08001846 Size = 1; // skip illegible bytes
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001847 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001848 }
1849
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001850 *OS << "\n";
1851 delete BufferMObj;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001852
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07001853#if defined(USE_DISASSEMBLER_FILE)
Zonr Chang932648d2010-10-13 22:23:56 +08001854 // If you want the disassemble results write to file, uncomment this.
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001855 OS->close();
1856 delete OS;
1857#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001858 return;
1859 }
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001860#else
Zonr Chang932648d2010-10-13 22:23:56 +08001861 inline void Disassemble(const std::string &Name, uint8_t *Start,
1862 size_t Length, bool IsStub) {
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001863 return;
1864 }
Zonr Chang932648d2010-10-13 22:23:56 +08001865#endif // defined(USE_DISASSEMBLER)
1866
1867 // Resolver to undefined symbol in CodeEmitter
1868 BCCSymbolLookupFn mpSymbolLookupFn;
1869 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001870
1871 public:
Zonr Chang932648d2010-10-13 22:23:56 +08001872 // Will take the ownership of @MemMgr
1873 explicit CodeEmitter(CodeMemoryManager *pMemMgr)
1874 : mpMemMgr(pMemMgr),
1875 mpTarget(NULL),
1876 mpTJI(NULL),
1877 mpTD(NULL),
1878 mpCurEmitFunction(NULL),
1879 mpConstantPool(NULL),
1880 mpJumpTable(NULL),
1881 mpMMI(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001882#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08001883 mpAsmInfo(NULL),
1884 mpDisassmbler(NULL),
1885 mpIP(NULL),
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001886#endif
Zonr Chang932648d2010-10-13 22:23:56 +08001887 mpSymbolLookupFn(NULL),
1888 mpSymbolLookupContext(NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001889 return;
1890 }
1891
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001892 inline global_addresses_const_iterator global_address_begin() const {
1893 return mGlobalAddressMap.begin();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001894 }
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07001895 inline global_addresses_const_iterator global_address_end() const {
1896 return mGlobalAddressMap.end();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001897 }
1898
Zonr Chang932648d2010-10-13 22:23:56 +08001899 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001900 mpSymbolLookupFn = pFn;
1901 mpSymbolLookupContext = pContext;
1902 return;
1903 }
1904
Zonr Chang932648d2010-10-13 22:23:56 +08001905 void setTargetMachine(llvm::TargetMachine &TM) {
1906 // Set Target
Shih-wei Liaocd61af32010-04-29 00:02:57 -07001907 mpTarget = &TM.getTarget();
Zonr Chang932648d2010-10-13 22:23:56 +08001908 // Set TargetJITInfo
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001909 mpTJI = TM.getJITInfo();
Zonr Chang932648d2010-10-13 22:23:56 +08001910 // set TargetData
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001911 mpTD = TM.getTargetData();
1912
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001913 assert(!mpTJI->needsGOT() && "We don't support GOT needed target!");
1914
1915 return;
1916 }
1917
Zonr Chang932648d2010-10-13 22:23:56 +08001918 // This callback is invoked when the specified function is about to be code
1919 // generated. This initializes the BufferBegin/End/Ptr fields.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001920 void startFunction(llvm::MachineFunction &F) {
1921 uintptr_t ActualSize = 0;
1922
1923 mpMemMgr->setMemoryWritable();
Zonr Chang932648d2010-10-13 22:23:56 +08001924
1925 // BufferBegin, BufferEnd and CurBufferPtr are all inherited from class
1926 // MachineCodeEmitter, which is the super class of the class
1927 // JITCodeEmitter.
1928 //
1929 // BufferBegin/BufferEnd - Pointers to the start and end of the memory
1930 // allocated for this code buffer.
1931 //
1932 // CurBufferPtr - Pointer to the next byte of memory to fill when emitting
1933 // code. This is guranteed to be in the range
1934 // [BufferBegin, BufferEnd]. If this pointer is at
1935 // BufferEnd, it will never move due to code emission, and
1936 // all code emission requests will be ignored (this is the
1937 // buffer overflow condition).
1938 BufferBegin = CurBufferPtr =
1939 mpMemMgr->startFunctionBody(F.getFunction(), ActualSize);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001940 BufferEnd = BufferBegin + ActualSize;
1941
Zonr Chang932648d2010-10-13 22:23:56 +08001942 if (mpCurEmitFunction == NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001943 mpCurEmitFunction = new EmittedFunctionCode();
1944 mpCurEmitFunction->FunctionBody = BufferBegin;
1945
Zonr Chang932648d2010-10-13 22:23:56 +08001946 // Ensure the constant pool/jump table info is at least 4-byte aligned.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001947 emitAlignment(16);
1948
1949 emitConstantPool(F.getConstantPool());
Zonr Chang932648d2010-10-13 22:23:56 +08001950 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001951 initJumpTableInfo(MJTI);
1952
Zonr Chang932648d2010-10-13 22:23:56 +08001953 // About to start emitting the machine code for the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001954 emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
1955
1956 UpdateGlobalMapping(F.getFunction(), CurBufferPtr);
1957
1958 mpCurEmitFunction->Code = CurBufferPtr;
1959
1960 mMBBLocations.clear();
1961
1962 return;
1963 }
1964
Zonr Chang932648d2010-10-13 22:23:56 +08001965 // This callback is invoked when the specified function has finished code
1966 // generation. If a buffer overflow has occurred, this method returns true
1967 // (the callee is required to try again).
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001968 bool finishFunction(llvm::MachineFunction &F) {
Zonr Chang932648d2010-10-13 22:23:56 +08001969 if (CurBufferPtr == BufferEnd) {
1970 // No enough memory
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001971 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
1972 return false;
1973 }
1974
Zonr Chang932648d2010-10-13 22:23:56 +08001975 if (llvm::MachineJumpTableInfo *MJTI = F.getJumpTableInfo())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001976 emitJumpTableInfo(MJTI);
1977
Zonr Chang932648d2010-10-13 22:23:56 +08001978 // FnStart is the start of the text, not the start of the constant pool
1979 // and other per-function data.
1980 uint8_t *FnStart =
1981 reinterpret_cast<uint8_t*>(
1982 GetPointerToGlobalIfAvailable(F.getFunction()));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001983
Zonr Chang932648d2010-10-13 22:23:56 +08001984 // FnEnd is the end of the function's machine code.
1985 uint8_t *FnEnd = CurBufferPtr;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001986
Zonr Chang932648d2010-10-13 22:23:56 +08001987 if (!mRelocations.empty()) {
1988 // Resolve the relocations to concrete pointers.
1989 for (int i = 0, e = mRelocations.size(); i != e; i++) {
1990 llvm::MachineRelocation &MR = mRelocations[i];
1991 void *ResultPtr = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001992
Zonr Chang932648d2010-10-13 22:23:56 +08001993 if (!MR.letTargetResolve()) {
1994 if (MR.isExternalSymbol()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001995 ResultPtr = GetPointerToNamedSymbol(MR.getExternalSymbol(), true);
Zonr Chang932648d2010-10-13 22:23:56 +08001996 if (MR.mayNeedFarStub())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001997 ResultPtr = GetExternalFunctionStub(ResultPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08001998 } else if (MR.isGlobalValue()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001999 ResultPtr = GetPointerToGlobal(MR.getGlobalValue(),
2000 BufferBegin
2001 + MR.getMachineCodeOffset(),
2002 MR.mayNeedFarStub());
Zonr Chang932648d2010-10-13 22:23:56 +08002003 } else if (MR.isIndirectSymbol()) {
2004 ResultPtr =
2005 GetPointerToGVIndirectSym(
2006 MR.getGlobalValue(),
2007 BufferBegin + MR.getMachineCodeOffset());
2008 } else if (MR.isBasicBlock()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002009 ResultPtr =
2010 (void*) getMachineBasicBlockAddress(MR.getBasicBlock());
Zonr Chang932648d2010-10-13 22:23:56 +08002011 } else if (MR.isConstantPoolIndex()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002012 ResultPtr =
Zonr Chang932648d2010-10-13 22:23:56 +08002013 (void*) getConstantPoolEntryAddress(MR.getConstantPoolIndex());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002014 } else {
2015 assert(MR.isJumpTableIndex() && "Unknown type of relocation");
2016 ResultPtr =
2017 (void*) getJumpTableEntryAddress(MR.getJumpTableIndex());
2018 }
2019
2020 MR.setResultPointer(ResultPtr);
2021 }
2022 }
2023
2024 mpTJI->relocate(BufferBegin, &mRelocations[0], mRelocations.size(),
2025 mpMemMgr->getGOTBase());
2026 }
2027
2028 mpMemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
Zonr Chang932648d2010-10-13 22:23:56 +08002029 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for
2030 // global variables that were referenced in the relocations.
2031 if (CurBufferPtr == BufferEnd)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002032 return false;
2033
Zonr Chang932648d2010-10-13 22:23:56 +08002034 // Now that we've succeeded in emitting the function.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002035 mpCurEmitFunction->Size = CurBufferPtr - BufferBegin;
2036 BufferBegin = CurBufferPtr = 0;
2037
Zonr Chang932648d2010-10-13 22:23:56 +08002038 if (F.getFunction()->hasName())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002039 mEmittedFunctions[F.getFunction()->getNameStr()] = mpCurEmitFunction;
2040 mpCurEmitFunction = NULL;
2041
2042 mRelocations.clear();
2043 mConstPoolAddresses.clear();
2044
Zonr Chang932648d2010-10-13 22:23:56 +08002045 if (mpMMI)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002046 mpMMI->EndFunction();
2047
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002048 updateFunctionStub(F.getFunction());
2049
Zonr Chang932648d2010-10-13 22:23:56 +08002050 // Mark code region readable and executable if it's not so already.
Shih-wei Liaoc4e4ddf2010-09-24 14:50:26 -07002051 mpMemMgr->setMemoryExecutable();
2052
2053 Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
2054
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002055 return false;
2056 }
2057
Zonr Chang932648d2010-10-13 22:23:56 +08002058 void startGVStub(const llvm::GlobalValue *GV, unsigned StubSize,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002059 unsigned Alignment) {
2060 mpSavedBufferBegin = BufferBegin;
2061 mpSavedBufferEnd = BufferEnd;
2062 mpSavedCurBufferPtr = CurBufferPtr;
2063
2064 BufferBegin = CurBufferPtr = mpMemMgr->allocateStub(GV, StubSize,
2065 Alignment);
2066 BufferEnd = BufferBegin + StubSize + 1;
2067
2068 return;
2069 }
2070
Zonr Chang932648d2010-10-13 22:23:56 +08002071 void startGVStub(void *Buffer, unsigned StubSize) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002072 mpSavedBufferBegin = BufferBegin;
2073 mpSavedBufferEnd = BufferEnd;
2074 mpSavedCurBufferPtr = CurBufferPtr;
2075
Zonr Chang932648d2010-10-13 22:23:56 +08002076 BufferBegin = CurBufferPtr = reinterpret_cast<uint8_t *>(Buffer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002077 BufferEnd = BufferBegin + StubSize + 1;
2078
2079 return;
2080 }
2081
2082 void finishGVStub() {
2083 assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
2084
Zonr Chang932648d2010-10-13 22:23:56 +08002085 // restore
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002086 BufferBegin = mpSavedBufferBegin;
2087 BufferEnd = mpSavedBufferEnd;
2088 CurBufferPtr = mpSavedCurBufferPtr;
2089
2090 return;
2091 }
2092
Zonr Chang932648d2010-10-13 22:23:56 +08002093 // Allocates and fills storage for an indirect GlobalValue, and returns the
2094 // address.
2095 void *allocIndirectGV(const llvm::GlobalValue *GV,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002096 const uint8_t *Buffer, size_t Size,
2097 unsigned Alignment) {
Zonr Chang932648d2010-10-13 22:23:56 +08002098 uint8_t *IndGV = mpMemMgr->allocateStub(GV, Size, Alignment);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002099 memcpy(IndGV, Buffer, Size);
2100 return IndGV;
2101 }
2102
Zonr Chang932648d2010-10-13 22:23:56 +08002103 // Emits a label
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002104 void emitLabel(llvm::MCSymbol *Label) {
2105 mLabelLocations[Label] = getCurrentPCValue();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002106 return;
2107 }
2108
Zonr Chang932648d2010-10-13 22:23:56 +08002109 // Allocate memory for a global. Unlike allocateSpace, this method does not
2110 // allocate memory in the current output buffer, because a global may live
2111 // longer than the current function.
2112 void *allocateGlobal(uintptr_t Size, unsigned Alignment) {
2113 // Delegate this call through the memory manager.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002114 return mpMemMgr->allocateGlobal(Size, Alignment);
2115 }
2116
Zonr Chang932648d2010-10-13 22:23:56 +08002117 // This should be called by the target when a new basic block is about to be
2118 // emitted. This way the MCE knows where the start of the block is, and can
2119 // implement getMachineBasicBlockAddress.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002120 void StartMachineBasicBlock(llvm::MachineBasicBlock *MBB) {
Zonr Chang932648d2010-10-13 22:23:56 +08002121 if (mMBBLocations.size() <= (unsigned) MBB->getNumber())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002122 mMBBLocations.resize((MBB->getNumber() + 1) * 2);
2123 mMBBLocations[MBB->getNumber()] = getCurrentPCValue();
2124 return;
2125 }
2126
Zonr Chang932648d2010-10-13 22:23:56 +08002127 // Whenever a relocatable address is needed, it should be noted with this
2128 // interface.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002129 void addRelocation(const llvm::MachineRelocation &MR) {
2130 mRelocations.push_back(MR);
2131 return;
2132 }
2133
Zonr Chang932648d2010-10-13 22:23:56 +08002134 // Return the address of the @Index entry in the constant pool that was
2135 // last emitted with the emitConstantPool method.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002136 uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
2137 assert(Index < mpConstantPool->getConstants().size() &&
2138 "Invalid constant pool index!");
2139 return mConstPoolAddresses[Index];
2140 }
2141
Zonr Chang932648d2010-10-13 22:23:56 +08002142 // Return the address of the jump table with index @Index in the function
2143 // that last called initJumpTableInfo.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002144 uintptr_t getJumpTableEntryAddress(unsigned Index) const {
Zonr Chang932648d2010-10-13 22:23:56 +08002145 const std::vector<llvm::MachineJumpTableEntry> &JT =
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002146 mpJumpTable->getJumpTables();
2147
Zonr Chang932648d2010-10-13 22:23:56 +08002148 assert((Index < JT.size()) && "Invalid jump table index!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002149
2150 unsigned int Offset = 0;
2151 unsigned int EntrySize = mpJumpTable->getEntrySize(*mpTD);
2152
Zonr Chang932648d2010-10-13 22:23:56 +08002153 for (unsigned i = 0; i < Index; i++)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002154 Offset += JT[i].MBBs.size();
2155 Offset *= EntrySize;
2156
Zonr Chang932648d2010-10-13 22:23:56 +08002157 return (uintptr_t)(reinterpret_cast<uint8_t*>(mpJumpTableBase) + Offset);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002158 }
2159
Zonr Chang932648d2010-10-13 22:23:56 +08002160 // Return the address of the specified MachineBasicBlock, only usable after
2161 // the label for the MBB has been emitted.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002162 uintptr_t getMachineBasicBlockAddress(llvm::MachineBasicBlock *MBB) const {
2163 assert(mMBBLocations.size() > (unsigned) MBB->getNumber() &&
Zonr Chang932648d2010-10-13 22:23:56 +08002164 mMBBLocations[MBB->getNumber()] &&
2165 "MBB not emitted!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002166 return mMBBLocations[MBB->getNumber()];
2167 }
2168
Zonr Chang932648d2010-10-13 22:23:56 +08002169 // Return the address of the specified LabelID, only usable after the
2170 // LabelID has been emitted.
2171 uintptr_t getLabelAddress(llvm::MCSymbol *Label) const {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002172 assert(mLabelLocations.count(Label) && "Label not emitted!");
2173 return mLabelLocations.find(Label)->second;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002174 }
2175
Zonr Chang932648d2010-10-13 22:23:56 +08002176 // Specifies the MachineModuleInfo object. This is used for exception
2177 // handling purposes.
2178 void setModuleInfo(llvm::MachineModuleInfo *Info) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002179 mpMMI = Info;
2180 return;
2181 }
2182
Zonr Chang932648d2010-10-13 22:23:56 +08002183 void updateFunctionStub(const llvm::Function *F) {
2184 // Get the empty stub we generated earlier.
2185 void *Stub;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002186 std::set<const llvm::Function*>::iterator I = PendingFunctions.find(F);
Zonr Chang932648d2010-10-13 22:23:56 +08002187 if (I != PendingFunctions.end())
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002188 Stub = mFunctionToLazyStubMap[F];
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002189 else
2190 return;
2191
Zonr Chang932648d2010-10-13 22:23:56 +08002192 void *Addr = GetPointerToGlobalIfAvailable(F);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002193
2194 assert(Addr != Stub &&
2195 "Function must have non-stub address to be updated.");
2196
Zonr Chang932648d2010-10-13 22:23:56 +08002197 // Tell the target jit info to rewrite the stub at the specified address,
2198 // rather than creating a new one.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002199 llvm::TargetJITInfo::StubLayout SL = mpTJI->getStubLayout();
2200 startGVStub(Stub, SL.Size);
2201 mpTJI->emitFunctionStub(F, Addr, *this);
2202 finishGVStub();
2203
Zonr Chang932648d2010-10-13 22:23:56 +08002204 Disassemble(F->getName(), reinterpret_cast<uint8_t*>(Stub),
2205 SL.Size, true);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002206
2207 PendingFunctions.erase(I);
2208
2209 return;
2210 }
2211
Zonr Chang932648d2010-10-13 22:23:56 +08002212 // Once you finish the compilation on a translation unit, you can call this
2213 // function to recycle the memory (which is used at compilation time and not
2214 // needed for runtime).
2215 //
2216 // NOTE: You should not call this funtion until the code-gen passes for a
2217 // given module is done. Otherwise, the results is undefined and may
2218 // cause the system crash!
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002219 void releaseUnnecessary() {
2220 mMBBLocations.clear();
2221 mLabelLocations.clear();
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002222 mGlobalAddressMap.clear();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002223 mFunctionToLazyStubMap.clear();
2224 GlobalToIndirectSymMap.clear();
2225 ExternalFnToStubMap.clear();
2226 PendingFunctions.clear();
2227
2228 return;
2229 }
2230
2231 void reset() {
2232 releaseUnnecessary();
2233
2234 mpSymbolLookupFn = NULL;
2235 mpSymbolLookupContext = NULL;
2236
2237 mpTJI = NULL;
2238 mpTD = NULL;
2239
Zonr Chang932648d2010-10-13 22:23:56 +08002240 for (EmittedFunctionsMapTy::iterator I = mEmittedFunctions.begin(),
2241 E = mEmittedFunctions.end();
2242 I != E;
2243 I++)
2244 if (I->second != NULL)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002245 delete I->second;
2246 mEmittedFunctions.clear();
2247
2248 mpMemMgr->reset();
2249
2250 return;
2251 }
2252
Zonr Chang932648d2010-10-13 22:23:56 +08002253 void *lookup(const char *Name) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002254 return lookup( llvm::StringRef(Name) );
2255 }
2256
Zonr Chang932648d2010-10-13 22:23:56 +08002257 void *lookup(const llvm::StringRef &Name) {
2258 EmittedFunctionsMapTy::const_iterator I =
2259 mEmittedFunctions.find(Name.str());
2260 if (I == mEmittedFunctions.end())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002261 return NULL;
2262 else
2263 return I->second->Code;
2264 }
2265
Zonr Chang932648d2010-10-13 22:23:56 +08002266 void getFunctionNames(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002267 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002268 BCCchar **functions) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002269 int functionCount = mEmittedFunctions.size();
2270
Zonr Chang932648d2010-10-13 22:23:56 +08002271 if (actualFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002272 *actualFunctionCount = functionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002273 if (functionCount > maxFunctionCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002274 functionCount = maxFunctionCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002275 if (functions)
2276 for (EmittedFunctionsMapTy::const_iterator
2277 I = mEmittedFunctions.begin(), E = mEmittedFunctions.end();
2278 (I != E) && (functionCount > 0);
2279 I++, functionCount--)
2280 *functions++ = const_cast<BCCchar*>(I->first.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002281
2282 return;
2283 }
2284
Zonr Chang932648d2010-10-13 22:23:56 +08002285 void getFunctionBinary(BCCchar *label,
2286 BCCvoid **base,
2287 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002288 EmittedFunctionsMapTy::const_iterator I = mEmittedFunctions.find(label);
Zonr Chang932648d2010-10-13 22:23:56 +08002289 if (I == mEmittedFunctions.end()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002290 *base = NULL;
2291 *length = 0;
2292 } else {
2293 *base = I->second->Code;
2294 *length = I->second->Size;
2295 }
2296 return;
2297 }
2298
2299 ~CodeEmitter() {
Zonr Chang932648d2010-10-13 22:23:56 +08002300 delete mpMemMgr;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002301#if defined(USE_DISASSEMBLER)
Zonr Chang932648d2010-10-13 22:23:56 +08002302 delete mpAsmInfo;
2303 delete mpDisassmbler;
2304 delete mpIP;
Shih-wei Liaocd61af32010-04-29 00:02:57 -07002305#endif
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002306 return;
2307 }
Zonr Chang932648d2010-10-13 22:23:56 +08002308 };
2309 // End of Class CodeEmitter
2310 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002311
Zonr Chang932648d2010-10-13 22:23:56 +08002312 // The CodeEmitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002313 llvm::OwningPtr<CodeEmitter> mCodeEmitter;
Zonr Chang932648d2010-10-13 22:23:56 +08002314 CodeEmitter *createCodeEmitter() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002315 mCodeEmitter.reset(new CodeEmitter(mCodeMemMgr.take()));
2316 return mCodeEmitter.get();
2317 }
2318
2319 BCCSymbolLookupFn mpSymbolLookupFn;
Zonr Chang932648d2010-10-13 22:23:56 +08002320 void *mpSymbolLookupContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002321
Zonr Chang932648d2010-10-13 22:23:56 +08002322 llvm::LLVMContext *mContext;
2323 llvm::Module *mModule;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002324
2325 bool mTypeInformationPrepared;
2326 std::vector<const llvm::Type*> mTypes;
2327
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002328 public:
Zonr Chang932648d2010-10-13 22:23:56 +08002329 Compiler()
2330 : mpSymbolLookupFn(NULL),
2331 mpSymbolLookupContext(NULL),
2332 mContext(NULL),
2333 mModule(NULL) {
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002334 llvm::remove_fatal_error_handler();
2335 llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002336 mContext = new llvm::LLVMContext();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002337 return;
2338 }
2339
Zonr Chang932648d2010-10-13 22:23:56 +08002340 // interface for BCCscript::registerSymbolCallback()
2341 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002342 mpSymbolLookupFn = pFn;
2343 mpSymbolLookupContext = pContext;
2344 return;
2345 }
2346
Zonr Changdbee68b2010-10-22 05:02:16 +08002347 int loadModule(llvm::Module *module) {
2348 GlobalInitialization();
2349 mModule = module;
2350 return hasError();
2351 }
2352
Zonr Chang932648d2010-10-13 22:23:56 +08002353 int loadModule(const char *bitcode, size_t bitcodeSize) {
Zonr Chang97f5e612010-10-22 20:38:26 +08002354 llvm::OwningPtr<llvm::MemoryBuffer> SB;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002355
Zonr Chang932648d2010-10-13 22:23:56 +08002356 if (bitcode == NULL || bitcodeSize <= 0)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002357 return 0;
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002358
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002359 GlobalInitialization();
2360
Zonr Chang932648d2010-10-13 22:23:56 +08002361 // Package input to object MemoryBuffer
Zonr Chang97f5e612010-10-22 20:38:26 +08002362 SB.reset(llvm::MemoryBuffer::getMemBuffer(
2363 llvm::StringRef(bitcode, bitcodeSize)));
2364
2365 if (SB.get() == NULL) {
2366 setError("Error reading input program bitcode into memory");
2367 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002368 }
2369
Zonr Chang932648d2010-10-13 22:23:56 +08002370 // Read the input Bitcode as a Module
Zonr Chang97f5e612010-10-22 20:38:26 +08002371 mModule = llvm::ParseBitcodeFile(SB.get(), *mContext, &mError);
2372 SB.reset();
2373 return hasError();
2374 }
Shih-wei Liaoc5611992010-05-09 06:37:55 -07002375
Zonr Chang97f5e612010-10-22 20:38:26 +08002376 int linkModule(const char *bitcode, size_t bitcodeSize) {
2377 llvm::OwningPtr<llvm::MemoryBuffer> SB;
2378
2379 if (bitcode == NULL || bitcodeSize <= 0)
2380 return 0;
2381
2382 if (mModule == NULL) {
2383 setError("No module presents for linking");
2384 return hasError();
2385 }
2386
2387 SB.reset(llvm::MemoryBuffer::getMemBuffer(
2388 llvm::StringRef(bitcode, bitcodeSize)));
2389
2390 if (SB.get() == NULL) {
2391 setError("Error reading input library bitcode into memory");
2392 return hasError();
2393 }
2394
2395 llvm::OwningPtr<llvm::Module> Lib(llvm::ParseBitcodeFile(SB.get(),
2396 *mContext,
2397 &mError));
2398 if (Lib.get() == NULL)
2399 return hasError();
2400
2401 if (llvm::Linker::LinkModules(mModule, Lib.take(), &mError))
2402 return hasError();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002403
2404 return hasError();
2405 }
2406
Zonr Chang932648d2010-10-13 22:23:56 +08002407 // interace for bccCompileScript()
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002408 int compile() {
Zonr Chang932648d2010-10-13 22:23:56 +08002409 llvm::TargetData *TD = NULL;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002410
Zonr Chang932648d2010-10-13 22:23:56 +08002411 llvm::TargetMachine *TM = NULL;
2412 const llvm::Target *Target;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002413 std::string FeaturesStr;
2414
Zonr Chang932648d2010-10-13 22:23:56 +08002415 llvm::FunctionPassManager *CodeGenPasses = NULL;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002416
Zonr Chang932648d2010-10-13 22:23:56 +08002417 const llvm::NamedMDNode *PragmaMetadata;
2418 const llvm::NamedMDNode *ExportVarMetadata;
2419 const llvm::NamedMDNode *ExportFuncMetadata;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002420
Zonr Chang932648d2010-10-13 22:23:56 +08002421 if (mModule == NULL) // No module was loaded
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002422 return 0;
2423
Zonr Chang932648d2010-10-13 22:23:56 +08002424 // Create TargetMachine
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002425 Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
Zonr Chang932648d2010-10-13 22:23:56 +08002426 if (hasError())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002427 goto on_bcc_compile_error;
2428
Zonr Chang932648d2010-10-13 22:23:56 +08002429 if (!CPU.empty() || !Features.empty()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002430 llvm::SubtargetFeatures F;
2431 F.setCPU(CPU);
Zonr Chang932648d2010-10-13 22:23:56 +08002432 for (std::vector<std::string>::const_iterator I = Features.begin(),
2433 E = Features.end();
2434 I != E;
2435 I++)
2436 F.AddFeature(*I);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002437 FeaturesStr = F.getString();
2438 }
2439
2440 TM = Target->createTargetMachine(Triple, FeaturesStr);
Zonr Chang932648d2010-10-13 22:23:56 +08002441 if (TM == NULL) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002442 setError("Failed to create target machine implementation for the"
2443 " specified triple '" + Triple + "'");
2444 goto on_bcc_compile_error;
2445 }
2446
Zonr Chang932648d2010-10-13 22:23:56 +08002447 // Create memory manager for creation of code emitter later.
2448 if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002449 setError("Failed to startup memory management for further compilation");
2450 goto on_bcc_compile_error;
2451 }
2452
Zonr Chang932648d2010-10-13 22:23:56 +08002453 // Create code emitter
2454 if (!mCodeEmitter.get()) {
2455 if (!createCodeEmitter()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002456 setError("Failed to create machine code emitter to complete"
2457 " the compilation");
2458 goto on_bcc_compile_error;
2459 }
2460 } else {
Zonr Chang932648d2010-10-13 22:23:56 +08002461 // Reuse the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002462 mCodeEmitter->reset();
2463 }
2464
2465 mCodeEmitter->setTargetMachine(*TM);
2466 mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
2467 mpSymbolLookupContext);
2468
Zonr Chang932648d2010-10-13 22:23:56 +08002469 // Get target data from Module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002470 TD = new llvm::TargetData(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08002471 // Create code-gen pass to run the code emitter
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002472 CodeGenPasses = new llvm::FunctionPassManager(mModule);
Zonr Chang932648d2010-10-13 22:23:56 +08002473 CodeGenPasses->add(TD); // Will take the ownership of TD
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002474
Zonr Chang932648d2010-10-13 22:23:56 +08002475 if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
2476 *mCodeEmitter,
2477 CodeGenOptLevel)) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002478 setError("The machine code emission is not supported by BCC on target '"
2479 + Triple + "'");
2480 goto on_bcc_compile_error;
2481 }
2482
Zonr Chang932648d2010-10-13 22:23:56 +08002483 // Run the pass (the code emitter) on every non-declaration function in the
2484 // module
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002485 CodeGenPasses->doInitialization();
Zonr Chang932648d2010-10-13 22:23:56 +08002486 for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
2487 I != E;
2488 I++)
2489 if (!I->isDeclaration())
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002490 CodeGenPasses->run(*I);
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002491
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002492 CodeGenPasses->doFinalization();
2493
Zonr Chang932648d2010-10-13 22:23:56 +08002494 // Copy the global address mapping from code emitter and remapping
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002495 ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
Zonr Chang932648d2010-10-13 22:23:56 +08002496 if (ExportVarMetadata) {
2497 for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
2498 llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
2499 if (ExportVar != NULL && ExportVar->getNumOperands() > 1) {
2500 llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
2501 if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002502 llvm::StringRef ExportVarName =
2503 static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
Zonr Chang932648d2010-10-13 22:23:56 +08002504 CodeEmitter::global_addresses_const_iterator I, E;
2505 for (I = mCodeEmitter->global_address_begin(),
2506 E = mCodeEmitter->global_address_end();
2507 I != E;
2508 I++) {
2509 if (I->first->getValueID() != llvm::Value::GlobalVariableVal)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002510 continue;
Zonr Chang932648d2010-10-13 22:23:56 +08002511 if (ExportVarName == I->first->getName()) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002512 mExportVars.push_back(I->second);
2513 break;
2514 }
2515 }
Zonr Chang932648d2010-10-13 22:23:56 +08002516 if (I != mCodeEmitter->global_address_end())
2517 continue; // found
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002518 }
2519 }
Zonr Chang932648d2010-10-13 22:23:56 +08002520 // if here, the global variable record in metadata is not found, make an
2521 // empty slot
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002522 mExportVars.push_back(NULL);
2523 }
2524 assert((mExportVars.size() == ExportVarMetadata->getNumOperands()) &&
2525 "Number of slots doesn't match the number of export variables!");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002526 }
2527
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002528 ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
Zonr Chang932648d2010-10-13 22:23:56 +08002529 if (ExportFuncMetadata) {
2530 for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
2531 llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
2532 if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
2533 llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
2534 if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002535 llvm::StringRef ExportFuncName =
2536 static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
2537 mExportFuncs.push_back(mCodeEmitter->lookup(ExportFuncName));
2538 }
2539 }
2540 }
2541 }
2542
Zonr Chang932648d2010-10-13 22:23:56 +08002543 // Tell code emitter now can release the memory using during the JIT since
2544 // we have done the code emission
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002545 mCodeEmitter->releaseUnnecessary();
2546
Zonr Chang932648d2010-10-13 22:23:56 +08002547 // Finally, read pragma information from the metadata node of the @Module if
2548 // any.
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002549 PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
Zonr Chang932648d2010-10-13 22:23:56 +08002550 if (PragmaMetadata)
2551 for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
2552 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
2553 if (Pragma != NULL &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002554 Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
Zonr Chang932648d2010-10-13 22:23:56 +08002555 llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
2556 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002557
Zonr Chang932648d2010-10-13 22:23:56 +08002558 if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002559 (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
2560 llvm::StringRef PragmaName =
2561 static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
2562 llvm::StringRef PragmaValue =
2563 static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
2564
Zonr Chang932648d2010-10-13 22:23:56 +08002565 mPragmas.push_back(
2566 std::make_pair(std::string(PragmaName.data(),
2567 PragmaName.size()),
2568 std::string(PragmaValue.data(),
2569 PragmaValue.size())));
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002570 }
2571 }
2572 }
2573
2574 on_bcc_compile_error:
Zonr Chang932648d2010-10-13 22:23:56 +08002575 // LOGE("on_bcc_compiler_error");
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002576 if (CodeGenPasses) {
2577 delete CodeGenPasses;
2578 } else if (TD) {
2579 delete TD;
2580 }
2581 if (TM)
2582 delete TM;
2583
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002584 if (mError.empty()) {
2585 return false;
2586 }
2587
Zonr Chang932648d2010-10-13 22:23:56 +08002588 // LOGE(getErrorMessage());
Shih-wei Liao066d5ef2010-05-11 03:28:39 -07002589 return true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002590 }
2591
Zonr Chang932648d2010-10-13 22:23:56 +08002592 // interface for bccGetScriptInfoLog()
2593 char *getErrorMessage() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002594 return const_cast<char*>(mError.c_str());
2595 }
2596
Zonr Chang932648d2010-10-13 22:23:56 +08002597 // interface for bccGetScriptLabel()
2598 void *lookup(const char *name) {
2599 void *addr = NULL;
2600 if (mCodeEmitter.get())
2601 // Find function pointer
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002602 addr = mCodeEmitter->lookup(name);
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002603 return addr;
2604 }
2605
Zonr Chang932648d2010-10-13 22:23:56 +08002606 // Interface for bccGetExportVars()
2607 void getExportVars(BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002608 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002609 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002610 int varCount = mExportVars.size();
2611
Zonr Chang932648d2010-10-13 22:23:56 +08002612 if (actualVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002613 *actualVarCount = varCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002614 if (varCount > maxVarCount)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002615 varCount = maxVarCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002616 if (vars)
2617 for (ExportVarList::const_iterator I = mExportVars.begin(),
2618 E = mExportVars.end();
2619 I != E;
2620 I++)
2621 *vars++ = *I;
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002622
2623 return;
2624 }
2625
Zonr Chang932648d2010-10-13 22:23:56 +08002626 // Interface for bccGetExportFuncs()
2627 void getExportFuncs(BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002628 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002629 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002630 int funcCount = mExportFuncs.size();
2631
Zonr Chang932648d2010-10-13 22:23:56 +08002632 if (actualFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002633 *actualFuncCount = funcCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002634 if (funcCount > maxFuncCount)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002635 funcCount = maxFuncCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002636 if (funcs)
2637 for (ExportFuncList::const_iterator I = mExportFuncs.begin(),
2638 E = mExportFuncs.end();
2639 I != E;
2640 I++)
2641 *funcs++ = *I;
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002642
2643 return;
2644 }
2645
Zonr Chang932648d2010-10-13 22:23:56 +08002646 // Interface for bccGetPragmas()
2647 void getPragmas(BCCsizei *actualStringCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002648 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002649 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002650 int stringCount = mPragmas.size() * 2;
2651
Zonr Chang932648d2010-10-13 22:23:56 +08002652 if (actualStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002653 *actualStringCount = stringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002654 if (stringCount > maxStringCount)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002655 stringCount = maxStringCount;
Zonr Chang932648d2010-10-13 22:23:56 +08002656 if (strings)
2657 for (PragmaList::const_iterator it = mPragmas.begin();
2658 stringCount > 0;
2659 stringCount -= 2, it++) {
2660 *strings++ = const_cast<BCCchar*>(it->first.c_str());
2661 *strings++ = const_cast<BCCchar*>(it->second.c_str());
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002662 }
2663
2664 return;
2665 }
2666
Zonr Chang932648d2010-10-13 22:23:56 +08002667 // Interface for bccGetFunctions()
2668 void getFunctions(BCCsizei *actualFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002669 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002670 BCCchar **functions) {
2671 if (mCodeEmitter.get())
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002672 mCodeEmitter->getFunctionNames(actualFunctionCount,
2673 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002674 functions);
2675 else
2676 *actualFunctionCount = 0;
2677
2678 return;
2679 }
2680
Zonr Chang932648d2010-10-13 22:23:56 +08002681 // Interface for bccGetFunctionBinary()
2682 void getFunctionBinary(BCCchar *function,
2683 BCCvoid **base,
2684 BCCsizei *length) {
2685 if (mCodeEmitter.get()) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002686 mCodeEmitter->getFunctionBinary(function, base, length);
2687 } else {
2688 *base = NULL;
2689 *length = 0;
2690 }
2691 return;
2692 }
2693
Zonr Chang932648d2010-10-13 22:23:56 +08002694 inline const llvm::Module *getModule() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002695 return mModule;
2696 }
2697
Zonr Chang932648d2010-10-13 22:23:56 +08002698 inline const std::vector<const llvm::Type*> &getTypes() const {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002699 return mTypes;
2700 }
2701
2702 ~Compiler() {
2703 delete mModule;
Zonr Chang932648d2010-10-13 22:23:56 +08002704 // llvm::llvm_shutdown();
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002705 delete mContext;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002706 return;
2707 }
Zonr Chang932648d2010-10-13 22:23:56 +08002708};
2709// End of Class Compiler
2710////////////////////////////////////////////////////////////////////////////////
2711
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002712
2713bool Compiler::GlobalInitialized = false;
2714
Zonr Chang932648d2010-10-13 22:23:56 +08002715// Code generation optimization level for the compiler
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002716llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
2717
2718std::string Compiler::Triple;
2719
2720std::string Compiler::CPU;
2721
2722std::vector<std::string> Compiler::Features;
2723
Zonr Chang932648d2010-10-13 22:23:56 +08002724// The named of metadata node that pragma resides (should be synced with
2725// slang.cpp)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002726const llvm::StringRef Compiler::PragmaMetadataName = "#pragma";
2727
Zonr Chang932648d2010-10-13 22:23:56 +08002728// The named of metadata node that export variable name resides (should be
2729// synced with slang_rs_metadata.h)
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002730const llvm::StringRef Compiler::ExportVarMetadataName = "#rs_export_var";
2731
Zonr Chang932648d2010-10-13 22:23:56 +08002732// The named of metadata node that export function name resides (should be
2733// synced with slang_rs_metadata.h)
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002734const llvm::StringRef Compiler::ExportFuncMetadataName = "#rs_export_func";
2735
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002736struct BCCscript {
Zonr Chang932648d2010-10-13 22:23:56 +08002737 //////////////////////////////////////////////////////////////////////////////
2738 // Part I. Compiler
2739 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002740 Compiler compiler;
2741
Zonr Chang932648d2010-10-13 22:23:56 +08002742 void registerSymbolCallback(BCCSymbolLookupFn pFn, BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002743 compiler.registerSymbolCallback(pFn, pContext);
2744 }
2745
Zonr Chang932648d2010-10-13 22:23:56 +08002746 //////////////////////////////////////////////////////////////////////////////
2747 // Part II. Logistics & Error handling
2748 //////////////////////////////////////////////////////////////////////////////
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002749 BCCscript() {
2750 bccError = BCC_NO_ERROR;
2751 }
2752
2753 ~BCCscript() {
2754 }
2755
2756 void setError(BCCenum error) {
2757 if (bccError == BCC_NO_ERROR && error != BCC_NO_ERROR) {
2758 bccError = error;
2759 }
2760 }
2761
2762 BCCenum getError() {
2763 BCCenum result = bccError;
2764 bccError = BCC_NO_ERROR;
2765 return result;
2766 }
2767
2768 BCCenum bccError;
2769};
2770
2771
2772extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002773BCCscript *bccCreateScript() {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002774 return new BCCscript();
2775}
2776
2777extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002778BCCenum bccGetError(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002779 return script->getError();
2780}
2781
2782extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002783void bccDeleteScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002784 delete script;
2785}
2786
2787extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002788void bccRegisterSymbolCallback(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002789 BCCSymbolLookupFn pFn,
Zonr Chang932648d2010-10-13 22:23:56 +08002790 BCCvoid *pContext) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002791 script->registerSymbolCallback(pFn, pContext);
2792}
2793
2794extern "C"
Zonr Changdbee68b2010-10-22 05:02:16 +08002795void bccScriptModule(BCCscript *script,
2796 BCCvoid *module) {
2797 script->compiler.loadModule(reinterpret_cast<llvm::Module*>(module));
2798}
2799
2800extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002801void bccScriptBitcode(BCCscript *script,
2802 const BCCchar *bitcode,
2803 BCCint size) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002804 script->compiler.loadModule(bitcode, size);
2805}
2806
2807extern "C"
Zonr Chang97f5e612010-10-22 20:38:26 +08002808void bccLinkBitcode(BCCscript *script,
2809 const BCCchar *bitcode,
2810 BCCint size) {
2811 script->compiler.linkModule(bitcode, size);
2812}
2813
2814extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002815void bccCompileScript(BCCscript *script) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002816 int result = script->compiler.compile();
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002817 if (result)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002818 script->setError(BCC_INVALID_OPERATION);
2819}
2820
2821extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002822void bccGetScriptInfoLog(BCCscript *script,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002823 BCCsizei maxLength,
Zonr Chang932648d2010-10-13 22:23:56 +08002824 BCCsizei *length,
2825 BCCchar *infoLog) {
2826 char *message = script->compiler.getErrorMessage();
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002827 int messageLength = strlen(message) + 1;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002828 if (length)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002829 *length = messageLength;
2830
2831 if (infoLog && maxLength > 0) {
2832 int trimmedLength = maxLength < messageLength ? maxLength : messageLength;
2833 memcpy(infoLog, message, trimmedLength);
2834 infoLog[trimmedLength] = 0;
2835 }
2836}
2837
2838extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002839void bccGetScriptLabel(BCCscript *script,
2840 const BCCchar *name,
2841 BCCvoid **address) {
2842 void *value = script->compiler.lookup(name);
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002843 if (value)
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002844 *address = value;
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002845 else
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002846 script->setError(BCC_INVALID_VALUE);
2847}
2848
2849extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002850void bccGetExportVars(BCCscript *script,
2851 BCCsizei *actualVarCount,
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002852 BCCsizei maxVarCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002853 BCCvoid **vars) {
Shih-wei Liaoabd1e3d2010-04-28 01:47:00 -07002854 script->compiler.getExportVars(actualVarCount, maxVarCount, vars);
2855}
2856
2857extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002858void bccGetExportFuncs(BCCscript *script,
2859 BCCsizei *actualFuncCount,
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002860 BCCsizei maxFuncCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002861 BCCvoid **funcs) {
Shih-wei Liao6bfd5422010-05-07 05:20:22 -07002862 script->compiler.getExportFuncs(actualFuncCount, maxFuncCount, funcs);
2863}
2864
2865extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002866void bccGetPragmas(BCCscript *script,
2867 BCCsizei *actualStringCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002868 BCCsizei maxStringCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002869 BCCchar **strings) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002870 script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
2871}
2872
2873extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002874void bccGetFunctions(BCCscript *script,
2875 BCCsizei *actualFunctionCount,
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002876 BCCsizei maxFunctionCount,
Zonr Chang932648d2010-10-13 22:23:56 +08002877 BCCchar **functions) {
Shih-wei Liao3cf39d12010-04-29 19:30:51 -07002878 script->compiler.getFunctions(actualFunctionCount,
2879 maxFunctionCount,
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002880 functions);
2881}
2882
2883extern "C"
Zonr Chang932648d2010-10-13 22:23:56 +08002884void bccGetFunctionBinary(BCCscript *script,
2885 BCCchar *function,
2886 BCCvoid **base,
2887 BCCsizei *length) {
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002888 script->compiler.getFunctionBinary(function, base, length);
2889}
2890
2891struct BCCtype {
Zonr Chang932648d2010-10-13 22:23:56 +08002892 const Compiler *compiler;
2893 const llvm::Type *t;
Shih-wei Liao77ed6142010-04-07 12:21:42 -07002894};
2895
Zonr Chang932648d2010-10-13 22:23:56 +08002896} // namespace bcc