[macruby-changes] [4882] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Nov 4 19:06:15 PDT 2010


Revision: 4882
          http://trac.macosforge.org/projects/ruby/changeset/4882
Author:   lsansonetti at apple.com
Date:     2010-11-04 19:06:13 -0700 (Thu, 04 Nov 2010)
Log Message:
-----------
add support for C-style arrays (from/to Ruby)

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

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2010-11-04 18:17:48 UTC (rev 4881)
+++ MacRuby/trunk/compiler.cpp	2010-11-05 02:06:13 UTC (rev 4882)
@@ -196,6 +196,8 @@
     dupArrayFunc = get_function("vm_ary_dup");
     newArrayFunc = get_function("vm_rary_new");
     asetArrayFunc = get_function("vm_rary_aset");
+    entryArrayFunc = get_function("vm_ary_entry");
+    checkArrayFunc = get_function("vm_ary_check");
     newStructFunc = NULL;
     newOpaqueFunc = NULL;
     newPointerFunc = NULL;
@@ -5336,6 +5338,42 @@
     return new BitCastInst(f, PtrTy, "", bb);
 }
 
+static void
+decompose_ary_type(const char *type, long *size_p, char *elem_type_p, 
+	const size_t elem_type_len)
+{
+    // Syntax is [8S] for `short foo[8]'.
+    // First, let's grab the size.
+    char buf[100];
+    unsigned int n = 0;
+    const char *p = type + 1;
+    while (isdigit(*p)) {
+	assert(n < (sizeof buf) - 1);
+	buf[n++] = *p;
+	p++;
+    }
+    assert(n > 0);
+    buf[n] = '\0';
+    const long size = atol(buf);
+    assert(size > 0);
+    if (size_p != NULL) {
+	*size_p = size;
+    }
+
+    // Second, the element type.
+    n = 0;
+    while (*p != _C_ARY_E) {
+	assert(n < (sizeof buf) - 1);
+	buf[n++] = *p;
+	p++;
+    }
+    assert(n > 0);
+    buf[n] = '\0';
+    if (elem_type_p != NULL) {
+	strlcpy(elem_type_p, buf, elem_type_len);
+    }
+}
+
 Value *
 RoxorCompiler::compile_conversion_to_c(const char *type, Value *val,
 	Value *slot)
@@ -5506,6 +5544,40 @@
 		return compile_get_cptr(val, type, slot);
 	    }
 	    break;
+
+	case _C_ARY_B:
+	    {
+		const ArrayType *ary_type = cast<ArrayType>(convert_type(type));
+		const Type *elem_type = ary_type->getElementType();
+		const unsigned elem_count = ary_type->getNumElements();
+
+		char elem_c_type[100];
+		decompose_ary_type(type, NULL, elem_c_type,
+			sizeof elem_c_type);
+
+		Value *elem_count_val = ConstantInt::get(Int32Ty, elem_count);
+		Value *args[] = {
+		    val,
+		    elem_count_val	
+		};
+		val = CallInst::Create(checkArrayFunc, args, args + 2, "", bb); 	
+		Value *ary = new AllocaInst(elem_type, elem_count_val, "", bb);
+		for (unsigned i = 0; i < elem_count; i++) {
+		    Value *idx = ConstantInt::get(Int32Ty, i);
+		    Value *args[] = {
+			val,
+			idx	
+		    };
+		    Value *elem = CallInst::Create(entryArrayFunc,
+			    args, args + 2, "", bb);
+		    Value *slot = GetElementPtrInst::Create(ary, idx, "", bb);
+		    compile_conversion_to_c(elem_c_type, elem, slot);
+		}
+
+		return new BitCastInst(ary, PointerType::getUnqual(ary_type),
+			"", bb);
+	    }
+	    break;
     }
 
     if (func == NULL) {
@@ -5745,7 +5817,35 @@
 
 		return compile_new_pointer(type + 1, val);
 	    }
