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