summaryrefslogtreecommitdiff
path: root/libffi
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2015-01-19 13:14:59 -0800
committerRichard Henderson <rth@gcc.gnu.org>2015-01-19 13:14:59 -0800
commit36035d796755d73bfb62b5b6c6afe19864016dd7 (patch)
treead7e07e65bd2c97439708c0d2db4ad604cfafe32 /libffi
parent9789b553b4c1248b56ec41f2bda47c6bb9785f2b (diff)
Merge with upstream libffi 3ac1610aa33c887ea9b14935208943925714a33e
Includes build fixes for Solaris and Cygwin. From-SVN: r219860
Diffstat (limited to 'libffi')
-rw-r--r--libffi/ChangeLog4
-rw-r--r--libffi/src/sparc/v8.S120
-rw-r--r--libffi/src/sparc/v9.S82
-rw-r--r--libffi/src/x86/sysv.S10
-rw-r--r--libffi/src/x86/unix64.S2
-rw-r--r--libffi/testsuite/libffi.call/pr1172638.c127
6 files changed, 252 insertions, 93 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index da17417eab4..dd8d516a42c 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,5 +1,9 @@
2015-01-19 Richard Henderson <rth@redhat.com>
+ * Merge to upstream commit 3ac1610aa33c887ea9b14935208943925714a33e.
+
+2015-01-19 Richard Henderson <rth@redhat.com>
+
PR libffi/64607
* testsuite/lib/libffi.exp (libffi-init): Append -L for the
just built libstdc++.
diff --git a/libffi/src/sparc/v8.S b/libffi/src/sparc/v8.S
index 3a811efe05f..3f483826c1a 100644
--- a/libffi/src/sparc/v8.S
+++ b/libffi/src/sparc/v8.S
@@ -48,7 +48,7 @@
#ifndef __GNUC__
.align 8
.globl C(ffi_flush_icache)
- .type C(ffi_flush_icache),@function
+ .type C(ffi_flush_icache),#function
FFI_HIDDEN(C(ffi_flush_icache))
C(ffi_flush_icache):
@@ -66,14 +66,15 @@ C(ffi_flush_icache):
.size C(ffi_flush_icache), . - C(ffi_flush_icache)
#endif
-.macro E index
- .align 16
- .org 2b + \index * 16
-.endm
+#if defined(__sun__) && defined(__svr4__)
+# define E(INDEX) .align 16
+#else
+# define E(INDEX) .align 16; .org 2b + INDEX * 16
+#endif
.align 8
.globl C(ffi_call_v8)
- .type C(ffi_call_v8),@function
+ .type C(ffi_call_v8),#function
FFI_HIDDEN(C(ffi_call_v8))
C(ffi_call_v8):
@@ -82,6 +83,7 @@ C(ffi_call_v8):
save %sp, %o4, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
+ cfi_register(%o7, %i7)
mov %i0, %o0 ! copy cif
add %sp, 64+32, %o1 ! load args area
@@ -114,71 +116,71 @@ C(ffi_call_v8):
! Note that each entry is 4 insns, enforced by the E macro.
.align 16
2:
-E SPARC_RET_VOID
+E(SPARC_RET_VOID)
ret
restore
-E SPARC_RET_STRUCT
+E(SPARC_RET_STRUCT)
unimp
-E SPARC_RET_UINT8
+E(SPARC_RET_UINT8)
and %o0, 0xff, %o0
st %o0, [%i2]
ret
restore
-E SPARC_RET_SINT8
+E(SPARC_RET_SINT8)
sll %o0, 24, %o0
b 7f
sra %o0, 24, %o0
-E SPARC_RET_UINT16
+E(SPARC_RET_UINT16)
sll %o0, 16, %o0
b 7f
srl %o0, 16, %o0
-E SPARC_RET_SINT16
+E(SPARC_RET_SINT16)
sll %o0, 16, %o0
b 7f
sra %o0, 16, %o0
-E SPARC_RET_UINT32
+E(SPARC_RET_UINT32)
7: st %o0, [%i2]
ret
restore
-E SP_V8_RET_CPLX16
+E(SP_V8_RET_CPLX16)
sth %o0, [%i2+2]
b 9f
srl %o0, 16, %o0
-E SPARC_RET_INT64
+E(SPARC_RET_INT64)
st %o0, [%i2]
st %o1, [%i2+4]
ret
restore
-E SPARC_RET_INT128
+E(SPARC_RET_INT128)
std %o0, [%i2]
std %o2, [%i2+8]
ret
restore
-E SPARC_RET_F_8
+E(SPARC_RET_F_8)
st %f7, [%i2+7*4]
nop
st %f6, [%i2+6*4]
nop
-E SPARC_RET_F_6
+E(SPARC_RET_F_6)
st %f5, [%i2+5*4]
nop
st %f4, [%i2+4*4]
nop
-E SPARC_RET_F_4
+E(SPARC_RET_F_4)
st %f3, [%i2+3*4]
nop
st %f2, [%i2+2*4]
nop
-E SPARC_RET_F_2
+E(SPARC_RET_F_2)
st %f1, [%i2+4]
st %f0, [%i2]
ret
restore
-E SP_V8_RET_CPLX8
+E(SP_V8_RET_CPLX8)
stb %o0, [%i2+1]
- b 10f
+ b 0f
srl %o0, 8, %o0
-E SPARC_RET_F_1
+E(SPARC_RET_F_1)
st %f0, [%i2]
ret
restore
@@ -188,7 +190,7 @@ E SPARC_RET_F_1
ret
restore
.align 8
-10: stb %o0, [%i2]
+0: stb %o0, [%i2]
ret
restore
@@ -201,17 +203,35 @@ E SPARC_RET_F_1
sll %l1, 2, %l0 ! size * 4
1: sll %l1, 4, %l1 ! size * 16
add %l0, %l1, %l0 ! size * 20
- add %o7, %l0, %o7 ! o7 = 0b + size*20
+ add %o7, %l0, %o7 ! o7 = 8b + size*20
jmp %o7+(2f-8b)
mov %i5, %g2 ! load static chain
2:
-.rept 0x1000
- call %i1
- nop
- unimp (. - 2b) / 20
- ret
+
+/* The Sun assembler doesn't understand .rept 0x1000. */
+#define rept1 \
+ call %i1; \
+ nop; \
+ unimp (. - 2b) / 20; \
+ ret; \
restore
-.endr
+
+#define rept16 \
+ rept1; rept1; rept1; rept1; \
+ rept1; rept1; rept1; rept1; \
+ rept1; rept1; rept1; rept1; \
+ rept1; rept1; rept1; rept1
+
+#define rept256 \
+ rept16; rept16; rept16; rept16; \
+ rept16; rept16; rept16; rept16; \
+ rept16; rept16; rept16; rept16; \
+ rept16; rept16; rept16; rept16
+
+ rept256; rept256; rept256; rept256
+ rept256; rept256; rept256; rept256
+ rept256; rept256; rept256; rept256
+ rept256; rept256; rept256; rept256
cfi_endproc
.size C(ffi_call_v8),. - C(ffi_call_v8)
@@ -231,7 +251,7 @@ E SPARC_RET_F_1
.align 8
.globl C(ffi_go_closure_v8)
- .type C(ffi_go_closure_v8),@function
+ .type C(ffi_go_closure_v8),#function
FFI_HIDDEN(C(ffi_go_closure_v8))
C(ffi_go_closure_v8):
@@ -239,6 +259,7 @@ C(ffi_go_closure_v8):
save %sp, -STACKFRAME, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
+ cfi_register(%o7, %i7)
ld [%g2+4], %o0 ! load cif
ld [%g2+8], %o1 ! load fun
@@ -249,7 +270,7 @@ C(ffi_go_closure_v8):
.align 8
.globl C(ffi_closure_v8)
- .type C(ffi_closure_v8),@function
+ .type C(ffi_closure_v8),#function
FFI_HIDDEN(C(ffi_closure_v8))
C(ffi_closure_v8):
@@ -257,6 +278,7 @@ C(ffi_closure_v8):
save %sp, -STACKFRAME, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
+ cfi_register(%o7, %i7)
ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif
ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun
@@ -285,70 +307,70 @@ C(ffi_closure_v8):
! Note that each entry is 4 insns, enforced by the E macro.
.align 16
2:
-E SPARC_RET_VOID
+E(SPARC_RET_VOID)
ret
restore
-E SPARC_RET_STRUCT
+E(SPARC_RET_STRUCT)
ld [%i2], %i0
jmp %i7+12
restore
-E SPARC_RET_UINT8
+E(SPARC_RET_UINT8)
ldub [%i2+3], %i0
ret
restore
-E SPARC_RET_SINT8
+E(SPARC_RET_SINT8)
ldsb [%i2+3], %i0
ret
restore
-E SPARC_RET_UINT16
+E(SPARC_RET_UINT16)
lduh [%i2+2], %i0
ret
restore
-E SPARC_RET_SINT16
+E(SPARC_RET_SINT16)
ldsh [%i2+2], %i0
ret
restore
-E SPARC_RET_UINT32
+E(SPARC_RET_UINT32)
ld [%i2], %i0
ret
restore
-E SP_V8_RET_CPLX16
+E(SP_V8_RET_CPLX16)
ld [%i2], %i0
ret
restore
-E SPARC_RET_INT64
+E(SPARC_RET_INT64)
ldd [%i2], %i0
ret
restore
-E SPARC_RET_INT128
+E(SPARC_RET_INT128)
ldd [%i2], %i0
ldd [%i2+8], %i2
ret
restore
-E SPARC_RET_F_8
+E(SPARC_RET_F_8)
ld [%i2+7*4], %f7
nop
ld [%i2+6*4], %f6
nop
-E SPARC_RET_F_6
+E(SPARC_RET_F_6)
ld [%i2+5*4], %f5
nop
ld [%i2+4*4], %f4
nop
-E SPARC_RET_F_4
+E(SPARC_RET_F_4)
ld [%i2+3*4], %f3
nop
ld [%i2+2*4], %f2
nop
-E SPARC_RET_F_2
+E(SPARC_RET_F_2)
ldd [%i2], %f0
ret
restore
-E SP_V8_RET_CPLX8
+E(SP_V8_RET_CPLX8)
lduh [%i2], %i0
ret
restore
-E SPARC_RET_F_1
+E(SPARC_RET_F_1)
ld [%i2], %f0
ret
restore
diff --git a/libffi/src/sparc/v9.S b/libffi/src/sparc/v9.S
index 52732d364ea..05ef54c3e15 100644
--- a/libffi/src/sparc/v9.S
+++ b/libffi/src/sparc/v9.S
@@ -42,17 +42,18 @@
#endif
#define L(Y) C1(.L, Y)
-.macro E index
- .align 16
- .org 2b + \index * 16
-.endm
+#if defined(__sun__) && defined(__svr4__)
+# define E(INDEX) .align 16
+#else
+# define E(INDEX) .align 16; .org 2b + INDEX * 16
+#endif
#define STACK_BIAS 2047
.text
.align 8
.globl C(ffi_call_v9)
- .type C(ffi_call_v9),@function
+ .type C(ffi_call_v9),#function
FFI_HIDDEN(C(ffi_call_v9))
C(ffi_call_v9):
@@ -60,6 +61,7 @@ C(ffi_call_v9):
save %sp, %o4, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
+ cfi_register(%o7, %i7)
mov %i0, %o0 ! copy cif
add %sp, STACK_BIAS+128+48, %o1 ! load args area
@@ -107,73 +109,73 @@ C(ffi_call_v9):
.align 16
2:
-E SPARC_RET_VOID
+E(SPARC_RET_VOID)
return %i7+8
nop
-E SPARC_RET_STRUCT
+E(SPARC_RET_STRUCT)
add %sp, STACK_BIAS-64+128+48, %l2
sub %sp, 64, %sp
b 8f
stx %o0, [%l2]
-E SPARC_RET_UINT8
+E(SPARC_RET_UINT8)
and %o0, 0xff, %i0
return %i7+8
stx %o0, [%o2]
-E SPARC_RET_SINT8
+E(SPARC_RET_SINT8)
sll %o0, 24, %o0
sra %o0, 24, %i0
return %i7+8
stx %o0, [%o2]
-E SPARC_RET_UINT16
+E(SPARC_RET_UINT16)
sll %o0, 16, %o0
srl %o0, 16, %i0
return %i7+8
stx %o0, [%o2]
-E SPARC_RET_SINT16
+E(SPARC_RET_SINT16)
sll %o0, 16, %o0
sra %o0, 16, %i0
return %i7+8
stx %o0, [%o2]
-E SPARC_RET_UINT32
+E(SPARC_RET_UINT32)
srl %o0, 0, %i0
return %i7+8
stx %o0, [%o2]
-E SP_V9_RET_SINT32
+E(SP_V9_RET_SINT32)
sra %o0, 0, %i0
return %i7+8
stx %o0, [%o2]
-E SPARC_RET_INT64
+E(SPARC_RET_INT64)
stx %o0, [%i2]
return %i7+8
nop
-E SPARC_RET_INT128
+E(SPARC_RET_INT128)
stx %o0, [%i2]
stx %o1, [%i2+8]
return %i7+8
nop
-E SPARC_RET_F_8
+E(SPARC_RET_F_8)
st %f7, [%i2+7*4]
nop
st %f6, [%i2+6*4]
nop
-E SPARC_RET_F_6
+E(SPARC_RET_F_6)
st %f5, [%i2+5*4]
nop
st %f4, [%i2+4*4]
nop
-E SPARC_RET_F_4
+E(SPARC_RET_F_4)
std %f2, [%i2+2*4]
return %i7+8
std %f0, [%o2]
-E SPARC_RET_F_2
+E(SPARC_RET_F_2)
return %i7+8
std %f0, [%o2]
-E SP_V9_RET_F_3
+E(SP_V9_RET_F_3)
st %f2, [%i2+2*4]
nop
st %f1, [%i2+1*4]
nop
-E SPARC_RET_F_1
+E(SPARC_RET_F_1)
return %i7+8
st %f0, [%o2]
@@ -213,7 +215,7 @@ E SPARC_RET_F_1
.align 8
.globl C(ffi_go_closure_v9)
- .type C(ffi_go_closure_v9),@function
+ .type C(ffi_go_closure_v9),#function
FFI_HIDDEN(C(ffi_go_closure_v9))
C(ffi_go_closure_v9):
@@ -221,6 +223,7 @@ C(ffi_go_closure_v9):
save %sp, -STACKFRAME, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
+ cfi_register(%o7, %i7)
ldx [%g5+8], %o0
ldx [%g5+16], %o1
@@ -232,7 +235,7 @@ C(ffi_go_closure_v9):
.align 8
.globl C(ffi_closure_v9)
- .type C(ffi_closure_v9),@function
+ .type C(ffi_closure_v9),#function
FFI_HIDDEN(C(ffi_closure_v9))
C(ffi_closure_v9):
@@ -240,6 +243,7 @@ C(ffi_closure_v9):
save %sp, -STACKFRAME, %sp
cfi_def_cfa_register(%fp)
cfi_window_save
+ cfi_register(%o7, %i7)
ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0
ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1
@@ -289,72 +293,72 @@ C(ffi_closure_v9):
! that is deallocated by the return.
.align 16
2:
-E SPARC_RET_VOID
+E(SPARC_RET_VOID)
return %i7+8
nop
-E SPARC_RET_STRUCT
+E(SPARC_RET_STRUCT)
ldx [FP-160], %i0
ldd [FP-160], %f0
b 8f
ldx [FP-152], %i1
-E SPARC_RET_UINT8
+E(SPARC_RET_UINT8)
ldub [FP-160+7], %i0
return %i7+8
nop
-E SPARC_RET_SINT8
+E(SPARC_RET_SINT8)
ldsb [FP-160+7], %i0
return %i7+8
nop
-E SPARC_RET_UINT16
+E(SPARC_RET_UINT16)
lduh [FP-160+6], %i0
return %i7+8
nop
-E SPARC_RET_SINT16
+E(SPARC_RET_SINT16)
ldsh [FP-160+6], %i0
return %i7+8
nop
-E SPARC_RET_UINT32
+E(SPARC_RET_UINT32)
lduw [FP-160+4], %i0
return %i7+8
nop
-E SP_V9_RET_SINT32
+E(SP_V9_RET_SINT32)
ldsw [FP-160+4], %i0
return %i7+8
nop
-E SPARC_RET_INT64
+E(SPARC_RET_INT64)
ldx [FP-160], %i0
return %i7+8
nop
-E SPARC_RET_INT128
+E(SPARC_RET_INT128)
ldx [FP-160], %i0
ldx [FP-160+8], %i1
return %i7+8
nop
-E SPARC_RET_F_8
+E(SPARC_RET_F_8)
ld [FP-160+7*4], %f7
nop
ld [FP-160+6*4], %f6
nop
-E SPARC_RET_F_6
+E(SPARC_RET_F_6)
ld [FP-160+5*4], %f5
nop
ld [FP-160+4*4], %f4
nop
-E SPARC_RET_F_4
+E(SPARC_RET_F_4)
ldd [FP-160], %f0
ldd [FP-160+8], %f2
return %i7+8
nop
-E SPARC_RET_F_2
+E(SPARC_RET_F_2)
ldd [FP-160], %f0
return %i7+8
nop
-E SP_V9_RET_F_3
+E(SP_V9_RET_F_3)
ld [FP-160+2*4], %f2
nop
ld [FP-160+1*4], %f1
nop
-E SPARC_RET_F_1
+E(SPARC_RET_F_1)
ld [FP-160], %f0
return %i7+8
nop
diff --git a/libffi/src/x86/sysv.S b/libffi/src/x86/sysv.S
index ebbea5d1110..78f245bda07 100644
--- a/libffi/src/x86/sysv.S
+++ b/libffi/src/x86/sysv.S
@@ -65,7 +65,7 @@
actual table. The entry points into the table are all 8 bytes.
The use of ORG asserts that we're at the correct location. */
/* ??? The clang assembler doesn't handle .org with symbolic expressions. */
-#if defined(__clang__) || defined(__APPLE__)
+#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__))
# define E(BASE, X) .balign 8
#else
# define E(BASE, X) .balign 8; .org BASE + X * 8
@@ -793,7 +793,7 @@ ENDF(C(ffi_closure_raw_THISCALL))
.section __TEXT,__textcoal_nt,coalesced,pure_instructions; \
.weak_definition X; \
.private_extern X
-#elif defined __ELF__
+#elif defined __ELF__ && !(defined(__sun__) && defined(__svr4__))
# define COMDAT(X) \
.section .text.X,"axG",@progbits,X,comdat; \
.globl X; \
@@ -822,10 +822,12 @@ ENDF(C(__x86.get_pc_thunk.dx))
#ifdef __APPLE__
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EHFrame0:
+#elif defined(X86_WIN32)
+.section .eh_frame,"r"
#elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE)
-.section .eh_frame,"a",@unwind
+.section .eh_frame,EH_FRAME_FLAGS,@unwind
#else
-.section .eh_frame,"a",@progbits
+.section .eh_frame,EH_FRAME_FLAGS,@progbits
#endif
#ifdef HAVE_AS_X86_PCREL
diff --git a/libffi/src/x86/unix64.S b/libffi/src/x86/unix64.S
index f9f916312c5..c83010c75b5 100644
--- a/libffi/src/x86/unix64.S
+++ b/libffi/src/x86/unix64.S
@@ -60,7 +60,7 @@
actual table. The entry points into the table are all 8 bytes.
The use of ORG asserts that we're at the correct location. */
/* ??? The clang assembler doesn't handle .org with symbolic expressions. */
-#if defined(__clang__) || defined(__APPLE__)
+#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__))
# define E(BASE, X) .balign 8
#else
# define E(BASE, X) .balign 8; .org BASE + X * 8
diff --git a/libffi/testsuite/libffi.call/pr1172638.c b/libffi/testsuite/libffi.call/pr1172638.c
new file mode 100644
index 00000000000..7da1621cd66
--- /dev/null
+++ b/libffi/testsuite/libffi.call/pr1172638.c
@@ -0,0 +1,127 @@
+/* Area: ffi_call
+ Purpose: Reproduce bug found in python ctypes
+ Limitations: none.
+ PR: Fedora 1174037 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct {
+ long x;
+ long y;
+} POINT;
+
+typedef struct {
+ long left;
+ long top;
+ long right;
+ long bottom;
+} RECT;
+
+static RECT ABI_ATTR pr_test(int i __UNUSED__, RECT ar __UNUSED__,
+ RECT* br __UNUSED__, POINT cp __UNUSED__,
+ RECT dr __UNUSED__, RECT *er __UNUSED__,
+ POINT fp, RECT gr __UNUSED__)
+{
+ RECT result;
+
+ result.left = fp.x;
+ result.right = fp.y;
+ result.top = fp.x;
+ result.bottom = fp.y;
+
+ return result;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type point_type, rect_type;
+ ffi_type *point_type_elements[3];
+ ffi_type *rect_type_elements[5];
+
+ int i;
+ POINT cp, fp;
+ RECT ar, br, dr, er, gr;
+ RECT *p1, *p2;
+
+ /* This is a hack to get a properly aligned result buffer */
+ RECT *rect_result =
+ (RECT *) malloc (sizeof(RECT));
+
+ point_type.size = 0;
+ point_type.alignment = 0;
+ point_type.type = FFI_TYPE_STRUCT;
+ point_type.elements = point_type_elements;
+ point_type_elements[0] = &ffi_type_slong;
+ point_type_elements[1] = &ffi_type_slong;
+ point_type_elements[2] = NULL;
+
+ rect_type.size = 0;
+ rect_type.alignment = 0;
+ rect_type.type = FFI_TYPE_STRUCT;
+ rect_type.elements = rect_type_elements;
+ rect_type_elements[0] = &ffi_type_slong;
+ rect_type_elements[1] = &ffi_type_slong;
+ rect_type_elements[2] = &ffi_type_slong;
+ rect_type_elements[3] = &ffi_type_slong;
+ rect_type_elements[4] = NULL;
+
+ args[0] = &ffi_type_sint;
+ args[1] = &rect_type;
+ args[2] = &ffi_type_pointer;
+ args[3] = &point_type;
+ args[4] = &rect_type;
+ args[5] = &ffi_type_pointer;
+ args[6] = &point_type;
+ args[7] = &rect_type;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 8, &rect_type, args) == FFI_OK);
+
+ i = 1;
+ ar.left = 2;
+ ar.right = 3;
+ ar.top = 4;
+ ar.bottom = 5;
+ br.left = 6;
+ br.right = 7;
+ br.top = 8;
+ br.bottom = 9;
+ cp.x = 10;
+ cp.y = 11;
+ dr.left = 12;
+ dr.right = 13;
+ dr.top = 14;
+ dr.bottom = 15;
+ er.left = 16;
+ er.right = 17;
+ er.top = 18;
+ er.bottom = 19;
+ fp.x = 20;
+ fp.y = 21;
+ gr.left = 22;
+ gr.right = 23;
+ gr.top = 24;
+ gr.bottom = 25;
+
+ values[0] = &i;
+ values[1] = &ar;
+ p1 = &br;
+ values[2] = &p1;
+ values[3] = &cp;
+ values[4] = &dr;
+ p2 = &er;
+ values[5] = &p2;
+ values[6] = &fp;
+ values[7] = &gr;
+
+ ffi_call (&cif, FFI_FN(pr_test), rect_result, values);
+
+ CHECK(rect_result->top == 20);
+
+ free (rect_result);
+ exit(0);
+}