[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