Get rid of type-punning pointer casts
[ruby.git] / vm_exec.h
blobc3b7d4e48882c3fec95973ae213cf9a0c62b659c
1 #ifndef RUBY_VM_EXEC_H
2 #define RUBY_VM_EXEC_H
3 /**********************************************************************
5 vm.h -
7 $Author$
8 created at: 04/01/01 16:56:59 JST
10 Copyright (C) 2004-2007 Koichi Sasada
12 **********************************************************************/
14 typedef long OFFSET;
15 typedef unsigned long lindex_t;
16 typedef VALUE GENTRY;
17 typedef rb_iseq_t *ISEQ;
19 #if VMDEBUG > 0
20 #define debugs printf
21 #define DEBUG_ENTER_INSN(insn) \
22 rb_vmdebug_debug_print_pre(ec, GET_CFP(), GET_PC());
24 #define SC_REGS()
26 #define DEBUG_END_INSN() \
27 rb_vmdebug_debug_print_post(ec, GET_CFP() SC_REGS());
29 #else
31 #define debugs
32 #define DEBUG_ENTER_INSN(insn)
33 #define DEBUG_END_INSN()
34 #endif
36 #define throwdebug if(0)ruby_debug_printf
37 /* #define throwdebug ruby_debug_printf */
39 /************************************************/
40 #if defined(DISPATCH_XXX)
41 error !
42 /************************************************/
43 #elif OPT_CALL_THREADED_CODE
45 #define LABEL(x) insn_func_##x
46 #define ELABEL(x)
47 #define LABEL_PTR(x) &LABEL(x)
49 #define INSN_ENTRY(insn) \
50 static rb_control_frame_t * \
51 FUNC_FASTCALL(LABEL(insn))(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp) {
53 #define END_INSN(insn) return reg_cfp;}
55 #define NEXT_INSN() return reg_cfp;
57 #define START_OF_ORIGINAL_INSN(x) /* ignore */
58 #define DISPATCH_ORIGINAL_INSN(x) return LABEL(x)(ec, reg_cfp);
60 /************************************************/
61 #elif OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
62 /* threaded code with gcc */
64 #define LABEL(x) INSN_LABEL_##x
65 #define ELABEL(x) INSN_ELABEL_##x
66 #define LABEL_PTR(x) RB_GNUC_EXTENSION(&&LABEL(x))
68 #define INSN_ENTRY_SIG(insn) \
69 if (0) { \
70 ruby_debug_printf("exec: %s@(%"PRIdPTRDIFF", %"PRIdPTRDIFF")@%s:%u\n", #insn, \
71 (reg_pc - ISEQ_BODY(reg_cfp->iseq)->iseq_encoded), \
72 (reg_cfp->pc - ISEQ_BODY(reg_cfp->iseq)->iseq_encoded), \
73 RSTRING_PTR(rb_iseq_path(reg_cfp->iseq)), \
74 rb_iseq_line_no(reg_cfp->iseq, reg_pc - ISEQ_BODY(reg_cfp->iseq)->iseq_encoded)); \
77 #define INSN_DISPATCH_SIG(insn)
79 #define INSN_ENTRY(insn) \
80 LABEL(insn): \
81 INSN_ENTRY_SIG(insn); \
83 /**********************************/
84 #if OPT_DIRECT_THREADED_CODE
86 /* for GCC 3.4.x */
87 #define TC_DISPATCH(insn) \
88 INSN_DISPATCH_SIG(insn); \
89 RB_GNUC_EXTENSION_BLOCK(goto *(void const *)GET_CURRENT_INSN()); \
92 #else
93 /* token threaded code */
95 /* dispatcher */
96 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && __GNUC__ == 3
97 #define DISPATCH_ARCH_DEPEND_WAY(addr) \
98 __asm__ __volatile__("jmp *%0;\t# -- inserted by vm.h\t[length = 2]" : : "r" (addr))
100 #else
101 #define DISPATCH_ARCH_DEPEND_WAY(addr) \
102 /* do nothing */
103 #endif
104 #define TC_DISPATCH(insn) \
105 DISPATCH_ARCH_DEPEND_WAY(insns_address_table[GET_CURRENT_INSN()]); \
106 INSN_DISPATCH_SIG(insn); \
107 RB_GNUC_EXTENSION_BLOCK(goto *insns_address_table[GET_CURRENT_INSN()]); \
108 rb_bug("tc error");
110 #endif /* OPT_DIRECT_THREADED_CODE */
112 #define END_INSN(insn) \
113 DEBUG_END_INSN(); \
114 TC_DISPATCH(insn);
116 #define INSN_DISPATCH() \
117 TC_DISPATCH(__START__) \
120 #define END_INSNS_DISPATCH() \
121 rb_bug("unknown insn: %"PRIdVALUE, GET_CURRENT_INSN()); \
122 } /* end of while loop */ \
124 #define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__)
126 /************************************************/
127 #else /* no threaded code */
128 /* most common method */
130 #define INSN_ENTRY(insn) \
131 case BIN(insn):
133 #define END_INSN(insn) \
134 DEBUG_END_INSN(); \
135 break;
137 #define INSN_DISPATCH() \
138 while (1) { \
139 switch (GET_CURRENT_INSN()) {
141 #define END_INSNS_DISPATCH() \
142 default: \
143 SDR(); \
144 rb_bug("unknown insn: %ld", GET_CURRENT_INSN()); \
145 } /* end of switch */ \
146 } /* end of while loop */ \
148 #define NEXT_INSN() goto first
150 #endif
152 #ifndef START_OF_ORIGINAL_INSN
153 #define START_OF_ORIGINAL_INSN(x) if (0) goto start_of_##x; start_of_##x:
154 #define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x;
155 #endif
157 #define VM_SP_CNT(ec, sp) ((sp) - (ec)->vm_stack)
159 #if OPT_CALL_THREADED_CODE
160 #define THROW_EXCEPTION(exc) do { \
161 ec->errinfo = (VALUE)(exc); \
162 return 0; \
163 } while (0)
164 #else
165 #define THROW_EXCEPTION(exc) return (VALUE)(exc)
166 #endif
168 // Run the interpreter from the JIT
169 #define VM_EXEC(ec, val) do { \
170 if (UNDEF_P(val)) { \
171 VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH); \
172 val = vm_exec(ec); \
174 } while (0)
176 // Run the JIT from the interpreter
177 #define JIT_EXEC(ec, val) do { \
178 rb_jit_func_t func; \
179 /* don't run tailcalls since that breaks FINISH */ \
180 if (UNDEF_P(val) && GET_CFP() != ec->cfp && (func = jit_compile(ec))) { \
181 val = func(ec, ec->cfp); \
182 if (ec->tag->state) THROW_EXCEPTION(val); \
184 } while (0)
186 #define SCREG(r) (reg_##r)
188 #define VM_DEBUG_STACKOVERFLOW 0
190 #if VM_DEBUG_STACKOVERFLOW
191 #define CHECK_VM_STACK_OVERFLOW_FOR_INSN CHECK_VM_STACK_OVERFLOW
192 #else
193 #define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin)
194 #endif
196 #define INSN_LABEL2(insn, name) INSN_LABEL_ ## insn ## _ ## name
197 #define INSN_LABEL(x) INSN_LABEL2(NAME_OF_CURRENT_INSN, x)
199 #endif /* RUBY_VM_EXEC_H */