summary refs log tree commit diff stats
path: root/tinyc/c67-link.c
blob: de72e442f85b3b3c7bcae3d9e2e242e32952cf34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifdef TARGET_DEFS_ONLY

#define EM_TCC_TARGET EM_C60

/* relocation type for 32 bit data relocation */
#define R_DATA_32   R_C60_32
#define R_DATA_PTR  R_C60_32
#define R_JMP_SLOT  R_C60_JMP_SLOT
#define R_GLOB_DAT  R_C60_GLOB_DAT
#define R_COPY      R_C60_COPY
#define R_RELATIVE  R_C60_RELATIVE

#define R_NUM       R_C60_NUM

#define ELF_START_ADDR 0x00000400
#define ELF_PAGE_SIZE  0x1000

#define PCRELATIVE_DLLPLT 0
#define RELOCATE_DLLPLT 0

#else /* !TARGET_DEFS_ONLY */

#include "tcc.h"

/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
   relocations, returns -1. */
int code_reloc (int reloc_type)
{
    switch (reloc_type) {
        case R_C60_32:
	case R_C60LO16:
	case R_C60HI16:
        case R_C60_GOT32:
        case R_C60_GOTOFF:
        case R_C60_GOTPC:
        case R_C60_COPY:
            return 0;

        case R_C60_PLT32:
            return 1;
    }

    tcc_error ("Unknown relocation type: %d", reloc_type);
    return -1;
}

/* Returns an enumerator to describe whether and when the relocation needs a
   GOT and/or PLT entry to be created. See tcc.h for a description of the
   different values. */
int gotplt_entry_type (int reloc_type)
{
    switch (reloc_type) {
        case R_C60_32:
	case R_C60LO16:
	case R_C60HI16:
        case R_C60_COPY:
            return NO_GOTPLT_ENTRY;

        case R_C60_GOTOFF:
        case R_C60_GOTPC:
            return BUILD_GOT_ONLY;

        case R_C60_PLT32:
        case R_C60_GOT32:
            return ALWAYS_GOTPLT_ENTRY;
    }

    tcc_error ("Unknown relocation type: %d", reloc_type);
    return -1;
}

ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
    tcc_error("C67 got not implemented");
    return 0;
}

/* relocate the PLT: compute addresses and offsets in the PLT now that final
   address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *s1)
{
    uint8_t *p, *p_end;

    if (!s1->plt)
      return;

    p = s1->plt->data;
    p_end = p + s1->plt->data_offset;

    if (p < p_end) {
        /* XXX: TODO */
        while (p < p_end) {
            /* XXX: TODO */
        }
   }
}

void relocate_init(Section *sr) {}

void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
    switch(type) {
        case R_C60_32:
            *(int *)ptr += val;
            break;
        case R_C60LO16:
            {
                uint32_t orig;

                /* put the low 16 bits of the absolute address add to what is
                   already there */
                orig  =   ((*(int *)(ptr  )) >> 7) & 0xffff;
                orig |=  (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;

                /* patch both at once - assumes always in pairs Low - High */
                *(int *) ptr    = (*(int *) ptr    & (~(0xffff << 7)) ) |
                                   (((val+orig)      & 0xffff) << 7);
                *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) |
                                  ((((val+orig)>>16) & 0xffff) << 7);
            }
            break;
        case R_C60HI16:
            break;
        default:
            fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
                    type, (unsigned) addr, ptr, (unsigned) val);
            break;
    }
}

