[macruby-changes] [1142] MacRuby/branches/experimental/roxor.cpp
source_changes at macosforge.org
source_changes at macosforge.org
Tue Mar 24 19:35:35 PDT 2009
Revision: 1142
http://trac.macosforge.org/projects/ruby/changeset/1142
Author: lsansonetti at apple.com
Date: 2009-03-24 19:35:34 -0700 (Tue, 24 Mar 2009)
Log Message:
-----------
fixed bugs in defined?
Modified Paths:
--------------
MacRuby/branches/experimental/roxor.cpp
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-03-24 21:49:37 UTC (rev 1141)
+++ MacRuby/branches/experimental/roxor.cpp 2009-03-25 02:35:34 UTC (rev 1142)
@@ -234,14 +234,6 @@
Function *getSpecialFunc;
Function *breakFunc;
- VALUE defined_nil;
- VALUE defined_self;
- VALUE defined_true;
- VALUE defined_false;
- VALUE defined_expression;
- VALUE defined_lvar;
- VALUE defined_assignment;
-
Constant *zeroVal;
Constant *oneVal;
Constant *twoVal;
@@ -291,6 +283,8 @@
Value *compile_defined_expression(NODE *node);
Value *compile_dstr(NODE *node);
void compile_dead_branch(void);
+ void compile_landing_pad_header(void);
+ void compile_landing_pad_footer(void);
Value *get_var(ID name, std::map<ID, Value *> &container,
bool do_assert) {
@@ -514,14 +508,6 @@
current_loop_end_bb = NULL;
current_loop_exit_val = NULL;
- defined_nil = 0;
- defined_self = 0;
- defined_true = 0;
- defined_false = 0;
- defined_expression = 0;
- defined_lvar = 0;
- defined_assignment = 0;
-
dispatcherFunc = NULL;
fastEqqFunc = NULL;
whenSplatFunc = NULL;
@@ -1041,65 +1027,41 @@
#define DEFINED_GVAR 2
#define DEFINED_CVAR 3
#define DEFINED_CONST 4
+#define DEFINED_SUPER 5
+#define DEFINED_METHOD 6
Value *
RoxorCompiler::compile_defined_expression(NODE *node)
{
+ // Easy cases first.
VALUE str = 0;
- int defined_mode = -1;
- VALUE defined_what = 0;
-
switch (nd_type(node)) {
case NODE_NIL:
- if (defined_nil == 0) {
- defined_nil = rb_str_new2("nil");
- rb_objc_retain((void *)defined_nil);
- }
- str = defined_nil;
+ str = (VALUE)CFSTR("nil");
break;
case NODE_SELF:
- if (defined_self == 0) {
- defined_self = rb_str_new2("self");
- rb_objc_retain((void *)defined_self);
- }
- str = defined_self;
+ str = (VALUE)CFSTR("self");
break;
case NODE_TRUE:
- if (defined_true == 0) {
- defined_true = rb_str_new2("true");
- rb_objc_retain((void *)defined_true);
- }
- str = defined_true;
+ str = (VALUE)CFSTR("true");
break;
case NODE_FALSE:
- if (defined_false == 0) {
- defined_false = rb_str_new2("false");
- rb_objc_retain((void *)defined_false);
- }
- str = defined_false;
+ str = (VALUE)CFSTR("false");
break;
case NODE_ARRAY:
+ case NODE_ZARRAY:
case NODE_STR:
case NODE_LIT:
- case NODE_ZARRAY:
- if (defined_expression == 0) {
- defined_expression = rb_str_new2("expression");
- rb_objc_retain((void *)defined_expression);
- }
- str = defined_expression;
+ str = (VALUE)CFSTR("expression");
break;
case NODE_LVAR:
case NODE_DVAR:
- if (defined_lvar == 0) {
- defined_lvar = rb_str_new2("local-variable");
- rb_objc_retain((void *)defined_lvar);
- }
- str = defined_lvar;
+ str = (VALUE)CFSTR("local-variable");
break;
case NODE_OP_ASGN1:
@@ -1115,61 +1077,120 @@
case NODE_CDECL:
case NODE_CVDECL:
case NODE_CVASGN:
- if (defined_assignment == 0) {
- defined_assignment = rb_str_new2("assignment");
- rb_objc_retain((void *)defined_assignment);
- }
- str = defined_assignment;
+ str = (VALUE)CFSTR("assignment");
break;
+ }
+ if (str != 0) {
+ return ConstantInt::get(RubyObjTy, (long)str);
+ }
+ // Now the less easy ones... let's set up an exception handler first
+ // because we might need to evalute things that will result in an
+ // exception.
+ Function *f = bb->getParent();
+ BasicBlock *old_rescue_bb = rescue_bb;
+ BasicBlock *new_rescue_bb = BasicBlock::Create("rescue", f);
+ BasicBlock *merge_bb = BasicBlock::Create("merge", f);
+ rescue_bb = new_rescue_bb;
+
+ // Prepare arguments for the runtime.
+ Value *self = current_self;
+ VALUE what1 = 0;
+ Value *what2 = NULL;
+ int type = 0;
+
+ switch (nd_type(node)) {
case NODE_IVAR:
- defined_mode = DEFINED_IVAR;
- defined_what = (VALUE)node->nd_vid;
+ type = DEFINED_IVAR;
+ what1 = (VALUE)node->nd_vid;
break;
case NODE_GVAR:
- defined_mode = DEFINED_GVAR;
- defined_what = (VALUE)node->nd_entry;
+ type = DEFINED_GVAR;
+ what1 = (VALUE)node->nd_entry;
break;
case NODE_CVAR:
- defined_mode = DEFINED_CVAR;
- defined_what = (VALUE)node->nd_vid;
+ type = DEFINED_CVAR;
+ what1 = (VALUE)node->nd_vid;
break;
case NODE_CONST:
- defined_mode = DEFINED_CONST;
- defined_what = (VALUE)node->nd_vid;
+ type = DEFINED_CONST;
+ what1 = (VALUE)node->nd_vid;
break;
- default:
- compile_node_error("unimplemented defined? argument", node);
+ case NODE_SUPER:
+ case NODE_ZSUPER:
+ type = DEFINED_SUPER;
+ what1 = (VALUE)current_mid;
+ break;
+
+ case NODE_COLON2:
+ what2 = compile_node(node->nd_head);
+ if (rb_is_const_id(node->nd_mid)) {
+ type = DEFINED_CONST;
+ what1 = (VALUE)node->nd_mid;
+ }
+ else {
+ type = DEFINED_METHOD;
+ what1 = (VALUE)node->nd_mid;
+ }
+ break;
+
+ case NODE_CALL:
+ case NODE_VCALL:
+ case NODE_FCALL:
+ case NODE_ATTRASGN:
+ if (nd_type(node) == NODE_CALL
+ || (nd_type(node) == NODE_ATTRASGN
+ && node->nd_recv != (NODE *)1)) {
+ self = compile_node(node->nd_recv);
+ }
+ type = DEFINED_METHOD;
+ what1 = (VALUE)node->nd_mid;
+ break;
}
- if (str != 0) {
- return ConstantInt::get(RubyObjTy, (long)str);
+ if (type == 0) {
+ compile_node_error("unrecognized defined? arg", node);
}
- else {
- assert(defined_mode != -1);
- assert(defined_what != 0);
-
- if (definedFunc == NULL) {
- // VALUE rb_vm_defined(VALUE self, int mode, VALUE what);
- definedFunc =
- cast<Function>(module->getOrInsertFunction("rb_vm_defined",
- RubyObjTy, RubyObjTy, Type::Int32Ty, RubyObjTy,
- NULL));
- }
- std::vector<Value *> params;
+ if (definedFunc == NULL) {
+ // VALUE rb_vm_defined(VALUE self, int type, VALUE what, VALUE what2);
+ definedFunc = cast<Function>(module->getOrInsertFunction(
+ "rb_vm_defined",
+ RubyObjTy, RubyObjTy, Type::Int32Ty, RubyObjTy, RubyObjTy,
+ NULL));
+ }
- params.push_back(current_self);
- params.push_back(ConstantInt::get(Type::Int32Ty, defined_mode));
- params.push_back(ConstantInt::get(RubyObjTy, defined_what));
+ std::vector<Value *> params;
- return CallInst::Create(definedFunc, params.begin(), params.end(), "",
- bb);
- }
+ params.push_back(self);
+ params.push_back(ConstantInt::get(Type::Int32Ty, type));
+ params.push_back(ConstantInt::get(RubyObjTy, what1));
+ params.push_back(what2 == NULL ? nilVal : what2);
+
+ // Call the runtime.
+ Value *val = compile_protected_call(definedFunc, params);
+ BasicBlock *normal_bb = bb;
+ BranchInst::Create(merge_bb, bb);
+
+ // The rescue block - here we simply do nothing.
+ bb = new_rescue_bb;
+ compile_landing_pad_header();
+ compile_landing_pad_footer();
+ BranchInst::Create(merge_bb, bb);
+
+ // Now merging.
+ bb = merge_bb;
+ PHINode *pn = PHINode::Create(RubyObjTy, "", bb);
+ pn->addIncoming(val, normal_bb);
+ pn->addIncoming(nilVal, new_rescue_bb);
+
+ rescue_bb = old_rescue_bb;
+
+ return pn;
}
Value *
@@ -1216,7 +1237,6 @@
return compile_node(node->nd_head);
}
- // XXX not sure about that...
return compile_current_class();
}
@@ -1224,11 +1244,67 @@
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 will be smart enough to eliminate
+ // 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,
+ Intrinsic::eh_exception);
+ Value *eh_ptr = CallInst::Create(eh_exception_f, "", bb);
+
+#if __LP64__
+ Function *eh_selector_f = Intrinsic::getDeclaration(module,
+ Intrinsic::eh_selector_i64);
+#else
+ Function *eh_selector_f = Intrinsic::getDeclaration(module,
+ Intrinsic::eh_selector_i32);
+#endif
+
+ std::vector<Value *> params;
+ params.push_back(eh_ptr);
+ Function *__gxx_personality_v0_func = NULL;
+ if (__gxx_personality_v0_func == NULL) {
+ __gxx_personality_v0_func = cast<Function>(
+ module->getOrInsertFunction("__gxx_personality_v0",
+ PtrTy, NULL));
+ }
+ params.push_back(new BitCastInst(__gxx_personality_v0_func,
+ PtrTy, "", bb));
+ params.push_back(compile_const_pointer(NULL));
+
+ CallInst::Create(eh_selector_f, params.begin(), params.end(),
+ "", bb);
+
+ Function *beginCatchFunc = NULL;
+ if (beginCatchFunc == NULL) {
+ // void *__cxa_begin_catch(void *);
+ beginCatchFunc = cast<Function>(
+ module->getOrInsertFunction("__cxa_begin_catch",
+ Type::VoidTy, PtrTy, NULL));
+ }
+ params.clear();
+ params.push_back(eh_ptr);
+ CallInst::Create(beginCatchFunc, params.begin(), params.end(),
+ "", bb);
+}
+
+void
+RoxorCompiler::compile_landing_pad_footer(void)
+{
+ Function *endCatchFunc = NULL;
+ if (endCatchFunc == NULL) {
+ // void __cxa_end_catch(void);
+ endCatchFunc = cast<Function>(
+ module->getOrInsertFunction("__cxa_end_catch",
+ Type::VoidTy, NULL));
+ }
+ CallInst::Create(endCatchFunc, "", bb);
+}
+
Value *
RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, std::vector<Value *> ¶ms)
{
@@ -3583,56 +3659,19 @@
// Landing pad header.
bb = new_rescue_bb;
- Function *eh_exception_f = Intrinsic::getDeclaration(module, Intrinsic::eh_exception);
- Value *eh_ptr = CallInst::Create(eh_exception_f, "", bb);
+ compile_landing_pad_header();
-#if __LP64__
- Function *eh_selector_f = Intrinsic::getDeclaration(module, Intrinsic::eh_selector_i64);
-#else
- Function *eh_selector_f = Intrinsic::getDeclaration(module, Intrinsic::eh_selector_i32);
-#endif
-
- std::vector<Value *> params;
- params.push_back(eh_ptr);
- Function *__gxx_personality_v0_func = NULL;
- if (__gxx_personality_v0_func == NULL) {
- __gxx_personality_v0_func = cast<Function>(
- module->getOrInsertFunction("__gxx_personality_v0",
- PtrTy, NULL));
- }
- params.push_back(new BitCastInst(__gxx_personality_v0_func, PtrTy, "", bb));
- params.push_back(compile_const_pointer(NULL));
-
- CallInst::Create(eh_selector_f, params.begin(), params.end(), "", bb);
-
- Function *beginCatchFunc = NULL;
- if (beginCatchFunc == NULL) {
- // void *__cxa_begin_catch(void *);
- beginCatchFunc = cast<Function>(
- module->getOrInsertFunction("__cxa_begin_catch",
- Type::VoidTy, PtrTy, NULL));
- }
- params.clear();
- params.push_back(eh_ptr);
- CallInst::Create(beginCatchFunc, params.begin(), params.end(), "", bb);
-
// Landing pad code.
Value *rescue_val = compile_node(node->nd_resq);
new_rescue_bb = bb;
// Landing pad footer.
- Function *endCatchFunc = NULL;
- if (endCatchFunc == NULL) {
- // void __cxa_end_catch(void);
- endCatchFunc = cast<Function>(
- module->getOrInsertFunction("__cxa_end_catch",
- Type::VoidTy, NULL));
- }
- CallInst::Create(endCatchFunc, "", bb);
+ compile_landing_pad_footer();
BranchInst::Create(merge_bb, bb);
- PHINode *pn = PHINode::Create(RubyObjTy, "rescue_result", merge_bb);
+ PHINode *pn = PHINode::Create(RubyObjTy, "rescue_result",
+ merge_bb);
pn->addIncoming(begin_val, real_begin_bb);
pn->addIncoming(rescue_val, new_rescue_bb);
bb = merge_bb;
@@ -4275,34 +4314,67 @@
extern "C"
VALUE
-rb_vm_defined(VALUE self, int mode, VALUE what)
+rb_vm_defined(VALUE self, int type, VALUE what, VALUE what2)
{
const char *str = NULL;
- switch (mode) {
+ switch (type) {
case DEFINED_IVAR:
if (rb_ivar_defined(self, (ID)what)) {
str = "instance-variable";
}
break;
-// case DEFINED_CVAR:
-// TODO
-
case DEFINED_GVAR:
if (rb_gvar_defined((struct global_entry *)what)) {
str = "global-variable";
}
break;
+ case DEFINED_CVAR:
+ if (rb_cvar_defined(CLASS_OF(self), (ID)what)) {
+ str = "class variable";
+ }
+ break;
+
case DEFINED_CONST:
- if (rb_const_defined(CLASS_OF(self), (ID)what)) {
- str = "constant";
+ {
+ VALUE outer = what2;
+ if (NIL_P(outer)) {
+ outer = CLASS_OF(self);
+ }
+ if (rb_const_defined(outer, (ID)what)) {
+ str = "constant";
+ }
}
break;
+ case DEFINED_SUPER:
+ case DEFINED_METHOD:
+ {
+ VALUE klass = CLASS_OF(self);
+ if (type == DEFINED_SUPER) {
+ klass = RCLASS_SUPER(klass);
+ }
+ const char *idname = rb_id2name((ID)what);
+ SEL sel = sel_registerName(idname);
+
+ bool ok = class_getInstanceMethod((Class)klass, sel) != NULL;
+ if (!ok && idname[strlen(idname) - 1] != ':') {
+ char buf[100];
+ snprintf(buf, sizeof buf, "%s:", idname);
+ sel = sel_registerName(buf);
+ ok = class_getInstanceMethod((Class)klass, sel) != NULL;
+ }
+
+ if (ok) {
+ str = type == DEFINED_SUPER ? "super" : "method";
+ }
+ }
+ break;
+
default:
- printf("unrecognized defined? mode %d\n", mode);
+ printf("unknown defined? type %d", type);
abort();
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090324/4b915150/attachment-0001.html>
More information about the macruby-changes
mailing list