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 }