ASC-4041: Skip two spidermonkey regression tests due to stack overflow when compiling...
[tamarin-stm.git] / nanojit / nanojit.h
blobd3fee308c42a968cdf764da12d1bd8b79be4a190
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is [Open Source Virtual Machine].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2007
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Adobe AS3 Team
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef __nanojit_h__
41 #define __nanojit_h__
43 #include "avmplus.h"
45 #ifdef FEATURE_NANOJIT
47 #if defined AVMPLUS_IA32
48 #define NANOJIT_IA32
49 #elif defined AVMPLUS_ARM
50 #define NANOJIT_ARM
51 #elif defined AVMPLUS_PPC
52 #define NANOJIT_PPC
53 #elif defined AVMPLUS_SPARC
54 #define NANOJIT_SPARC
55 #elif defined AVMPLUS_AMD64
56 #define NANOJIT_X64
57 #elif defined VMCFG_SH4
58 #define NANOJIT_SH4
59 #elif defined AVMPLUS_MIPS
60 #define NANOJIT_MIPS
61 #else
62 #error "unknown nanojit architecture"
63 #endif
65 #ifdef AVMPLUS_64BIT
66 #define NANOJIT_64BIT
67 #endif
69 #if defined NANOJIT_64BIT
70 #define IF_64BIT(...) __VA_ARGS__
71 #define UNLESS_64BIT(...)
72 #define CASE32(x)
73 #define CASE64(x) case x
74 #else
75 #define IF_64BIT(...)
76 #define UNLESS_64BIT(...) __VA_ARGS__
77 #define CASE32(x) case x
78 #define CASE64(x)
79 #endif
81 #if defined NANOJIT_IA32 || defined NANOJIT_X64
82 #define CASE86(x) case x
83 #else
84 #define CASE86(x)
85 #endif
87 // Embed no-op macros that let Valgrind work with the JIT.
88 #ifdef MOZ_VALGRIND
89 # define JS_VALGRIND
90 #endif
91 #ifdef JS_VALGRIND
92 # include <valgrind/valgrind.h>
93 #elif !defined(VALGRIND_DISCARD_TRANSLATIONS)
94 # define VALGRIND_DISCARD_TRANSLATIONS(addr, szB)
95 #endif
97 namespace nanojit
99 /**
100 * -------------------------------------------
101 * START AVM bridging definitions
102 * -------------------------------------------
104 typedef avmplus::AvmCore AvmCore;
106 const uint32_t MAXARGS = 8;
108 #ifdef NJ_NO_VARIADIC_MACROS
109 inline void NanoAssertMsgf(bool a,const char *f,...) {}
110 inline void NanoAssertMsg(bool a,const char *m) {}
111 inline void NanoAssert(bool a) {}
112 #elif defined(_DEBUG)
114 #define __NanoAssertMsgf(a, file_, line_, f, ...) \
115 if (!(a)) { \
116 avmplus::AvmLog("Assertion failure: " f "%s (%s:%d)\n", __VA_ARGS__, #a, file_, line_); \
117 avmplus::AvmAssertFail(""); \
120 #define _NanoAssertMsgf(a, file_, line_, f, ...) __NanoAssertMsgf(a, file_, line_, f, __VA_ARGS__)
122 #define NanoAssertMsgf(a,f,...) do { __NanoAssertMsgf(a, __FILE__, __LINE__, f ": ", __VA_ARGS__); } while (0)
123 #define NanoAssertMsg(a,m) do { __NanoAssertMsgf(a, __FILE__, __LINE__, "\"%s\": ", m); } while (0)
124 #define NanoAssert(a) do { __NanoAssertMsgf(a, __FILE__, __LINE__, "%s", ""); } while (0)
125 #else
126 #define NanoAssertMsgf(a,f,...) do { } while (0) /* no semi */
127 #define NanoAssertMsg(a,m) do { } while (0) /* no semi */
128 #define NanoAssert(a) do { } while (0) /* no semi */
129 #endif
132 * Sun Studio C++ compiler has a bug
133 * "sizeof expression not accepted as size of array parameter"
134 * The bug number is 6688515. It is not public yet.
135 * Turn off this assert for Sun Studio until this bug is fixed.
137 #ifdef __SUNPRO_CC
138 #define NanoStaticAssert(condition)
139 #else
140 #define NanoStaticAssert(condition) \
141 extern void nano_static_assert(int arg[(condition) ? 1 : -1])
142 #endif
146 * -------------------------------------------
147 * END AVM bridging definitions
148 * -------------------------------------------
152 #ifdef AVMPLUS_VERBOSE
153 #define NJ_VERBOSE 1
154 #endif
156 #ifdef NJ_NO_VARIADIC_MACROS
157 #include <stdio.h>
158 #define verbose_outputf if (_logc->lcbits & LC_Native) \
159 Assembler::outputf
160 #define verbose_only(x) x
161 #elif defined(NJ_VERBOSE)
162 #include <stdio.h>
163 #define verbose_outputf if (_logc->lcbits & LC_Native) \
164 Assembler::outputf
165 #define verbose_only(...) __VA_ARGS__
166 #else
167 #define verbose_outputf
168 #define verbose_only(...)
169 #endif /*NJ_VERBOSE*/
171 #ifdef _DEBUG
172 #define debug_only(x) x
173 #else
174 #define debug_only(x)
175 #endif /* DEBUG */
177 #define isS8(i) ( int32_t(i) == int8_t(i) )
178 #define isU8(i) ( int32_t(i) == uint8_t(i) )
179 #define isS16(i) ( int32_t(i) == int16_t(i) )
180 #define isU16(i) ( int32_t(i) == uint16_t(i) )
181 #define isS24(i) ( (int32_t((i)<<8)>>8) == (i) )
183 static inline bool isS32(intptr_t i) {
184 return int32_t(i) == i;
187 static inline bool isU32(uintptr_t i) {
188 return uint32_t(i) == i;
191 #define alignTo(x,s) ((((uintptr_t)(x)))&~(((uintptr_t)s)-1))
192 #define alignUp(x,s) ((((uintptr_t)(x))+(((uintptr_t)s)-1))&~(((uintptr_t)s)-1))
194 #define NJ_MIN(x, y) ((x) < (y) ? (x) : (y))
195 #define NJ_MAX(x, y) ((x) > (y) ? (x) : (y))
197 namespace nanojit
199 // Define msbSet32(), lsbSet32(), msbSet64(), and lsbSet64() functions using
200 // fast find-first-bit instructions intrinsics when available.
201 // The fall-back implementations use iteration.
202 #if defined(_WIN32) && (_MSC_VER >= 1300) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
204 extern "C" unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask);
205 extern "C" unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask);
206 # pragma intrinsic(_BitScanForward)
207 # pragma intrinsic(_BitScanReverse)
209 // Returns the index of the most significant bit that is set.
210 static inline int msbSet32(uint32_t x) {
211 unsigned long idx;
212 _BitScanReverse(&idx, (unsigned long)(x | 1)); // the '| 1' ensures a 0 result when x==0
213 return idx;
216 // Returns the index of the least significant bit that is set.
217 static inline int lsbSet32(uint32_t x) {
218 unsigned long idx;
219 _BitScanForward(&idx, (unsigned long)(x | 0x80000000)); // the '| 0x80000000' ensures a 0 result when x==0
220 return idx;
223 #if defined(_M_AMD64) || defined(_M_X64)
224 extern "C" unsigned char _BitScanForward64(unsigned long * Index, unsigned __int64 Mask);
225 extern "C" unsigned char _BitScanReverse64(unsigned long * Index, unsigned __int64 Mask);
226 # pragma intrinsic(_BitScanForward64)
227 # pragma intrinsic(_BitScanReverse64)
229 // Returns the index of the most significant bit that is set.
230 static inline int msbSet64(uint64_t x) {
231 unsigned long idx;
232 _BitScanReverse64(&idx, (unsigned __int64)(x | 1)); // the '| 1' ensures a 0 result when x==0
233 return idx;
236 // Returns the index of the least significant bit that is set.
237 static inline int lsbSet64(uint64_t x) {
238 unsigned long idx;
239 _BitScanForward64(&idx, (unsigned __int64)(x | 0x8000000000000000LL)); // the '| 0x80000000' ensures a 0 result when x==0
240 return idx;
242 #else
243 // Returns the index of the most significant bit that is set.
244 static int msbSet64(uint64_t x) {
245 return (x & 0xffffffff00000000LL) ? msbSet32(uint32_t(x >> 32)) + 32 : msbSet32(uint32_t(x));
247 // Returns the index of the least significant bit that is set.
248 static int lsbSet64(uint64_t x) {
249 return (x & 0x00000000ffffffffLL) ? lsbSet32(uint32_t(x)) : lsbSet32(uint32_t(x >> 32)) + 32;
251 #endif
253 #elif (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
255 // Returns the index of the most significant bit that is set.
256 static inline int msbSet32(uint32_t x) {
257 return 31 - __builtin_clz(x | 1);
260 // Returns the index of the least significant bit that is set.
261 static inline int lsbSet32(uint32_t x) {
262 return __builtin_ctz(x | 0x80000000);
265 // Returns the index of the most significant bit that is set.
266 static inline int msbSet64(uint64_t x) {
267 return 63 - __builtin_clzll(x | 1);
270 // Returns the index of the least significant bit that is set.
271 static inline int lsbSet64(uint64_t x) {
272 return __builtin_ctzll(x | 0x8000000000000000LL);
275 #else
277 // Slow fall-back: return most significant bit set by searching iteratively.
278 static int msbSet32(uint32_t x) {
279 for (int i = 31; i >= 0; i--)
280 if ((1 << i) & x)
281 return i;
282 return 0;
285 // Slow fall-back: return least significant bit set by searching iteratively.
286 static int lsbSet32(uint32_t x) {
287 for (int i = 0; i < 32; i++)
288 if ((1 << i) & x)
289 return i;
290 return 31;
293 // Slow fall-back: return most significant bit set by searching iteratively.
294 static int msbSet64(uint64_t x) {
295 for (int i = 63; i >= 0; i--)
296 if ((1LL << i) & x)
297 return i;
298 return 0;
301 // Slow fall-back: return least significant bit set by searching iteratively.
302 static int lsbSet64(uint64_t x) {
303 for (int i = 0; i < 64; i++)
304 if ((1LL << i) & x)
305 return i;
306 return 63;
309 #endif // select compiler
310 } // namespace nanojit
312 // -------------------------------------------------------------------
313 // START debug-logging definitions
314 // -------------------------------------------------------------------
316 /* Debug printing stuff. All Nanojit and jstracer debug printing
317 should be routed through LogControl::printf. Don't use
318 ad-hoc calls to printf, fprintf(stderr, ...) etc.
320 Similarly, don't use ad-hoc getenvs etc to decide whether or not to
321 print debug output. Instead consult the relevant control bit in
322 LogControl::lcbits in the LogControl object you are supplied with.
325 # if defined(__GNUC__)
326 # define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y)))
327 # else
328 # define PRINTF_CHECK(x, y)
329 # endif
331 namespace nanojit {
333 // LogControl, a class for controlling and routing debug output
335 enum LC_Bits {
336 /* Output control bits for Nanojit code. Only use bits 15
337 and below, so that callers can use bits 16 and above for
338 themselves. */
339 // TODO: add entries for the writer pipeline
340 LC_FragProfile = 1<<7, // collect per-frag usage counts
341 LC_Liveness = 1<<6, // show LIR liveness analysis
342 LC_ReadLIR = 1<<5, // as read from LirBuffer
343 LC_AfterSF = 1<<4, // after StackFilter
344 LC_AfterDCE = 1<<3, // after dead code elimination
345 LC_Native = 1<<2, // final native code
346 LC_RegAlloc = 1<<1, // stuff to do with reg alloc
347 LC_Activation = 1<<0 // enable printActivationState
350 class LogControl
352 public:
353 // All Nanojit and jstracer printing should be routed through
354 // this function.
355 virtual ~LogControl() {}
356 #ifdef NJ_VERBOSE
357 virtual void printf( const char* format, ... ) PRINTF_CHECK(2,3);
358 #endif
360 // An OR of LC_Bits values, indicating what should be output
361 uint32_t lcbits;
365 // -------------------------------------------------------------------
366 // END debug-logging definitions
367 // -------------------------------------------------------------------
370 #include "njconfig.h"
371 #include "Allocator.h"
372 #include "Containers.h"
373 #include "Native.h"
374 #include "CodeAlloc.h"
375 #include "LIR.h"
376 #include "RegAlloc.h"
377 #include "Fragmento.h"
378 #include "Assembler.h"
380 #endif // FEATURE_NANOJIT
381 #endif // __nanojit_h__