[macruby-changes] [1314] MacRuby/branches/experimental/roxor.cpp

source_changes at macosforge.org source_changes at macosforge.org
Fri Apr 3 18:27:24 PDT 2009


Revision: 1314
          http://trac.macosforge.org/projects/ruby/changeset/1314
Author:   lsansonetti at apple.com
Date:     2009-04-03 18:27:24 -0700 (Fri, 03 Apr 2009)
Log Message:
-----------
fixed return in a begin/ensure block + did a small refactoring of compile_jump()

Modified Paths:
--------------
    MacRuby/branches/experimental/roxor.cpp

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-04 00:14:38 UTC (rev 1313)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-04 01:27:24 UTC (rev 1314)
@@ -191,6 +191,7 @@
 	bool current_block;
 	BasicBlock *begin_bb;
 	BasicBlock *rescue_bb;
+	BasicBlock *ensure_bb;
 	NODE *current_block_node;
 	Function *current_block_func;
 	jmp_buf *return_from_block_jmpbuf;
@@ -239,7 +240,7 @@
 	Function *breakFunc;
 	Function *longjmpFunc;
 	Function *setjmpFunc;
-	Function *brokenWithFunc;
+	Function *popBrokenValue;
 
 	Constant *zeroVal;
 	Constant *oneVal;
@@ -293,9 +294,9 @@
 	Value *compile_defined_expression(NODE *node);
 	Value *compile_dstr(NODE *node);
 	Value *compile_dvar_slot(ID name);
+	void compile_break_val(Value *val);
 	Value *compile_jump(NODE *node);
 
-	void compile_dead_branch(void);
 	void compile_landing_pad_header(void);
 	void compile_landing_pad_footer(void);
 	void compile_rethrow_exception(void);
@@ -542,6 +543,7 @@
     entry_bb = NULL;
     begin_bb = NULL;
     rescue_bb = NULL;
+    ensure_bb = NULL;
     current_mid = 0;
     current_instance_method = false;
     self_id = rb_intern("self");
@@ -595,7 +597,7 @@
     breakFunc = NULL;
     longjmpFunc = NULL;
     setjmpFunc = NULL;
-    brokenWithFunc = NULL;
+    popBrokenValue = NULL;
 
 #if __LP64__
     RubyObjTy = IntTy = Type::Int64Ty;
@@ -1381,74 +1383,88 @@
     return new LoadInst(slot, "", bb);
 }
 
