[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