[macruby-changes] [3906] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sat Apr 3 23:07:57 PDT 2010


Revision: 3906
          http://trac.macosforge.org/projects/ruby/changeset/3906
Author:   lsansonetti at apple.com
Date:     2010-04-03 23:07:54 -0700 (Sat, 03 Apr 2010)
Log Message:
-----------
fixed ZSUPER compilation inside blocks

Modified Paths:
--------------
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2010-04-04 04:11:15 UTC (rev 3905)
+++ MacRuby/trunk/compiler.cpp	2010-04-04 06:07:54 UTC (rev 3906)
@@ -61,6 +61,7 @@
     current_block_chain = false;
     current_block_node = NULL;
     current_block_func = NULL;
+    current_non_block_func = NULL;
     current_opened_class = NULL;
     dynamic_class = false;
     current_module = false;
@@ -3043,360 +3044,370 @@
     BranchInst::Create(mergeBB, bb);
 }
 
-Value *
-RoxorCompiler::compile_node(NODE *node)
+Function *
+RoxorCompiler::compile_scope(NODE *node)
 {
+    rb_vm_arity_t arity = rb_vm_node_arity(node);
+    const int nargs = bb == NULL ? 0 : arity.real;
+    const bool has_dvars = block_declaration;
+
+    // Get dynamic vars.
+    if (has_dvars && node->nd_tbl != NULL) {
+	const int args_count = (int)node->nd_tbl[0];
+	const int lvar_count = (int)node->nd_tbl[args_count + 1];
+	for (int i = 0; i < lvar_count; i++) {
+	    ID id = node->nd_tbl[i + args_count + 2];
+	    if (lvars.find(id) != lvars.end()) {
+		std::vector<ID>::iterator iter = std::find(dvars.begin(),
+			dvars.end(), id);
+		if (iter == dvars.end()) {
 #if ROXOR_COMPILER_DEBUG
-    printf("%s:%ld ", fname, nd_line(node));
-    for (int i = 0; i < level; i++) {
-	printf("...");
-    }
-    printf("... %s\n", ruby_node_name(nd_type(node)));
+		    printf("dvar %s\n", rb_id2name(id));
 #endif
-    if (current_line != nd_line(node)) {
-	current_line = nd_line(node);
-	if (debug_mode) {
-	    compile_debug_trap();
+		    dvars.push_back(id);
+		}
+	    }
 	}
     }
 
-    switch (nd_type(node)) {
-	case NODE_SCOPE:
-	    {
-		rb_vm_arity_t arity = rb_vm_node_arity(node);
-		const int nargs = bb == NULL ? 0 : arity.real;
-		const bool has_dvars = block_declaration;
+    // Create function type.
+    std::vector<const Type *> types;
+    types.push_back(RubyObjTy);	// self
+    types.push_back(PtrTy);	// sel
+    if (has_dvars) {
+	types.push_back(RubyObjPtrPtrTy); // dvars array
+	types.push_back(PtrTy); // rb_vm_block_t of the currently running block
+    }
+    for (int i = 0; i < nargs; ++i) {
+	types.push_back(RubyObjTy);
+    }
+    FunctionType *ft = FunctionType::get(RubyObjTy, types, false);
 
-		// Get dynamic vars.
-		if (has_dvars && node->nd_tbl != NULL) {
-		    const int args_count = (int)node->nd_tbl[0];
-		    const int lvar_count = (int)node->nd_tbl[args_count + 1];
-		    for (int i = 0; i < lvar_count; i++) {
-			ID id = node->nd_tbl[i + args_count + 2];
-			if (lvars.find(id) != lvars.end()) {
-			    std::vector<ID>::iterator iter = std::find(dvars.begin(), dvars.end(), id);
-			    if (iter == dvars.end()) {
-#if ROXOR_COMPILER_DEBUG
-				printf("dvar %s\n", rb_id2name(id));
-#endif
-				dvars.push_back(id);
-			    }
-			}
-		    }
-		}
+    std::string function_name;
+    if (ruby_aot_compile) {
+	function_name.append(RSTRING_PTR(ruby_aot_init_func));
+	function_name.append("_ruby_scope");
+    }
+    else {
+	function_name.append("__ruby_scope");
+    }
 
-		// Create function type.
-		std::vector<const Type *> types;
-		types.push_back(RubyObjTy);	// self
-		types.push_back(PtrTy);		// sel
-		if (has_dvars) {
-		    types.push_back(RubyObjPtrPtrTy); // dvars array
-		    types.push_back(PtrTy); // rb_vm_block_t of the currently running block
-		}
-		for (int i = 0; i < nargs; ++i) {
-		    types.push_back(RubyObjTy);
-		}
-		FunctionType *ft = FunctionType::get(RubyObjTy, types, false);
+    Function *f = Function::Create(ft, GlobalValue::ExternalLinkage,
+	    function_name, module);
 
-		std::string function_name;
- 		if (ruby_aot_compile) {
-		    function_name.append(RSTRING_PTR(ruby_aot_init_func));
-		    function_name.append("_ruby_scope");
- 		}
- 		else {
-		    function_name.append("__ruby_scope");
- 		}
+    BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
+    BasicBlock *old_rescue_rethrow_bb = rescue_rethrow_bb;
+    BasicBlock *old_entry_bb = entry_bb;
+    BasicBlock *old_bb = bb;
+    BasicBlock *new_rescue_invoke_bb = NULL;
+    BasicBlock *new_rescue_rethrow_bb = NULL;
+    rescue_invoke_bb = NULL;
+    rescue_rethrow_bb = NULL;
+    bb = BasicBlock::Create(context, "MainBlock", f);
 
-		Function *f = Function::Create(ft, GlobalValue::ExternalLinkage,
-			function_name, module);
-
-		BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
-		BasicBlock *old_rescue_rethrow_bb = rescue_rethrow_bb;
-		BasicBlock *old_entry_bb = entry_bb;
-		BasicBlock *old_bb = bb;
-		BasicBlock *new_rescue_invoke_bb = NULL;
-		BasicBlock *new_rescue_rethrow_bb = NULL;
-		rescue_invoke_bb = NULL;
-		rescue_rethrow_bb = NULL;
-		bb = BasicBlock::Create(context, "MainBlock", f);
-
-		DISubprogram old_debug_subprogram = debug_subprogram;
+    DISubprogram old_debug_subprogram = debug_subprogram;
 #if 0
-		// This is not the right way to emit subprogram DWARF entries,
-		// llc emits some assembly that doesn't compile because some
-		// symbols are duplicated.
-		debug_subprogram = debug_info->CreateSubprogram(
-			debug_compile_unit, f->getName(), f->getName(),
-			f->getName(), debug_compile_unit, nd_line(node),
-			DIType(), f->hasInternalLinkage(), true);
-		debug_info->InsertSubprogramStart(debug_subprogram, bb);
+    // This is not the right way to emit subprogram DWARF entries,
+    // llc emits some assembly that doesn't compile because some
+    // symbols are duplicated.
+    debug_subprogram = debug_info->CreateSubprogram(
+	    debug_compile_unit, f->getName(), f->getName(),
+	    f->getName(), debug_compile_unit, nd_line(node),
+	    DIType(), f->hasInternalLinkage(), true);
+    debug_info->InsertSubprogramStart(debug_subprogram, bb);
 #endif
 
-		std::map<ID, Value *> old_lvars = lvars;
-		lvars.clear();
-		Value *old_self = current_self;
+    std::map<ID, Value *> old_lvars = lvars;
+    lvars.clear();
+    Value *old_self = current_self;
 
-		Function::arg_iterator arg;
+    Function::arg_iterator arg;
 
-		arg = f->arg_begin();
-		Value *self = arg++;
-		self->setName("self");
-		current_self = self;
+    arg = f->arg_begin();
+    Value *self = arg++;
+    self->setName("self");
+    current_self = self;
 
-		Value *sel = arg++;
-		sel->setName("sel");
+    Value *sel = arg++;
+    sel->setName("sel");
 
-		Value *old_running_block = running_block;
-		Value *old_current_var_uses = current_var_uses;
-		current_var_uses = NULL;
+    Value *old_running_block = running_block;
+    Value *old_current_var_uses = current_var_uses;
+    current_var_uses = NULL;
 
-		if (has_dvars) {
-		    Value *dvars_arg = arg++;
-		    dvars_arg->setName("dvars");
-		    running_block = arg++;
-		    running_block->setName("running_block");
-		}
-		else {
-		    running_block = NULL;
-		}
+    if (has_dvars) {
+	Value *dvars_arg = arg++;
+	dvars_arg->setName("dvars");
+	running_block = arg++;
+	running_block->setName("running_block");
+    }
+    else {
+	running_block = NULL;
+    }
 
-		current_block_arg = NULL;
-		if (node->nd_tbl != NULL) {
-		    bool has_vars_to_save = false;
-		    int i, args_count = (int)node->nd_tbl[0];
-		    assert(args_count == nargs
-			    || args_count == nargs + 1 /* optional block */
-			    || args_count == nargs - 1 /* unnamed param (|x,|) */);
-		    for (i = 0; i < args_count; i++) {
-			ID id = node->nd_tbl[i + 1];
+    current_block_arg = NULL;
+    if (node->nd_tbl != NULL) {
+	bool has_vars_to_save = false;
+	int i, args_count = (int)node->nd_tbl[0];
+	assert(args_count == nargs
+		|| args_count == nargs + 1 /* optional block */
+		|| args_count == nargs - 1 /* unnamed param (|x,|) */);
+	for (i = 0; i < args_count; i++) {
+	    ID id = node->nd_tbl[i + 1];
 #if ROXOR_COMPILER_DEBUG
-			printf("arg %s\n", rb_id2name(id));
+	    printf("arg %s\n", rb_id2name(id));
 #endif
 
-			Value *val = NULL;
-			if (i < nargs) {
-			    val = arg++;
-			    val->setName(rb_id2name(id));
-			}
-			else {
-			    // Optional block.
-			    if (currentBlockObjectFunc == NULL) {
-				// VALUE rb_vm_current_block_object(void);
-				currentBlockObjectFunc = cast<Function>(
-					module->getOrInsertFunction("rb_vm_current_block_object", 
-					    RubyObjTy, NULL));
-			    }
-			    val = CallInst::Create(currentBlockObjectFunc, "", bb);
-			    current_block_arg = val;
-			}
-			Value *slot = new AllocaInst(RubyObjTy, "", bb);
-			new StoreInst(val, slot, bb);
-			lvars[id] = slot;
-			has_vars_to_save = true;
-		    }
+	    Value *val = NULL;
+	    if (i < nargs) {
+		val = arg++;
+		val->setName(rb_id2name(id));
+	    }
+	    else {
+		// Optional block.
+		if (currentBlockObjectFunc == NULL) {
+		    // VALUE rb_vm_current_block_object(void);
+		    currentBlockObjectFunc = cast<Function>(
+			    module->getOrInsertFunction(
+				"rb_vm_current_block_object", RubyObjTy, NULL));
+		}
+		val = CallInst::Create(currentBlockObjectFunc, "", bb);
+		current_block_arg = val;
+	    }
+	    Value *slot = new AllocaInst(RubyObjTy, "", bb);
+	    new StoreInst(val, slot, bb);
+	    lvars[id] = slot;
+	    has_vars_to_save = true;
+	}
 
-		    // local vars must be created before the optional arguments
-		    // because they can be used in them, for instance with def f(a=b=c=1)
-		    if (compile_lvars(&node->nd_tbl[args_count + 1])) {
-			has_vars_to_save = true;
-		    }
+	// Local vars must be created before the optional arguments
+	// because they can be used in them, for instance with def f(a=b=c=1).
+	if (compile_lvars(&node->nd_tbl[args_count + 1])) {
+	    has_vars_to_save = true;
+	}
 
-		    if (has_vars_to_save) {
-			current_var_uses = new AllocaInst(PtrTy, "", bb);
-			new StoreInst(compile_const_pointer(NULL),
-				current_var_uses, bb);
+	if (has_vars_to_save) {
+	    current_var_uses = new AllocaInst(PtrTy, "", bb);
+	    new StoreInst(compile_const_pointer(NULL),
+		    current_var_uses, bb);
 
-			new_rescue_invoke_bb = BasicBlock::Create(context,
-				"rescue_save_vars", f);
-			new_rescue_rethrow_bb = BasicBlock::Create(context,
-				"rescue_save_vars.rethrow", f);
-			rescue_invoke_bb = new_rescue_invoke_bb;
-			rescue_rethrow_bb = new_rescue_rethrow_bb;
-		    }
+	    new_rescue_invoke_bb = BasicBlock::Create(context,
+		    "rescue_save_vars", f);
+	    new_rescue_rethrow_bb = BasicBlock::Create(context,
+		    "rescue_save_vars.rethrow", f);
+	    rescue_invoke_bb = new_rescue_invoke_bb;
+	    rescue_rethrow_bb = new_rescue_rethrow_bb;
+	}
 
-		    NODE *args_node = node->nd_args;
-		    if (args_node != NULL) {
-			// compile multiple assignment arguments (def f((a, b, v)))
-			// (this must also be done after the creation of local variables)
-			NODE *rest_node = args_node->nd_next;
-			if (rest_node != NULL) {
-			    NODE *right_req_node = rest_node->nd_next;
-			    if (right_req_node != NULL) {
-				NODE *last_node = right_req_node->nd_next;
-				if (last_node != NULL) {
-				    assert(nd_type(last_node) == NODE_AND);
-				    // multiple assignment for the left-side required arguments
-				    if (last_node->nd_1st != NULL) {
-					compile_node(last_node->nd_1st);
-				    }
-				    // multiple assignment for the right-side required arguments
-				    if (last_node->nd_2nd != NULL) {
-					compile_node(last_node->nd_2nd);
-				    }
-				}
-			    }
+	NODE *args_node = node->nd_args;
+	if (args_node != NULL) {
+	    // Compile multiple assignment arguments (def f((a, b, v))).
+	    // This must also be done after the creation of local variables.
+	    NODE *rest_node = args_node->nd_next;
+	    if (rest_node != NULL) {
+		NODE *right_req_node = rest_node->nd_next;
+		if (right_req_node != NULL) {
+		    NODE *last_node = right_req_node->nd_next;
+		    if (last_node != NULL) {
+			assert(nd_type(last_node) == NODE_AND);
+			// Multiple assignment for the left-side required
+			// arguments.
+			if (last_node->nd_1st != NULL) {
+			    compile_node(last_node->nd_1st);
 			}
-
-			// Compile optional arguments.
-			Function::ArgumentListType::iterator iter = f->arg_begin();
-			++iter; // skip self
-			++iter; // skip sel
-			NODE *opt_node = args_node->nd_opt;
-			if (opt_node != NULL) {
-			    int to_skip = args_node->nd_frml;
-			    if (has_dvars) {
-				to_skip += 2; // dvars array and currently running block
-			    }
-			    for (i = 0; i < to_skip; i++) {
-				++iter; // skip dvars and args required on the left-side
-			    }
-			    iter = compile_optional_arguments(iter, opt_node);
+			// Multiple assignment for the right-side required
+			// arguments.
+			if (last_node->nd_2nd != NULL) {
+			    compile_node(last_node->nd_2nd);
 			}
 		    }
 		}
+	    }
 
-		Value *val = NULL;
-		if (node->nd_body != NULL) {
-		    entry_bb = BasicBlock::Create(context, "entry_point", f); 
-		    BranchInst::Create(entry_bb, bb);
-		    bb = entry_bb;
+	    // Compile optional arguments.
+	    Function::ArgumentListType::iterator iter = f->arg_begin();
+	    ++iter; // skip self
+	    ++iter; // skip sel
+	    NODE *opt_node = args_node->nd_opt;
+	    if (opt_node != NULL) {
+		int to_skip = args_node->nd_frml;
+		if (has_dvars) {
+		    to_skip += 2; // dvars array and currently running block
+		}
+		for (i = 0; i < to_skip; i++) {
+		    ++iter; // skip dvars and args required on the left-side
+		}
+		iter = compile_optional_arguments(iter, opt_node);
+	    }
+	}
+    }
 
-		    rb_vm_arity_t old_current_arity = current_arity;
-		    current_arity = arity;
+    Value *val = NULL;
+    if (node->nd_body != NULL) {
+	entry_bb = BasicBlock::Create(context, "entry_point", f); 
+	BranchInst::Create(entry_bb, bb);
+	bb = entry_bb;
 
-		    DEBUG_LEVEL_INC();
-		    val = compile_node(node->nd_body);
-		    DEBUG_LEVEL_DEC();
+	rb_vm_arity_t old_current_arity = current_arity;
+	Function *old_current_non_block_func = current_non_block_func;
+	if (!block_declaration) {
+	    current_non_block_func = f;
+	    current_arity = arity;
+	}
 
-		    current_arity = old_current_arity;
+	DEBUG_LEVEL_INC();
+	val = compile_node(node->nd_body);
+	DEBUG_LEVEL_DEC();
+
+	current_non_block_func = old_current_non_block_func;
+	current_arity = old_current_arity;
+    }
+    if (val == NULL) {
+	val = nilVal;
+    }
+
+    ReturnInst::Create(context, val, bb);
+
+    // The rethrows after the save of variables must be real rethrows.
+    rescue_rethrow_bb = NULL;
+    rescue_invoke_bb = NULL;
+
+    // Current_lvar_uses has 2 uses or more if it is really used.
+    // (there is always a StoreInst in which we assign it NULL)
+    if (current_var_uses != NULL && current_var_uses->hasNUsesOrMore(2)) {
+	// Searches all ReturnInst in the function we just created and add
+	// before a call to the function to save the local variables if
+	// necessary (we can't do this before finishing compiling the whole
+	// function because we can't be sure if the function contains a block
+	// or not before).
+	std::vector<ReturnInst *> to_fix;
+	for (Function::iterator block_it = f->begin();
+		block_it != f->end();
+		++block_it) {
+	    for (BasicBlock::iterator inst_it = block_it->begin();
+		    inst_it != block_it->end();
+		    ++inst_it) {
+		ReturnInst *inst = dyn_cast<ReturnInst>(inst_it);
+		if (inst != NULL) {
+		    to_fix.push_back(inst);
 		}
-		if (val == NULL) {
-		    val = nilVal;
-		}
+	    }
+	}
+	// We have to process the blocks in a second loop because
+	// we can't modify the blocks while iterating on them.
+	for (std::vector<ReturnInst *>::iterator inst_it = to_fix.begin();
+		inst_it != to_fix.end();
+		++inst_it) {
 
-		ReturnInst::Create(context, val, bb);
+	    ReturnInst *inst = *inst_it;
+	    BasicBlock *startBB = inst->getParent();
+	    BasicBlock *mergeBB = startBB->splitBasicBlock(inst, "merge");
+	    // We do not want the BranchInst added by splitBasicBlock.
+	    startBB->getInstList().pop_back();
+	    compile_keep_vars(startBB, mergeBB);
+	}
 
-		// the rethrows after the save of variables must be real rethrows
-		rescue_rethrow_bb = NULL;
-		rescue_invoke_bb = NULL;
+	if (new_rescue_invoke_bb->use_empty()
+		&& new_rescue_rethrow_bb->use_empty()) {
+	    new_rescue_invoke_bb->eraseFromParent();
+	    new_rescue_rethrow_bb->eraseFromParent();
+	}
+	else {
+	    if (new_rescue_invoke_bb->use_empty()) {
+		new_rescue_invoke_bb->eraseFromParent();
+	    }
+	    else {
+		bb = new_rescue_invoke_bb;
+		compile_landing_pad_header();
+		BranchInst::Create(new_rescue_rethrow_bb, bb);
+	    }
 
-		// current_lvar_uses has 2 uses or more if it is really used
-		// (there is always a StoreInst in which we assign it NULL)
-		if (current_var_uses != NULL && current_var_uses->hasNUsesOrMore(2)) {
-		    // searches all ReturnInst in the function we just created and add before
-		    // a call to the function to save the local variables if necessary
-		    // (we can't do this before finishing compiling the whole function
-		    // because we can't be sure if the function contains a block or not before)
-		    std::vector<ReturnInst *> to_fix;
-		    for (Function::iterator block_it = f->begin();
-			 block_it != f->end();
-			 ++block_it) {
-			for (BasicBlock::iterator inst_it = block_it->begin();
-			     inst_it != block_it->end();
-			     ++inst_it) {
-			    ReturnInst *inst = dyn_cast<ReturnInst>(inst_it);
-			    if (inst != NULL) {
-				to_fix.push_back(inst);
-			    }
-			}
-		    }
-		    // we have to process the blocks in a second loop because
-		    // we can't modify the blocks while iterating on them
-		    for (std::vector<ReturnInst *>::iterator inst_it = to_fix.begin();
-			 inst_it != to_fix.end();
-			 ++inst_it) {
+	    bb = new_rescue_rethrow_bb;
+	    BasicBlock *mergeBB = BasicBlock::Create(context,
+		    "merge", f);
+	    compile_keep_vars(bb, mergeBB);
 
-			ReturnInst *inst = *inst_it;
-			BasicBlock *startBB = inst->getParent();
-			BasicBlock *mergeBB = startBB->splitBasicBlock(inst, "merge");
-			// we do not want the BranchInst added by splitBasicBlock
-			startBB->getInstList().pop_back();
-			compile_keep_vars(startBB, mergeBB);
-		    }
+	    bb = mergeBB;
+	    compile_rethrow_exception();
+	}
+    }
+    else if (current_var_uses != NULL) {
+	for (BasicBlock::use_iterator rescue_use_it =
+		new_rescue_invoke_bb->use_begin();
+		rescue_use_it != new_rescue_invoke_bb->use_end();
+		rescue_use_it = new_rescue_invoke_bb->use_begin()) {
+	    InvokeInst* invoke = dyn_cast<InvokeInst>(rescue_use_it);
+	    assert(invoke != NULL);
 
-		    if (new_rescue_invoke_bb->use_empty() && new_rescue_rethrow_bb->use_empty()) {
-			new_rescue_invoke_bb->eraseFromParent();
-			new_rescue_rethrow_bb->eraseFromParent();
-		    }
-		    else {
-			if (new_rescue_invoke_bb->use_empty()) {
-			    new_rescue_invoke_bb->eraseFromParent();
-			}
-			else {
-			    bb = new_rescue_invoke_bb;
-			    compile_landing_pad_header();
-			    BranchInst::Create(new_rescue_rethrow_bb, bb);
-			}
+	    // Transform the InvokeInst in CallInst.
+	    std::vector<Value *> params;
+	    for (InvokeInst::op_iterator op_it = invoke->op_begin()+3;
+		    op_it != invoke->op_end(); ++op_it) {
+		params.push_back(op_it->get());
+	    }
+	    CallInst *call_inst = CallInst::Create(
+		    invoke->getOperand(0),
+		    params.begin(), params.end(),
+		    invoke->getNameStr(),
+		    invoke);
 
-			bb = new_rescue_rethrow_bb;
-			BasicBlock *mergeBB = BasicBlock::Create(context,
-				"merge", f);
-			compile_keep_vars(bb, mergeBB);
+	    invoke->replaceAllUsesWith(call_inst);
+	    BasicBlock *normal_bb = dyn_cast<BasicBlock>(invoke->getOperand(1));
+	    assert(normal_bb != NULL);
+	    BranchInst::Create(normal_bb, invoke);
+	    invoke->eraseFromParent();
+	}
+	new_rescue_invoke_bb->eraseFromParent();
 
-			bb = mergeBB;
-			compile_rethrow_exception();
-		    }
-		}
-		else if (current_var_uses != NULL) {
-		    for (BasicBlock::use_iterator rescue_use_it = new_rescue_invoke_bb->use_begin();
-			 rescue_use_it != new_rescue_invoke_bb->use_end();
-			 rescue_use_it = new_rescue_invoke_bb->use_begin()) {
-			InvokeInst* invoke = dyn_cast<InvokeInst>(rescue_use_it);
-			assert(invoke != NULL);
+	if (new_rescue_rethrow_bb->use_empty()) {
+	    new_rescue_rethrow_bb->eraseFromParent();
+	}
+	else {
+	    bb = new_rescue_rethrow_bb;
+	    compile_rethrow_exception();
+	}
+    }
 
-			// transform the InvokeInst in CallInst
-			std::vector<Value *> params;
-			for (InvokeInst::op_iterator op_it = invoke->op_begin()+3;
-			     op_it != invoke->op_end(); ++op_it) {
-			    params.push_back(op_it->get());
-			}
-			CallInst *call_inst = CallInst::Create(
-				invoke->getOperand(0),
-				params.begin(), params.end(),
-				invoke->getNameStr(),
-				invoke);
+    rescue_rethrow_bb = old_rescue_rethrow_bb;
+    rescue_invoke_bb = old_rescue_invoke_bb;
 
-			invoke->replaceAllUsesWith(call_inst);
-			BasicBlock *normal_bb = dyn_cast<BasicBlock>(invoke->getOperand(1));
-			assert(normal_bb != NULL);
-			BranchInst::Create(normal_bb, invoke);
-			invoke->eraseFromParent();
-		    }
-		    new_rescue_invoke_bb->eraseFromParent();
+    bb = old_bb;
+    entry_bb = old_entry_bb;
+    lvars = old_lvars;
+    current_self = old_self;
+    current_var_uses = old_current_var_uses;
+    running_block = old_running_block;
+    debug_subprogram = old_debug_subprogram;
 
-		    if (new_rescue_rethrow_bb->use_empty()) {
-			new_rescue_rethrow_bb->eraseFromParent();
-		    }
-		    else {
-			bb = new_rescue_rethrow_bb;
-			compile_rethrow_exception();
-		    }
-		}
+    return f;
+}
 
-		rescue_rethrow_bb = old_rescue_rethrow_bb;
-		rescue_invoke_bb = old_rescue_invoke_bb;
+Value *
+RoxorCompiler::compile_node(NODE *node)
+{
+#if ROXOR_COMPILER_DEBUG
+    printf("%s:%ld ", fname, nd_line(node));
+    for (int i = 0; i < level; i++) {
+	printf("...");
+    }
+    printf("... %s\n", ruby_node_name(nd_type(node)));
+#endif
+    if (current_line != nd_line(node)) {
+	current_line = nd_line(node);
+	if (debug_mode) {
+	    compile_debug_trap();
+	}
+    }
 
-		bb = old_bb;
-		entry_bb = old_entry_bb;
-		lvars = old_lvars;
-		current_self = old_self;
-		current_var_uses = old_current_var_uses;
-		running_block = old_running_block;
-		debug_subprogram = old_debug_subprogram;
+    switch (nd_type(node)) {
+	case NODE_SCOPE:
+	    return cast<Value>(compile_scope(node));
 
-		return cast<Value>(f);
-	    }
-	    break;
-
 	case NODE_DVAR:
 	case NODE_LVAR:
-	    {
-		assert(node->nd_vid > 0);
+	    assert(node->nd_vid > 0);
+	    return new LoadInst(compile_lvar_slot(node->nd_vid), "", bb);
 
-		return new LoadInst(compile_lvar_slot(node->nd_vid), "", bb);
-	    }
-	    break;
-
 	case NODE_GVAR:
 	    {
 		assert(node->nd_vid > 0);
@@ -3404,14 +3415,16 @@
 
 		if (gvarGetFunc == NULL) {
 		    // VALUE rb_gvar_get(struct global_entry *entry);
-		    gvarGetFunc = cast<Function>(module->getOrInsertFunction("rb_gvar_get", RubyObjTy, PtrTy, NULL));
+		    gvarGetFunc = cast<Function>(module->getOrInsertFunction(
+				"rb_gvar_get", RubyObjTy, PtrTy, NULL));
 		}
 
 		std::vector<Value *> params;
 
 		params.push_back(compile_global_entry(node));
 
-		return CallInst::Create(gvarGetFunc, params.begin(), params.end(), "", bb);
+		return CallInst::Create(gvarGetFunc, params.begin(),
+			params.end(), "", bb);
 	    }
 	    break;
 
@@ -4127,12 +4140,10 @@
 		bool positive_arity = false;
 		if (nd_type(node) == NODE_ZSUPER) {
 		    assert(args == NULL);
-		    int arity = bb->getParent()->getArgumentList().size();
-		    arity -= 2; // skip self and sel
-		    if (block_declaration) {
-			arity -= 2; // skip dvar and current_block
-		    }
-		    positive_arity = arity > 0;
+		    assert(current_non_block_func != NULL);
+		    positive_arity = 
+			current_non_block_func->getArgumentList().size()
+			    - 2 /* skip self and sel */ > 0;
 		}
 		else {
 		    NODE *n = args;
@@ -4276,19 +4287,12 @@
 		int argc = 0;
 		if (nd_type(node) == NODE_ZSUPER) {
 		    Function::ArgumentListType &fargs =
-			bb->getParent()->getArgumentList();
+			current_non_block_func->getArgumentList();
 		    const int fargs_arity = fargs.size() - 2;
-		    const int arity = block_declaration
-			? fargs_arity - 2 // skip dvars and current_block
-			: fargs_arity;
-		    params.push_back(ConstantInt::get(Int32Ty, arity));
+		    params.push_back(ConstantInt::get(Int32Ty, fargs_arity));
 		    Function::ArgumentListType::iterator iter = fargs.begin();
 		    iter++; // skip self
 		    iter++; // skip sel
-		    if (block_declaration) {
-			iter++; // skip dvars
-			iter++; // skip current_block
-		    }
 		    const int rest_pos = current_arity.max == -1
 			? (current_arity.left_req
 				+ (current_arity.real - current_arity.min - 1))
@@ -4302,7 +4306,20 @@
 			// We can't simply push the direct argument address
 			// because if may have a default value.
 			ID argid = rb_intern(iter->getName().data());
-			Value *argslot = compile_lvar_slot(argid);
+			Value *argslot;
+			if (block_declaration) {
+			    if (std::find(dvars.begin(), dvars.end(), argid)
+				    == dvars.end()) {
+				// Dvar does not exist yet, so we create it
+				// on demand!
+				dvars.push_back(argid);
+			    }
+			    argslot = compile_dvar_slot(argid);			
+			}
+			else {
+			    argslot = compile_lvar_slot(argid);
+			}
+
 			params.push_back(new LoadInst(argslot, "", bb));
 
 			++i;

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2010-04-04 04:11:15 UTC (rev 3905)
+++ MacRuby/trunk/compiler.h	2010-04-04 06:07:54 UTC (rev 3906)
@@ -113,6 +113,7 @@
 	bool current_rescue;
 	NODE *current_block_node;
 	Function *current_block_func;
+	Function *current_non_block_func;
 	GlobalVariable *current_opened_class;
 	bool dynamic_class;
 	bool current_module;
@@ -254,6 +255,7 @@
 	    return compile_const_pointer(ptr, PtrPtrTy);
 	}
 
+	Function *compile_scope(NODE *node);
 	Instruction *compile_protected_call(Value *imp,
 		std::vector<Value *> &params);
 	void compile_dispatch_arguments(NODE *args,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100403/03ad0d57/attachment-0001.html>


More information about the macruby-changes mailing list