[macruby-changes] [2903] MacRuby/trunk/compiler.cpp

source_changes at macosforge.org source_changes at macosforge.org
Mon Oct 26 19:26:42 PDT 2009


Revision: 2903
          http://trac.macosforge.org/projects/ruby/changeset/2903
Author:   lsansonetti at apple.com
Date:     2009-10-26 19:26:42 -0700 (Mon, 26 Oct 2009)
Log Message:
-----------
naive implementation of the not-enough-registers x86-64 ABI

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

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2009-10-27 02:25:44 UTC (rev 2902)
+++ MacRuby/trunk/compiler.cpp	2009-10-27 02:26:42 UTC (rev 2903)
@@ -6771,6 +6771,42 @@
     return slot;
 }
 
+#if __LP64__
+# define MAX_GPR_REGS 6
+# define MAX_SSE_REGS 8
+// The x86-64 ABI requires us to pass by reference arguments when there isn't
+// enough registers anymore. We need to count both GPR and SEE registers usage.
+// For more info: http://www.x86-64.org/documentation/abi.pdf
+static void
+examine(const Type *t, int *ngpr, int *nsse)
+{
+    switch (t->getTypeID()) {
+	case Type::IntegerTyID:
+	case Type::PointerTyID:
+	    (*ngpr)++;
+	    break;
+
+	case Type::FloatTyID:
+	case Type::DoubleTyID:
+	    (*nsse)++;
+	    break;
+
+	case Type::StructTyID:
+	    {
+		const StructType *st = cast<StructType>(t);
+		for (unsigned i = 0; i < st->getNumElements(); i++) {
+		    examine(st->getElementType(i), ngpr, nsse);
+		}
+	    }
+	    break;
+
+	default:
+	    // oops
+	    break;
+    }
+}
+#endif
+
 Function *
 RoxorCompiler::compile_objc_stub(Function *ruby_func, IMP ruby_imp,
 	const rb_vm_arity_t &arity, const char *types)
@@ -6781,6 +6817,10 @@
     const char *p = types;
     std::vector<const Type *> f_types;
 
+#if __LP64__
+    int gprcount = 0, ssecount = 0;
+#endif
+
     // Return value.
     p = GetFirstType(p, buf, sizeof buf);
     std::string ret_type(buf);
@@ -6793,6 +6833,9 @@
 	f_types.push_back(PointerType::getUnqual(f_ret_type));
 	f_sret_type = f_ret_type;
 	f_ret_type = VoidTy;
+#if __LP64__
+	gprcount++;
+#endif
     }
 
     // self
@@ -6803,13 +6846,29 @@
     f_types.push_back(PtrTy);
     p = SkipFirstType(p);
     p = SkipStackSize(p);
+#if __LP64__
+    gprcount += 2;
+#endif
     // Arguments.
     std::vector<std::string> arg_types;
     std::vector<unsigned int> byval_args;
     for (int i = 0; i < arity.real; i++) {
 	p = GetFirstType(p, buf, sizeof buf);
 	const Type *t = convert_type(buf);
-	if (GET_CORE()->is_large_struct_type(t)) {
+	bool enough_registers = true;
+#if __LP64__
+	int ngpr = 0, nsse = 0;
+	examine(t, &ngpr, &nsse);
+	if (gprcount + ngpr > MAX_GPR_REGS || ssecount + nsse > MAX_SSE_REGS) {
+	    enough_registers = false;
+	}
+	else {
+	    gprcount += ngpr;
+	    ssecount += nsse;
+	}
+	//printf("arg[%d] is using %d gpr %d sse\n", i, ngpr, nsse);
+#endif
+	if (!enough_registers || GET_CORE()->is_large_struct_type(t)) {
 	    // We are passing a large struct, we need to mark this argument
 	    // with the byval attribute and configure the internal stub
 	    // call to pass a pointer to the structure, to conform to the ABI.
@@ -6851,12 +6910,14 @@
     // Convert every incoming argument into Ruby type.
     for (int i = 0; i < arity.real; i++) {
 	Value *a = arg++;
+	const Type *t = f_types[i + 2 + sret_i];
 	if (std::find(byval_args.begin(), byval_args.end(),
 		    (unsigned int)i + 3 + sret_i) != byval_args.end()) {
 	    a = new LoadInst(a, "", bb);
+	    t = cast<PointerType>(t)->getElementType();
 	}
 	Value *ruby_arg = compile_conversion_to_ruby(arg_types[i].c_str(),
-		f_types[i + 2 + sret_i], a);
+		t, a);
 	params.push_back(ruby_arg);
     }
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091026/6892df7a/attachment.html>


More information about the macruby-changes mailing list