1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LLVM_LICENSE_HEADER@
5 */
6
7/*
8 *  import_interim_byref.c
9 *  Examples
10 *
11 *  Created by Blaine Garst on 2/13/08.
12 *  Copyright 2008 __MyCompanyName__. All rights reserved.
13 *
14 */
15
16
17
18#include "driver.h"
19
20// Interim closure implementation - merely keep addresses of stack until we learn
21// how to move other parameters into byref block
22//
23//
24
25#if __BLOCKS__
26int import_byref_interim_real(int verbose) {
27    int x = rand();
28    int y = 15;
29    void (^myClosure)(void) = ^ (void) { | y | setGlobalInt(x+y); ++y;};
30    x++;
31    callVoidVoid(myClosure);
32
33    int globalValue = getGlobalInt();
34    int desiredValue = x+y-2;
35    if (error_found("import_byref_interim", globalValue, desiredValue, verbose)) return 1;
36
37#if FULL_CLOSURES
38    void (^myClosureCopy)(void) = Block_copy(myClosure);
39    callVoidVoid(myClosureCopy);
40
41    globalValue = getGlobalInt();
42    if (error_found("import_byref_interim copy", globalValue, desiredValue, verbose)) return 1;
43
44    Block_release(myClosureCopy);
45#endif
46    return 0;
47}
48
49#endif __BLOCKS__
50
51
52struct import_byref_interim_struct {
53  struct Block_basic base;
54  const int x;
55  int *py;
56};
57
58// the "thunks" compiled for the invoke entry point of the import_byref
59
60void invoke_import_byref_interim(struct import_byref_interim_struct *aBlock) {
61  // no return value so just a void invoke
62  // the compound statement rewritten to reference locals via the const copies.
63  {
64    //printf("closure x is %d and y is %d\n", aBlock->x, *aBlock->py);
65    setGlobalInt(aBlock->x + *aBlock->py);
66    ++*aBlock->py;
67   }
68}
69
70
71// The rewritten version of the code above
72
73int import_byref_interim(int verbose) {
74   int x = rand();
75   int y = 15;
76
77   struct import_byref_interim_struct myClosure = {
78        { 0, BLOCK_NO_COPY, sizeof(struct import_byref_interim_struct),
79            (void (*)(void *))invoke_import_byref_interim,
80        },
81        x, // capture x
82        &y // capture y
83   };
84   x++;
85   callVoidVoid(&myClosure.base);
86
87   int globalValue = getGlobalInt();
88   int desiredValue = x+y-2;
89   if (error_found("import_byref_interim", globalValue, desiredValue, verbose)) return 1;
90
91#if FULL_CLOSURES
92    struct import_byref_interim_struct *myClosureCopy = Block_copy(&myClosure.base);
93    callVoidVoid(&myClosureCopy->base);
94
95    globalValue = getGlobalInt();
96    if (error_found("import_byref_interim copy", globalValue, desiredValue, verbose)) return 1;
97    Block_release(myClosureCopy);
98#endif
99
100
101    return 0;
102}
103