-	    break; 
+	    break;
+
+	case _C_ARY_B:
+	    {
+		long elem_count = 0;
+		char elem_c_type[100];
+		decompose_ary_type(type, &elem_count, elem_c_type,
+			sizeof elem_c_type);
+		const Type *elem_type = convert_type(elem_c_type);
+
+		val = new BitCastInst(val, PointerType::getUnqual(elem_type),
+			"", bb);
+
+		Value *ary = CallInst::Create(newArrayFunc,
+			ConstantInt::get(Int32Ty, elem_count), "", bb);
+		for (long i = 0; i < elem_count; i++) {
+		    Value *idx = ConstantInt::get(Int32Ty, i);
+		    Value *slot = GetElementPtrInst::Create(val, idx, "", bb);
+		    Value *elem = new LoadInst(slot, "", bb);
+		    Value *args[] = {
+			ary,
+			idx,
+			compile_conversion_to_ruby(elem_c_type, elem_type, elem)
+		    };
+		    CallInst::Create(asetArrayFunc, args, args + 3, "", bb);
+		}
+		return ary;
+	    }
+	    break;
     }
 
     if (func == NULL) {
@@ -5819,29 +5919,9 @@
 
 	case _C_ARY_B:
 	    {
-		// Syntax is [8S] for `short foo[8]'.
-		// First, let's grab the size.
 		char buf[100];
-		unsigned int n = 0;
-		const char *p = type + 1;
-		while (isdigit(*p)) {
-		    assert(n < (sizeof buf) - 1);
-		    buf[n++] = *p;
-		    p++;
-		}
-		assert(n > 0);
-		buf[n] = '\0';
-		const long size = atol(buf);
-		assert(size > 0);
-		// Second, the element type.
-		n = 0;
-		while (*p != _C_ARY_E) {
-		    assert(n < (sizeof buf) - 1);
-		    buf[n++] = *p;
-		    p++;
-		}
-		assert(n > 0);
-		buf[n] = '\0';
+		long size = 0;
+		decompose_ary_type(type, &size, buf, sizeof buf);
 		const Type *type = convert_type(buf);
 		// Now, we can return the array type.
 		return ArrayType::get(type, size);
@@ -5969,6 +6049,10 @@
 	    f_type = PointerType::getUnqual(llvm_type);
 	    byval_args.push_back(f_types.size() + 1 /* retval */);
 	}
+	else if (ArrayType::classof(llvm_type)) {
+	    // Vectors are passed by reference.
+	    f_type = PointerType::getUnqual(llvm_type);
+	}
 
 	if (!stop_arg_type) {
 	    // In order to conform to the ABI, we must stop providing types
@@ -6353,6 +6437,10 @@
 	    t = PointerType::getUnqual(t);
 	    byval_args.push_back(f_types.size() + 1 /* retval */);
 	}
+	else if (ArrayType::classof(t)) {
+	    // Vectors are passed by reference.
+	    t = PointerType::getUnqual(t);
+	}
 	f_types.push_back(t);
 	arg_types.push_back(buf);
     }

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2010-11-04 18:17:48 UTC (rev 4881)
+++ MacRuby/trunk/compiler.h	2010-11-05 02:06:13 UTC (rev 4882)
@@ -186,6 +186,8 @@
 	Function *dupArrayFunc;
 	Function *newArrayFunc;
 	Function *asetArrayFunc;
+	Function *entryArrayFunc;
+	Function *checkArrayFunc;
 	Function *newStructFunc;
 	Function *newOpaqueFunc;
 	Function *newPointerFunc;

Modified: MacRuby/trunk/kernel.c
===================================================================
--- MacRuby/trunk/kernel.c	2010-11-04 18:17:48 UTC (rev 4881)
+++ MacRuby/trunk/kernel.c	2010-11-05 02:06:13 UTC (rev 4882)
@@ -925,6 +925,26 @@
 }
 
 PRIMITIVE VALUE
+vm_ary_check(VALUE obj, int size)
+{
+    VALUE ary = rb_check_convert_type(obj, T_ARRAY, "Array", "to_ary");
+    if (NIL_P(ary)) {
+	rb_raise(rb_eTypeError, "expected Array");
+    }
+    if (RARRAY_LEN(ary) != size) {
+	rb_raise(rb_eArgError, "expected Array of size %d, got %ld",
+		size, RARRAY_LEN(ary));
+    }
+    return ary;
+}
+
+PRIMITIVE VALUE
+vm_ary_entry(VALUE ary, int i)
+{
+    return rb_ary_entry(ary, i);
+}
+
+PRIMITIVE VALUE
 vm_rary_new(int len)
 {
     VALUE ary = rb_ary_new2(len);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20101104/e721b17b/attachment-0001.html>


More information about the macruby-changes mailing list