From 7f7834abf738ab26236bea159fce7f37dea03f1f Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 23 Sep 2008 07:49:45 +0000 Subject: * include/ruby/node.h, vm_core.h: move definition of RUBY_VM_METHOD_NODE to node.h. * class.c, common.mk: remove useless inclusion. * compile.h, iseq.h, vm_core.h: rename compile.h to iseq.h. move some definitions from vm_core.h to iseq.h. * compile.c, iseq.c, vm.c: ditto. * eval.c, compile.c: move some functions for parser from eval.c to compile.c. * eval_intern.h, vm_core.h: move va_init_list() macro to vm_core.h. * iseq.c (rb_iseq_new_top, rb_iseq_first_lineno): added. * load.c, ruby.c: use rb_iseq_new_top() instead of rb_iseq_new() with ISEQ_TYPE_TOP constant directly. * proc.c: use rb_iseq_first_lineno() instead of accessing iseq structure. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19472 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- compile.c | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 279 insertions(+), 12 deletions(-) (limited to 'compile.c') diff --git a/compile.c b/compile.c index 41d1a9247f..8e8decbe96 100644 --- a/compile.c +++ b/compile.c @@ -14,21 +14,10 @@ #define USE_INSN_STACK_INCREASE 1 #include "vm_core.h" -#include "compile.h" +#include "iseq.h" #include "insns.inc" #include "insns_info.inc" -#ifdef HAVE_STDARG_PROTOTYPES -#include -#define va_init_list(a,b) va_start(a,b) -#else -#include -#define va_init_list(a,b) va_start(a) -#endif - -VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt); - -/* types */ typedef struct iseq_link_element { enum { @@ -82,6 +71,232 @@ struct iseq_compile_data_ensure_node_stack { struct ensure_range *erange; }; +/** + * debug function(macro) interface depend on CPDEBUG + * if it is less than 0, runtime option is in effect. + * + * debug level: + * 0: no debug output + * 1: show node type + * 2: show node important parameters + * ... + * 5: show other parameters + * 10: show every AST array + */ + +#ifndef CPDEBUG +#define CPDEBUG 0 +#endif + +#if CPDEBUG >= 0 +#define compile_debug CPDEBUG +#else +#define compile_debug iseq->compile_data->option->debug_level +#endif + +NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4)); + +#if CPDEBUG + +#define compile_debug_print_indent(level) \ + ruby_debug_print_indent(level, compile_debug, gl_node_level * 2) + +#define debugp(header, value) (void) \ + (compile_debug_print_indent(1) && \ + ruby_debug_print_value(1, compile_debug, header, value)) + +#define debugi(header, id) (void) \ + (compile_debug_print_indent(1) && \ + ruby_debug_print_id(1, compile_debug, header, id)) + +#define debugp_param(header, value) (void) \ + (compile_debug_print_indent(1) && \ + ruby_debug_print_value(1, compile_debug, header, value)) + +#define debugp_verbose(header, value) (void) \ + (compile_debug_print_indent(2) && \ + ruby_debug_print_value(2, compile_debug, header, value)) + +#define debugp_verbose_node(header, value) (void) \ + (compile_debug_print_indent(10) && \ + ruby_debug_print_value(10, compile_debug, header, value)) + +#define debug_node_start(node) ((void) \ + (compile_debug_print_indent(1) && \ + (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)node), gl_node_level)), \ + gl_node_level++) + +#define debug_node_end() gl_node_level --; + +#else + +static inline ID +r_id(ID id) +{ + return id; +} + +static inline VALUE +r_value(VALUE value) +{ + return value; +} + +#define debugi(header, id) r_id(id) +#define debugp(header, value) r_value(value) +#define debugp_verbose(header, value) r_value(value) +#define debugp_verbose_node(header, value) r_value(value) +#define debugp_param(header, value) r_value(value) +#define debug_node_start(node) ((void)0) +#define debug_node_end() ((void)0) +#endif + +#if CPDEBUG > 1 || CPDEBUG < 0 +PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2); +#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf +#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs(msg, stderr)), (v)) +#else +#define debugs if(0)printf +#define debug_compile(msg, v) (v) +#endif + + +/* create new label */ +#define NEW_LABEL(l) new_label_body(iseq, l) + +#define iseq_filename(iseq) \ + (((rb_iseq_t*)DATA_PTR(iseq))->filename) + +#define NEW_ISEQVAL(node, name, type) \ + new_child_iseq(iseq, node, name, 0, type) + +#define NEW_CHILD_ISEQVAL(node, name, type) \ + new_child_iseq(iseq, node, name, iseq->self, type) + +#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \ + new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym) + +/* add instructions */ +#define ADD_SEQ(seq1, seq2) \ + APPEND_LIST(seq1, seq2) + +/* add an instruction */ +#define ADD_INSN(seq, line, insn) \ + ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, BIN(insn), 0)) + +/* add an instruction with label operand */ +#define ADD_INSNL(seq, line, insn, label) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 1, (VALUE)label)) + +/* add an instruction with some operands (1, 2, 3, 5) */ +#define ADD_INSN1(seq, line, insn, op1) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 1, (VALUE)op1)) + +#define ADD_INSN2(seq, line, insn, op1, op2) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 2, (VALUE)op1, (VALUE)op2)) + +#define ADD_INSN3(seq, line, insn, op1, op2, op3) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 3, (VALUE)op1, (VALUE)op2, (VALUE)op3)) + +/* Specific Insn factory */ +#define ADD_SEND(seq, line, id, argc) \ + ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(0)) + +#define ADD_CALL_RECEIVER(seq, line) \ + ADD_INSN(seq, line, putnil) + +#define ADD_CALL(seq, line, id, argc) \ + ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL_BIT)) + +#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \ + ADD_SEND_R(seq, line, id, argc, block, (VALUE)INT2FIX(VM_CALL_FCALL_BIT)) + +#define ADD_SEND_R(seq, line, id, argc, block, flag) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_send(iseq, line, \ + (VALUE)id, (VALUE)argc, (VALUE)block, (VALUE)flag)) + +#define ADD_TRACE(seq, line, event) \ + do { \ + if ((event) == RUBY_EVENT_LINE && iseq->coverage && \ + RARRAY_PTR(iseq->coverage)[(line) - 1] == Qnil) { \ + RARRAY_PTR(iseq->coverage)[(line) - 1] = INT2FIX(0); \ + ADD_INSN1(seq, line, trace, INT2FIX(RUBY_EVENT_COVERAGE)); \ + } \ + if (iseq->compile_data->option->trace_instruction) { \ + ADD_INSN1(seq, line, trace, INT2FIX(event)); \ + } \ + }while(0); + +/* add label */ +#define ADD_LABEL(seq, label) \ + ADD_ELEM(seq, (LINK_ELEMENT *) label) + +#define ADD_ADJUST(seq, line, label) \ + ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, line)) + +#define ADD_ADJUST_RESTORE(seq, label) \ + ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, -1)) + +#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \ + (rb_ary_push(iseq->compile_data->catch_table_ary, \ + rb_ary_new3(5, type, \ + (VALUE)(ls) | 1, (VALUE)(le) | 1, \ + iseqv, (VALUE)(lc) | 1))) + +/* compile node */ +#define COMPILE(anchor, desc, node) \ + (debug_compile("== " desc "\n", \ + iseq_compile_each(iseq, anchor, node, 0))) + +/* compile node, this node's value will be poped */ +#define COMPILE_POPED(anchor, desc, node) \ + (debug_compile("== " desc "\n", \ + iseq_compile_each(iseq, anchor, node, 1))) + +/* compile node, which is poped when 'poped' is true */ +#define COMPILE_(anchor, desc, node, poped) \ + (debug_compile("== " desc "\n", \ + iseq_compile_each(iseq, anchor, node, poped))) + +#define OPERAND_AT(insn, idx) \ + (((INSN*)(insn))->operands[idx]) + +#define INSN_OF(insn) \ + (((INSN*)(insn))->insn_id) + +/* error */ +#define COMPILE_ERROR(strs) \ +{ \ + VALUE tmp = GET_THREAD()->errinfo; \ + if (compile_debug) rb_compile_bug strs; \ + GET_THREAD()->errinfo = iseq->compile_data->err_info; \ + rb_compile_error strs; \ + iseq->compile_data->err_info = GET_THREAD()->errinfo; \ + GET_THREAD()->errinfo = tmp; \ + ret = 0; \ + break; \ +} + +#define ERROR_ARGS ruby_sourcefile, nd_line(node), + + +#define COMPILE_OK 1 +#define COMPILE_NG 0 + + +/* leave name uninitialized so that compiler warn if INIT_ANCHOR is + * missing */ +#define DECL_ANCHOR(name) \ + LINK_ANCHOR *name, name##_body__ = {{0,},} +#define INIT_ANCHOR(name) \ + (name##_body__.last = &name##_body__.anchor, name = &name##_body__) + + #include "optinsn.inc" #if OPT_INSTRUCTIONS_UNIFICATION #include "optunifs.inc" @@ -5051,3 +5266,55 @@ iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, iseq_build_body(iseq, anchor, body, labels_table); return iseq->self; } + +/* for parser */ + +int +rb_dvar_defined(ID id) +{ + rb_thread_t *th = GET_THREAD(); + rb_iseq_t *iseq; + if (th->base_block && (iseq = th->base_block->iseq)) { + while (iseq->type == ISEQ_TYPE_BLOCK || + iseq->type == ISEQ_TYPE_RESCUE || + iseq->type == ISEQ_TYPE_ENSURE || + iseq->type == ISEQ_TYPE_EVAL) { + int i; + + for (i = 0; i < iseq->local_table_size; i++) { + if (iseq->local_table[i] == id) { + return 1; + } + } + iseq = iseq->parent_iseq; + } + } + return 0; +} + +int +rb_local_defined(ID id) +{ + rb_thread_t *th = GET_THREAD(); + rb_iseq_t *iseq; + + if (th->base_block && th->base_block->iseq) { + int i; + iseq = th->base_block->iseq->local_iseq; + + for (i=0; ilocal_table_size; i++) { + if (iseq->local_table[i] == id) { + return 1; + } + } + } + return 0; +} + +int +rb_parse_in_eval(void) +{ + return GET_THREAD()->parse_in_eval != 0; +} + + -- cgit v1.2.3