src/share/vm/opto/generateOptoStub.cpp

Print this page
rev 5186 : 8024342: PPC64 (part 111): Support for C calling conventions that require 64-bit ints.
Summary: Some platforms, as ppc and s390x/zArch require that 32-bit ints are passed as 64-bit values to C functions. This change adds support to adapt the signature and to issue proper casts to c2-compiled stubs. The functions are used in generate_native_wrapper(). Adapt signature in PhaseIdealLoop::intrinsify_fill().

@@ -44,10 +44,14 @@
                         int is_fancy_jump,
                         bool pass_tls,
                         bool return_pc) {
   ResourceMark rm;
 
+  // Do we need to convert ints to longs for c calls?
+  const bool convert_ints_to_longs =
+    SharedRuntime::c_calling_convention_requires_ints_as_longs();
+
   const TypeTuple *jdomain = C->tf()->domain();
   const TypeTuple *jrange  = C->tf()->range();
 
   // The procedure start
   StartNode* start = new (C) StartNode(root(), jdomain);

@@ -115,12 +119,20 @@
   // Compute signature for C call.  Varies from the Java signature!
   const Type **fields = TypeTuple::fields(2*parm_cnt+2);
   uint cnt = TypeFunc::Parms;
   // The C routines gets the base of thread-local storage passed in as an
   // extra argument.  Not all calls need it, but its cheap to add here.
-  for( ; cnt<parm_cnt; cnt++ )
-    fields[cnt] = jdomain->field_at(cnt);
+  for (uint pcnt = cnt; pcnt < parm_cnt; pcnt++, cnt++) {
+    // Convert ints to longs if required.
+    if (convert_ints_to_longs && jdomain->field_at(pcnt)->isa_int()) {
+      fields[cnt++] = TypeLong::LONG;
+      fields[cnt]   = Type::HALF; // must add an additional half for a long
+    } else {
+      fields[cnt] = jdomain->field_at(pcnt);
+    }
+  }
+
   fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage
   // Also pass in the caller's PC, if asked for.
   if( return_pc )
     fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC
 

@@ -167,16 +179,24 @@
   call->jvms()->set_bci(0);
   call->jvms()->set_offsets(cnt);
 
   // Set fixed predefined input arguments
   cnt = 0;
-  for( i=0; i<TypeFunc::Parms; i++ )
-    call->init_req( cnt++, map()->in(i) );
+  for (i = 0; i < TypeFunc::Parms; i++)
+    call->init_req(cnt++, map()->in(i));
   // A little too aggressive on the parm copy; return address is not an input
   call->set_req(TypeFunc::ReturnAdr, top());
-  for( ; i<parm_cnt; i++ )    // Regular input arguments
-    call->init_req( cnt++, map()->in(i) );
+  for (; i < parm_cnt; i++) { // Regular input arguments
+    // Convert ints to longs if required.
+    if (convert_ints_to_longs && jdomain->field_at(i)->isa_int()) {
+      Node* int_as_long = _gvn.transform(new (C) ConvI2LNode(map()->in(i)));
+      call->init_req(cnt++, int_as_long); // long
+      call->init_req(cnt++, top());       // half
+    } else {
+      call->init_req(cnt++, map()->in(i));
+    }
+  }
 
   call->init_req( cnt++, thread );
   if( return_pc )             // Return PC, if asked for
     call->init_req( cnt++, returnadr() );
   _gvn.transform_no_reclaim(call);