[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 *> ¶ms);
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