[Mono-bugs] [Bug 79312][Nor] Changed - returning a struct by value giving unexpected results

bugzilla-daemon at bugzilla.ximian.com bugzilla-daemon at bugzilla.ximian.com
Thu Sep 7 18:08:48 EDT 2006


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by james.eberle at comcast.net.

http://bugzilla.ximian.com/show_bug.cgi?id=79312

--- shadow/79312	2006-09-07 17:04:09.000000000 -0400
+++ shadow/79312.tmp.20786	2006-09-07 18:08:48.000000000 -0400
@@ -176,6 +176,192 @@
 
 
 
 ------- Additional Comments From robertj at gmx.net  2006-09-07 17:04 -------
 Jim, if you still have questions, reopen the bug.
 
+
+------- Additional Comments From james.eberle at comcast.net  2006-09-07 18:08 -------
+Apologies for dragging this out. I agree w/ your assessment (for the
+most part
+:) ). It's a C-linkage question more than anything to do w/ Mono.
+Short answer
+is that per PPC32 OSX ABI standards, void* are returned in GPR3, whereas
+composite values are returned as an address in GPR3. I'm including the
+code I
+used to demonstrate this to myself.
+
+I still have 2 questions.
+
+1. Since "IntPtr" is defined as struct, why doesn't it fall to the
+same incorrect
+bindings as any other struct? Is it a special-case at the p/invoke code?
+
+2. Can I use a MarshalAs attribute to force the proper return value
+semantics?
+I've tried this but could not get desired behavior.
+
+Many thanks!
+Jim
+
+--- Apple's PPC32 ABI ----
+
+http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/LowLevelABI.pdf
+
+32-bit PowerPC Function Calling Conventions
+
+* Returning Results *
+The following list describes where a function's return value is passed
+to the caller.
+
+- Scalars smaller than 4 bytes (such as char and short) are placed in
+the low
+  word of GPR3. The register's highword is undefined.
+
+- Scalars 4 bytes in size (such as long, int, and pointers, including
+array
+  pointers) are placed in GPR3.
+
+- Values of type long long are returned in the high word of GPR3 and
+the low
+  word of GPR4.
+
+- Floating-point values are placed in FPR1.
+
+- Composite values (such as struct and union) and values larger than 4
+bytes
+  are placed at the location pointed to by GPR3.
+
+--- Apple's PPC32 ABI (End) ----
+
+--- The gory details ----
+
+$ cat pt.c
+
+struct ShortPoint {
+  short x;
+  short y;
+};
+
+struct ShortPoint GetPoint() {
+  struct ShortPoint ret = { 16, 32 };
+  return ret;
+}
+
+void* GetPVoid() {
+  return (void*)8192;
+}
+
+$ gcc -c pt.c
+$ gcc -dynamiclib -o pt.dylib pt.o
+
+$ cat callpt.cs
+
+using System;
+using System.Runtime.InteropServices;
+
+struct ShortPoint {
+  internal short x;
+  internal short y;
+}
+
+struct IntStruct {
+  internal int x;
+}
+
+struct Call {
+  const string LIB = "pt.dylib";
+
+  public static void Main() {
+    ShortPoint pt = GetPoint();
+    Console.WriteLine("x: {0} y: {1}", (int)pt.x, (int)pt.y);
+
+    IntPtr    a = GetPVoid1();
+    IntStruct b = GetPVoid2();
+    Console.WriteLine("a: {0} b: {1}", (int)a, (int)b.x);
+  }
+
+  [DllImport(LIB)]
+  public static extern ShortPoint GetPoint();
+
+  [DllImport(LIB, EntryPoint="GetPVoid")]
+  public static extern IntPtr GetPVoid1();
+
+  [DllImport(LIB, EntryPoint="GetPVoid")]
+  public static extern IntStruct GetPVoid2();
+
+}
+
+$ mcs -warn:4 callpt.cs
+$ mono callpt.exe
+x: 16 y: 32
+a: 8192 b: 0
+
+$ cat callpt.c
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+struct ShortPoint {
+  short x;
+  short y;
+};
+
+typedef struct ShortPoint (*GETPT)();
+typedef void* (*GETPV)();
+
+int main(int argc, char* argv[]) {
+  void* lib = dlopen("pt.dylib", RTLD_LAZY);
+  if (lib == 0) {
+    return 1;
+  }
+  GETPT GetPoint = (GETPT)dlsym(lib, "GetPoint");
+  GETPV GetPVoid = (GETPV)dlsym(lib, "GetPVoid");
+  struct ShortPoint pt = GetPoint();
+  void* pv = GetPVoid();
+  printf("x: %hd, y: %hd\n", pt.x, pt.y);
+  printf("p: %d\n", pv);
+  dlclose(lib);
+  return 0;
+}
+
+$ gcc -g -o callpt callpt.c
+$ gcc -g -c pt.c
+$ gcc -dynamiclib -o pt.dylib pt.o
+
+$ ./callpt
+x: 16, y: 32
+p: 8192
+
+$ gdb callpt
+
+(gdb) disas
+Dump of assembler code for function GetPoint:
+0x00006f44 <GetPoint+0>:        stmw    r30,-8(r1)
+0x00006f48 <GetPoint+4>:        stwu    r1,-64(r1)
+0x00006f4c <GetPoint+8>:        mr      r30,r1
+0x00006f50 <GetPoint+12>:       mr      r2,r3
+0x00006f54 <GetPoint+16>:       li      r0,16
+0x00006f58 <GetPoint+20>:       sth     r0,24(r30)
+0x00006f5c <GetPoint+24>:       li      r0,32
+0x00006f60 <GetPoint+28>:       sth     r0,26(r30)
+0x00006f64 <GetPoint+32>:       lwz     r0,24(r30)
+0x00006f68 <GetPoint+36>:       stw     r0,0(r2)
+0x00006f6c <GetPoint+40>:       mr      r3,r2     ; <-- return ref to
+stack in r3
+0x00006f70 <GetPoint+44>:       lwz     r1,0(r1)
+0x00006f74 <GetPoint+48>:       lmw     r30,-8(r1)
+0x00006f78 <GetPoint+52>:       blr
+End of assembler dump.
+
+(gdb) disas
+Dump of assembler code for function GetPVoid:
+0x00006f7c <GetPVoid+0>:        stmw    r30,-8(r1)
+0x00006f80 <GetPVoid+4>:        stwu    r1,-48(r1)
+0x00006f84 <GetPVoid+8>:        mr      r30,r1
+0x00006f88 <GetPVoid+12>:       li      r0,8192
+0x00006f8c <GetPVoid+16>:       mr      r3,r0     ; <-- return value in r3
+0x00006f90 <GetPVoid+20>:       lwz     r1,0(r1)
+0x00006f94 <GetPVoid+24>:       lmw     r30,-8(r1)
+0x00006f98 <GetPVoid+28>:       blr
+End of assembler dump.
+


More information about the mono-bugs mailing list