#endif /* !TARGET_DEFS_ONLY */
> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:address:number <span class="Constant">5</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number ] <span class="Comment"># both allocations should have returned the same address</span> <span class="traceContains">+mem: storing 1 in location 5</span> <span class="Delimiter">:(before &quot;End Decrement Reference Count(old_address, payload_type, payload_size)&quot;)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>old_refcount == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;automatically abandoning &quot;</span> &lt;&lt; old_address &lt;&lt; end<span class="Delimiter">();</span> abandon<span class="Delimiter">(</span>old_address<span class="Delimiter">,</span> payload_type<span class="Delimiter">,</span> payload_size<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">//: When abandoning addresses we'll save them to a 'free list', segregated by size.</span> <span class="Delimiter">:(before &quot;End routine Fields&quot;)</span> map&lt;<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>&gt; free_list<span class="Delimiter">;</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> abandon<span class="Delimiter">(</span><span class="Normal">int</span> address<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* payload_type<span class="Delimiter">,</span> <span class="Normal">int</span> payload_size<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;abandon&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;updating refcounts inside &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>payload_type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="CommentedCode">//? Total_free += size;</span> <span class="CommentedCode">//? Num_free++;</span> <span class="CommentedCode">//? cerr &lt;&lt; &quot;abandon: &quot; &lt;&lt; size &lt;&lt; '\n';</span> <span class="Comment">// decrement any contained refcounts</span> <span class="Normal">if</span> <span class="Delimiter">(</span>payload_type<span class="Delimiter">-&gt;</span>name == <span class="Constant">&quot;array&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> reagent element<span class="Delimiter">;</span> element<span class="Delimiter">.</span>type = copy_array_element<span class="Delimiter">(</span>payload_type<span class="Delimiter">);</span> <span class="Normal">int</span> array_length = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>name != <span class="Constant">&quot;array&quot;</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span>element<span class="Delimiter">.</span>value = address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">skip length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> element<span class="Delimiter">.</span>value &lt; address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">skip length</span><span class="Comment">*/</span><span class="Constant">1</span>+array_length<span class="Delimiter">;</span> ++element<span class="Delimiter">.</span>value<span class="Delimiter">)</span> update_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>element<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Normal">int</span> element_size = size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> vector&lt;<span class="Normal">double</span>&gt; zeros<span class="Delimiter">;</span> zeros<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>element_size<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; array_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> element<span class="Delimiter">.</span>value = address + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> + <span class="Comment">/*</span><span class="Comment">skip array length</span><span class="Comment">*/</span><span class="Constant">1</span> + i*element_size<span class="Delimiter">;</span> update_container_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> zeros<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>payload_type<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>payload_type<span class="Delimiter">))</span> <span class="Delimiter">{</span> reagent tmp<span class="Delimiter">;</span> tmp<span class="Delimiter">.</span>value = address + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> tmp<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*payload_type<span class="Delimiter">);</span> vector&lt;<span class="Normal">double</span>&gt; zeros<span class="Delimiter">;</span> zeros<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>size_of<span class="Delimiter">(</span>payload_type<span class="Delimiter">));</span> update_container_refcounts<span class="Delimiter">(</span>tmp<span class="Delimiter">,</span> zeros<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// clear memory</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = address<span class="Delimiter">;</span> curr &lt; address+payload_size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// append existing free list to address</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;abandon&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;saving &quot;</span> &lt;&lt; address &lt;&lt; <span class="Constant">&quot; in free-list of size &quot;</span> &lt;&lt; payload_size &lt;&lt; end<span class="Delimiter">();</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>free_list<span class="Delimiter">,</span> payload_size<span class="Delimiter">));</span> put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>free_list<span class="Delimiter">,</span> payload_size<span class="Delimiter">,</span> address<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;ensure_space(size)&quot; following &quot;case ALLOCATE&quot;)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">))</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;abandon&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;picking up space from free-list of size &quot;</span> &lt;&lt; size &lt;&lt; end<span class="Delimiter">();</span> <span class="Normal">int</span> result = get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;new alloc from free list: &quot;</span> &lt;&lt; result &lt;&lt; end<span class="Delimiter">();</span> put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">));</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = result+<span class="Constant">1</span><span class="Delimiter">;</span> curr &lt; result+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;memory in free list was not zeroed out: &quot;</span> &lt;&lt; curr &lt;&lt; <span class="Constant">'/'</span> &lt;&lt; result &lt;&lt; <span class="Constant">&quot;; somebody wrote to us after free!!!</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// always fatal</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Normal">else</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario new_differing_size_no_reclaim)</span> def main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:number <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># abandon</span> <span class="Constant">3</span>:address:array:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> <span class="Comment"># different size</span> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:address:array:number <span class="Constant">5</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number ] <span class="Comment"># no reuse</span> <span class="traceContains">+mem: storing 0 in location 5</span> <span class="Delimiter">:(scenario new_reclaim_array)</span> def main [ <span class="Constant">1</span>:address:array:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:array:number <span class="Constant">1</span>:address:array:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Comment"># abandon</span> <span class="Constant">3</span>:address:array:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">2</span> <span class="Comment"># same size</span> <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:address:array:number <span class="Constant">5</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:number<span class="Delimiter">,</span> <span class="Constant">4</span>:number ] <span class="Comment"># both calls to new returned identical addresses</span> <span class="traceContains">+mem: storing 1 in location 5</span> <span class="Delimiter">:(scenario abandon_on_overwrite)</span> def main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Comment"># over-writing one allocation with another</span> <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: automatically abandoning 1000</span> <span class="Delimiter">:(scenario abandon_after_call)</span> def main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Comment"># passing in addresses to recipes increments refcount</span> foo <span class="Constant">1</span>:address:number <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] def foo [ <span class="Constant">2</span>:address:number<span class="Special"> &lt;- </span>next-ingredient <span class="Comment"># return does NOT yet decrement refcount; memory must be explicitly managed</span> <span class="Constant">2</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;number&quot;)} &lt;- next-ingredient</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 1 -&gt; 0</span> <span class="traceContains">+mem: automatically abandoning 1000</span> <span class="Delimiter">:(scenario abandon_on_overwrite_array)</span> def main [ <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">30</span> <span class="Comment"># allocate an array</span> <span class="Constant">10</span>:address:array:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">20</span> <span class="Constant">11</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>:address:array:number <span class="Comment"># doesn't increment refcount</span> <span class="Comment"># allocate another array in its place, implicitly freeing the previous allocation</span> <span class="Constant">10</span>:address:array:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">25</span> ] <span class="traceContains">+run: {10: (&quot;address&quot; &quot;array&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}, {25: &quot;literal&quot;}</span> <span class="Comment"># abandoned array is of old size (20, not 25)</span> <span class="traceContains">+abandon: saving 1000 in free-list of size 22</span> <span class="Delimiter">:(scenario refcounts_abandon_address_in_container)</span> <span class="Comment"># container containing an address</span> container foo [ <span class="Normal">x</span>:address:number ] def main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:address:foo<span class="Special"> &lt;- </span><span class="Normal">new</span> foo:type *<span class="Constant">2</span>:address:foo<span class="Special"> &lt;- </span>put *<span class="Constant">2</span>:address:foo<span class="Delimiter">,</span> x:offset<span class="Delimiter">,</span> <span class="Constant">1</span>:address:number <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Constant">2</span>:address:foo<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;foo&quot;)} &lt;- new {foo: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1002: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()} &lt;- put {2: (&quot;address&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}, {x: &quot;offset&quot;}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;foo&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="Comment"># start abandoning container containing address</span> <span class="traceContains">+mem: decrementing refcount of 1002: 1 -&gt; 0</span> <span class="Comment"># nested abandon</span> <span class="traceContains">+mem: decrementing refcount of 1000: 1 -&gt; 0</span> <span class="traceContains">+abandon: saving 1000 in free-list of size 2</span> <span class="Comment"># actually abandon the container containing address</span> <span class="traceContains">+abandon: saving 1002 in free-list of size 2</span> <span class="Comment"># todo: move past dilated reagent</span> <span class="Delimiter">:(scenario refcounts_abandon_address_in_array)</span> def main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:address:array:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> <span class="Delimiter">{(</span>address number<span class="Delimiter">)</span>: type<span class="Delimiter">},</span> <span class="Constant">3</span> *<span class="Constant">2</span>:address:array:address:number<span class="Special"> &lt;- </span>put-index *<span class="Constant">2</span>:address:array:address:number<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:number <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Constant">2</span>:address:array:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;array&quot; &quot;address&quot; &quot;number&quot;), &quot;lookup&quot;: ()} &lt;- put-index {2: (&quot;address&quot; &quot;array&quot; &quot;address&quot; &quot;number&quot;), &quot;lookup&quot;: ()}, {1: &quot;literal&quot;}, {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;array&quot; &quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="Comment"># nested abandon</span> <span class="traceContains">+mem: decrementing refcount of 1000: 1 -&gt; 0</span> <span class="traceContains">+abandon: saving 1000 in free-list of size 2</span> <span class="Delimiter">:(scenario refcounts_abandon_address_in_container_in_array)</span> <span class="Comment"># container containing an address</span> container foo [ <span class="Normal">x</span>:address:number ] def main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span><span class="Normal">new</span> number:type <span class="Constant">2</span>:address:array:foo<span class="Special"> &lt;- </span><span class="Normal">new</span> foo:type<span class="Delimiter">,</span> <span class="Constant">3</span> <span class="Constant">3</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">1</span>:address:number *<span class="Constant">2</span>:address:array:foo<span class="Special"> &lt;- </span>put-index *<span class="Constant">2</span>:address:array:foo<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">3</span>:foo <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Constant">3</span>:foo<span class="Special"> &lt;- </span>merge <span class="Constant">0</span> <span class="Constant">2</span>:address:array:foo<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> ] <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- new {number: &quot;type&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -&gt; 1</span> <span class="traceContains">+run: {3: &quot;foo&quot;} &lt;- merge {1: (&quot;address&quot; &quot;number&quot;)}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -&gt; 2</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;array&quot; &quot;foo&quot;), &quot;lookup&quot;: ()} &lt;- put-index {2: (&quot;address&quot; &quot;array&quot; &quot;foo&quot;), &quot;lookup&quot;: ()}, {1: &quot;literal&quot;}, {3: &quot;foo&quot;}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -&gt; 3</span> <span class="traceContains">+run: {1: (&quot;address&quot; &quot;number&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 3 -&gt; 2</span> <span class="traceContains">+run: {3: &quot;foo&quot;} &lt;- merge {0: &quot;literal&quot;}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -&gt; 1</span> <span class="traceContains">+run: {2: (&quot;address&quot; &quot;array&quot; &quot;foo&quot;)} &lt;- copy {0: &quot;literal&quot;}</span> <span class="Comment"># nested abandon</span> <span class="traceContains">+mem: decrementing refcount of 1000: 1 -&gt; 0</span> <span class="traceContains">+abandon: saving 1000 in free-list of size 2</span> </pre> </body> </html> <!-- vim: set foldmethod=manual : -->