1 /**
2  * A leaking bump-the-pointer allocator
3  *
4  * This is only for dmd, not dmc.
5  * It implements a heap allocator that never frees.
6  *
7  * Compiler implementation of the
8  * $(LINK2 https://www.dlang.org, D programming language).
9  *
10  * Copyright:   Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
11  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
12  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
13  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/ph2.d, backend/ph2.d)
14  */
15 
16 module dmd.backend.ph2;
17 
18 import core.stdc.stdio;
19 import core.stdc.stdlib;
20 import core.stdc.string;
21 
22 import dmd.backend.cc;
23 import dmd.backend.global;
24 
25 extern (C++):
26 
27 nothrow: @nogc:
28 
29 /**********************************************
30  * Do our own storage allocator, a replacement
31  * for malloc/free.
32  */
33 
34 struct Heap
35 {
36     Heap *prev;         // previous heap
37     ubyte *buf;         // buffer
38     ubyte *p;           // high water mark
39     uint nleft;         // number of bytes left
40 }
41 
42 __gshared Heap *heap=null;
43 
44 void ph_init()
45 {
46     if (!heap) {
47         heap = cast(Heap *)calloc(1,Heap.sizeof);
48     }
49     assert(heap);
50 }
51 
52 
53 
54 void ph_term()
55 {
56     //printf("ph_term()\n");
57 debug
58 {
59     Heap *h;
60     Heap *hprev;
61 
62     for (h = heap; h; h = hprev)
63     {
64         hprev = h.prev;
65         free(h.buf);
66         free(h);
67     }
68 }
69 }
70 
71 void ph_newheap(size_t nbytes)
72 {   uint newsize;
73     Heap *h;
74 
75     h = cast(Heap *) malloc(Heap.sizeof);
76     if (!h)
77         err_nomem();
78 
79     newsize = (nbytes > 0xFF00) ? cast(uint)nbytes : 0xFF00;
80     h.buf = cast(ubyte *) malloc(newsize);
81     if (!h.buf)
82     {
83         free(h);
84         err_nomem();
85     }
86     h.nleft = newsize;
87     h.p = h.buf;
88     h.prev = heap;
89     heap = h;
90 }
91 
92 void *ph_malloc(size_t nbytes)
93 {   ubyte *p;
94 
95     nbytes += uint.sizeof * 2;
96     nbytes &= ~(uint.sizeof - 1);
97 
98     if (nbytes >= heap.nleft)
99         ph_newheap(nbytes);
100     p = heap.p;
101     heap.p += nbytes;
102     heap.nleft -= nbytes;
103     *cast(uint *)p = cast(uint)(nbytes - uint.sizeof);
104     p += uint.sizeof;
105     return p;
106 }
107 
108 void *ph_calloc(size_t nbytes)
109 {   void *p;
110 
111     p = ph_malloc(nbytes);
112     return p ? memset(p,0,nbytes) : p;
113 }
114 
115 void ph_free(void *p)
116 {
117 }
118 
119 void *ph_realloc(void *p,size_t nbytes)
120 {
121     //printf("ph_realloc(%p,%d)\n",p,cast(int)nbytes);
122     if (!p)
123         return ph_malloc(nbytes);
124     if (!nbytes)
125     {   ph_free(p);
126         return null;
127     }
128     void *newp = ph_malloc(nbytes);
129     if (newp)
130     {   uint oldsize = (cast(uint *)p)[-1];
131         memcpy(newp,p,oldsize);
132         ph_free(p);
133     }
134     return newp;
135 }
136 
137 void err_nomem()
138 {
139     printf("Error: out of memory\n");
140     err_exit();
141 }