+void
+RoxorCompiler::compile_break_val(Value *val)
+{
+    if (breakFunc == NULL) {
+	// void rb_vm_break(VALUE val);
+	breakFunc = cast<Function>(
+		module->getOrInsertFunction("rb_vm_break", 
+		    Type::VoidTy, RubyObjTy, NULL));
+    }
+    std::vector<Value *> params;
+    params.push_back(val);
+    CallInst::Create(breakFunc, params.begin(),
+	    params.end(), "", bb);
+}
+
 Value *
 RoxorCompiler::compile_jump(NODE *node)
 {
-    if (nd_type(node) == NODE_RETRY) {
-	// Simply jump to the nearest begin label.
-	if (begin_bb == NULL) {
-	    rb_raise(rb_eSyntaxError, "unexpected retry");
-	}
-	// TODO raise a SyntaxError if called outside of a "rescue"
-	// block.
-	BranchInst::Create(begin_bb, bb);
-	compile_dead_branch();
-	return nilVal;
-    }
-
     const bool within_loop = current_loop_begin_bb != NULL
 	&& current_loop_body_bb != NULL
 	&& current_loop_end_bb != NULL;
 
-    // These cases should never happen.
-    if (!current_block && !within_loop) {
-	if (nd_type(node) == NODE_BREAK) {
-	    rb_raise(rb_eLocalJumpError, "unexpected break");
-	}
-	if (nd_type(node) == NODE_NEXT) {
-	    rb_raise(rb_eLocalJumpError, "unexpected next");
-	}
-	if (nd_type(node) == NODE_REDO) {
-	    rb_raise(rb_eLocalJumpError, "unexpected redo");
-	}
-    }
+    const bool within_block = current_block && current_mid == 0;
 
-    // The return value of the jump.
-    Value *val = node->nd_head != NULL
-	? compile_node(node->nd_head) : nilVal;
+    Value *val = nd_type(node) == NODE_RETRY
+	? nilVal
+	: node->nd_head != NULL
+	    ? compile_node(node->nd_head) : nilVal;
 
-    if (within_loop) {
-	// Simple branching.
-	if (nd_type(node) == NODE_BREAK) {
-	    current_loop_exit_val = val;
-	    BranchInst::Create(current_loop_end_bb, bb);
-	}
-	else if (nd_type(node) == NODE_NEXT) {
-	    BranchInst::Create(current_loop_begin_bb, bb);
-	}
-	else if (nd_type(node) == NODE_REDO) {
-	    BranchInst::Create(current_loop_body_bb, bb);
-	}
-	else {
-	    ReturnInst::Create(val, bb);
-	}
-    }
-    else {
-	if (nd_type(node) == NODE_BREAK
-	    || (current_block && current_mid == 0
-		&& nd_type(node) == NODE_RETURN)) {
-	    // First let's save the return value in the VM.
-	    if (breakFunc == NULL) {
-		// void rb_vm_break(VALUE val);
-		breakFunc = cast<Function>(
-			module->getOrInsertFunction("rb_vm_break", 
-			    Type::VoidTy, RubyObjTy, NULL));
+    switch (nd_type(node)) {
+	case NODE_RETRY:
+	    // Simply jump to the nearest begin label.
+	    if (begin_bb == NULL) {
+		rb_raise(rb_eSyntaxError, "unexpected retry");
 	    }
-	    std::vector<Value *> params;
-	    params.push_back(val);
-	    CallInst::Create(breakFunc, params.begin(),
-		    params.end(), "", bb);
-	    if (nd_type(node) == NODE_RETURN) {
+	    // TODO raise a SyntaxError if called outside of a "rescue"
+	    // block.
+	    BranchInst::Create(begin_bb, bb);
+	    break;
+
+	case NODE_BREAK:
+	    if (within_loop) {
+		current_loop_exit_val = val;
+		BranchInst::Create(current_loop_end_bb, bb);
+	    }
+	    else if (within_block) {
+		compile_break_val(val);
+		ReturnInst::Create(val, bb);
+	    }
+	    else {
+		rb_raise(rb_eLocalJumpError, "unexpected break");
+	    }
+	    break;
+
+	case NODE_NEXT:
+	    if (within_loop) {
+		BranchInst::Create(current_loop_begin_bb, bb);
+	    }
+	    else if (within_block) {
+		ReturnInst::Create(val, bb);
+	    }
+	    else {
+		rb_raise(rb_eLocalJumpError, "unexpected next");
+	    }
+	    break;
+
+	case NODE_REDO:
+	    if (within_loop) {
+		BranchInst::Create(current_loop_body_bb, bb);
+	    }
+	    else if (within_block) {
+		assert(entry_bb != NULL);
+		BranchInst::Create(entry_bb, bb);
+	    }
+	    else {
+		rb_raise(rb_eLocalJumpError, "unexpected redo");
+	    }
+	    break;
+
+	case NODE_RETURN:
+	   if (within_block) {
+		compile_break_val(val);
 		// Return-from-block is implemented using a setjmp() call.
 		if (longjmpFunc == NULL) {
 		    // void longjmp(jmp_buf, int);
@@ -1456,7 +1472,7 @@
 			module->getOrInsertFunction("longjmp", 
 			    Type::VoidTy, PtrTy, Type::Int32Ty, NULL));
 		}
-		params.clear();
+		std::vector<Value *> params;
 		if (return_from_block_jmpbuf == NULL) {
 		    return_from_block_jmpbuf = 
 			(jmp_buf *)malloc(sizeof(jmp_buf));
@@ -1468,18 +1484,24 @@
 		params.push_back(ConstantInt::get(Type::Int32Ty, 1));
 		CallInst::Create(longjmpFunc, params.begin(), params.end(), "",
 				 bb);
-	    }
-	    ReturnInst::Create(val, bb);
-	}
-	else if (nd_type(node) == NODE_REDO) {
-	    assert(entry_bb != NULL);
-	    BranchInst::Create(entry_bb, bb);
-	}
-	else {
-	    ReturnInst::Create(val, bb);
-	}
+		ReturnInst::Create(val, bb);
+	   }
+	   else {
+	       if (ensure_bb != NULL) {
+		   BranchInst::Create(ensure_bb, bb);
+	       }
+	       else {
+		   ReturnInst::Create(val, bb);
+	       }
+	   }
+	   break;
     }
-    compile_dead_branch();
+
+    // To not complicate the compiler even more, let's be very lazy here and
+    // continue on a dead branch. Hopefully LLVM is smart enough to eliminate
+    // it at compilation time.
+    bb = BasicBlock::Create("DEAD", bb->getParent());
+
     return val;
 }
 
@@ -1499,15 +1521,6 @@
 }
 
 void
-RoxorCompiler::compile_dead_branch(void)
-{
-    // To not complicate the compiler even more, let's be very lazy here and
-    // continue on a dead branch. Hopefully LLVM is smart enough to eliminate
-    // it at compilation time.
-    bb = BasicBlock::Create("DEAD", bb->getParent());
-}
-
-void
 RoxorCompiler::compile_landing_pad_header(void)
 {
     Function *eh_exception_f = Intrinsic::getDeclaration(module,
@@ -4116,7 +4129,8 @@
 		assert(node->nd_ensr != NULL);
 
 		Function *f = bb->getParent();
-		BasicBlock *ensure_bb = BasicBlock::Create("ensure", f);
+		BasicBlock *old_ensure_bb = ensure_bb;
+		ensure_bb = BasicBlock::Create("ensure", f);
 		Value *val;
 
 		if (nd_type(node->nd_head) != NODE_RESCUE) {
@@ -4139,19 +4153,17 @@
 		    compile_node(node->nd_ensr);
 		    compile_rethrow_exception();
 		    //compile_landing_pad_footer();
-
-		    bb = ensure_bb;
-		    compile_node(node->nd_ensr);
 		}
 		else {
 		    val = compile_node(node->nd_head);
 		    BranchInst::Create(ensure_bb, bb);
-
-		    bb = ensure_bb;
-		    compile_node(node->nd_ensr);
 		}
 
-		return val;//nilVal;
+		bb = ensure_bb;
+		ensure_bb = old_ensure_bb;
+		compile_node(node->nd_ensr);
+
+		return val;
 	    }
 	    break;
 
@@ -4263,16 +4275,15 @@
 		    BranchInst::Create(ret_bb, no_ret_bb, need_ret, bb);
 		
 		    bb = ret_bb;
-		    if (brokenWithFunc == NULL) {
+		    if (popBrokenValue == NULL) {
 			// VALUE rb_vm_pop_broken_value(void);
-			brokenWithFunc = cast<Function>(
+			popBrokenValue = cast<Function>(
 				module->getOrInsertFunction(
 				    "rb_vm_pop_broken_value", 
 				    RubyObjTy, NULL));
 		    }
 		    params.clear();
-		    Value *val = CallInst::Create(brokenWithFunc,
-			    params.begin(), params.end(), "", bb);
+		    Value *val = compile_protected_call(popBrokenValue, params);
 		    ReturnInst::Create(val, bb);	
 
 		    bb = no_ret_bb;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090403/8fdaf706/attachment.html>


More information about the macruby-changes mailing list