186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst//
286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst//                     The LLVM Compiler Infrastructure
386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst//
486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst// This file is distributed under the University of Illinois Open Source
586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst// License. See LICENSE.TXT for details.
686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst/*
886d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst *  objectRRGC.c
986d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst *  testObjects
1086d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst *
1186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst *  Created by Blaine Garst on 10/31/08.
1286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst *
1386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst * Test that the runtime honors the new callouts properly for retain/release and GC
1486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst * CON FIG C  rdar://6175959
1586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst */
1686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
1786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
1886d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
1986d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst#include <stdio.h>
2086d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst#include <Block_private.h>
2186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
2286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
2386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garstint AssignCalled = 0;
2486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garstint DisposeCalled = 0;
2586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
2686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst// local copy instead of libSystem.B.dylib copy
2786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garstvoid _Block_object_assign(void *destAddr, const void *object, const int isWeak) {
2886d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    //printf("_Block_object_assign(%p, %p, %d) called\n", destAddr, object, isWeak);
2986d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    AssignCalled = 1;
3086d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst}
3186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
3286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garstvoid _Block_object_dispose(const void *object, const int isWeak) {
3386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    //printf("_Block_object_dispose(%p, %d) called\n", object, isWeak);
3486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    DisposeCalled = 1;
3586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst}
3686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
3786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garststruct MyStruct {
3886d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    long isa;
3986d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    long field;
4086d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst};
4186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
4286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garsttypedef struct MyStruct *__attribute__((NSObject)) MyStruct_t;
4386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst
4486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garstint main(int argc, char *argv[]) {
4586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    // create a block
4686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    struct MyStruct X;
4786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    MyStruct_t xp = (MyStruct_t)&X;
4886d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    xp->field = 10;
4986d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    void (^myBlock)(void) = ^{ printf("field is %ld\n", xp->field); };
5086d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    // should be a copy helper generated with a calls to above routines
5186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    // Lets find out!
5286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    struct Block_layout *bl = (struct Block_layout *)(void *)myBlock;
5386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    if ((bl->flags & BLOCK_HAS_DESCRIPTOR) != BLOCK_HAS_DESCRIPTOR) {
5486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        printf("using old runtime layout!\n");
5586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        return 1;
5686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    }
5786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    if ((bl->flags & BLOCK_HAS_COPY_DISPOSE) != BLOCK_HAS_COPY_DISPOSE) {
5886d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        printf("no copy dispose!!!!\n");
5986d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        return 1;
6086d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    }
6186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    // call helper routines directly.  These will, in turn, we hope, call the stubs above
6286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    long destBuffer[256];
6386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    //printf("destbuffer is at %p, block at %p\n", destBuffer, (void *)bl);
6486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    //printf("dump is %s\n", _Block_dump(myBlock));
6586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    bl->descriptor->copy(destBuffer, bl);
6686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    bl->descriptor->dispose(bl);
6786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    if (AssignCalled == 0) {
6886d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        printf("did not call assign helper!\n");
6986d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        return 1;
7086d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    }
7186d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    if (DisposeCalled == 0) {
7286d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        printf("did not call dispose helper\n");
7386d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst        return 1;
7486d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    }
7586d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    printf("%s: Success!\n", argv[0]);
7686d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst    return 0;
7786d0ba4286ec42dcd055bd22434c7f40009834bdBlaine Garst}
78