1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 1984-1998 by Symantec 6 * Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/util2.d, backend/util2.d) 10 */ 11 12 // Only used for DMD 13 14 module dmd.backend.util2; 15 16 // Utility subroutines 17 18 import core.stdc.stdio; 19 import core.stdc.stdlib; 20 import core.stdc.string; 21 import core.stdc.stdint : uint64_t; 22 23 import dmd.backend.cc; 24 import dmd.backend.cdef; 25 import dmd.backend.global; 26 import dmd.backend.mem; 27 28 extern (C++): 29 30 nothrow: 31 32 void *ph_malloc(size_t nbytes); 33 void *ph_calloc(size_t nbytes); 34 void ph_free(void *p); 35 void *ph_realloc(void *p , size_t nbytes); 36 37 extern (C) void printInternalFailure(FILE* stream); // from dmd/mars.d 38 39 40 void util_exit(int exitcode); 41 42 void file_progress() 43 { 44 } 45 46 /******************************* 47 * Alternative assert failure. 48 */ 49 50 void util_assert(const(char)* file, int line) 51 { 52 fflush(stdout); 53 printInternalFailure(stdout); 54 printf("Internal error: %s %d\n",file,line); 55 err_exit(); 56 //#if __clang__ 57 // __builtin_unreachable(); 58 //#endif 59 } 60 61 /**************************** 62 * Clean up and exit program. 63 */ 64 65 void err_exit() 66 { 67 util_exit(EXIT_FAILURE); 68 } 69 70 /******************************** 71 * Clean up and exit program. 72 */ 73 74 void err_break() 75 { 76 util_exit(255); 77 } 78 79 80 /**************************** 81 * Clean up and exit program. 82 */ 83 84 void util_exit(int exitcode) 85 { 86 exit(exitcode); /* terminate abnormally */ 87 } 88 89 version (CRuntime_DigitalMars) 90 { 91 92 extern (C) extern __gshared int controlc_saw; 93 94 /******************************** 95 * Control C interrupts go here. 96 */ 97 98 private extern (C) void controlc_handler() 99 { 100 //printf("saw controlc\n"); 101 controlc_saw = 1; 102 } 103 104 /********************************* 105 * Trap control C interrupts. 106 */ 107 108 version (MARS) { } else 109 { 110 111 extern (C) 112 { 113 void controlc_open(); 114 void controlc_close(); 115 alias _controlc_handler_t = void function(); 116 extern __gshared _controlc_handler_t _controlc_handler; 117 118 void _STI_controlc() 119 { 120 //printf("_STI_controlc()\n"); 121 _controlc_handler = &controlc_handler; 122 controlc_open(); /* trap control C */ 123 } 124 125 void _STD_controlc() 126 { 127 //printf("_STD_controlc()\n"); 128 controlc_close(); 129 } 130 } 131 132 } 133 } 134 135 /*********************************** 136 * Send progress report. 137 */ 138 139 void util_progress() 140 { 141 version (MARS) { } else { 142 version (CRuntime_DigitalMars) 143 { 144 if (controlc_saw) 145 err_break(); 146 } 147 } 148 } 149 150 void util_progress(int linnum) 151 { 152 version (MARS) { } else { 153 version (CRuntime_DigitalMars) 154 { 155 if (controlc_saw) 156 err_break(); 157 } 158 } 159 } 160 161 162 /********************************** 163 * Binary string search. 164 * Input: 165 * p . string of characters 166 * tab array of pointers to strings 167 * n = number of pointers in the array 168 * Returns: 169 * index (0..n-1) into tab[] if we found a string match 170 * else -1 171 */ 172 173 version (X86) version (CRuntime_DigitalMars) 174 version = X86asm; 175 176 int binary(const(char)* p, const(char)* *table,int high) 177 { 178 version (X86asm) 179 { 180 alias len = high; // reuse parameter storage 181 asm nothrow 182 { 183 184 // First find the length of the identifier. 185 xor EAX,EAX ; // Scan for a 0. 186 mov EDI,p ; 187 mov ECX,EAX ; 188 dec ECX ; // Longest possible string. 189 repne ; 190 scasb ; 191 mov EDX,high ; // EDX = high 192 not ECX ; // length of the id including '/0', stays in ECX 193 dec EDX ; // high-- 194 js short Lnotfound ; 195 dec EAX ; // EAX = -1, so that eventually EBX = low (0) 196 mov len,ECX ; 197 198 even ; 199 L4D: lea EBX,[EAX + 1] ; // low = mid + 1 200 cmp EBX,EDX ; 201 jg Lnotfound ; 202 203 even ; 204 L15: lea EAX,[EBX + EDX] ; // EAX = low + high 205 206 // Do the string compare. 207 208 mov EDI,table ; 209 sar EAX,1 ; // mid = (low + high) >> 1 210 mov ESI,p ; 211 mov EDI,[4*EAX+EDI] ; // Load table[mid] 212 mov ECX,len ; // length of id 213 repe ; 214 cmpsb ; 215 216 je short L63 ; // return mid if equal 217 jns short L4D ; // if (cond < 0) 218 lea EDX,-1[EAX] ; // high = mid - 1 219 cmp EBX,EDX ; 220 jle L15 ; 221 222 Lnotfound: 223 mov EAX,-1 ; // Return -1. 224 225 even ; 226 L63: ; 227 } 228 } 229 else 230 { 231 int low = 0; 232 char cp = *p; 233 high--; 234 p++; 235 236 while (low <= high) 237 { 238 int mid = (low + high) >> 1; 239 int cond = table[mid][0] - cp; 240 if (cond == 0) 241 cond = strcmp(table[mid] + 1,p); 242 if (cond > 0) 243 high = mid - 1; 244 else if (cond < 0) 245 low = mid + 1; 246 else 247 return mid; /* match index */ 248 } 249 return -1; 250 } 251 } 252 253 254 // search table[0 .. high] for p[0 .. len] (where p.length not necessairily equal to len) 255 int binary(const(char)* p, size_t len, const(char)** table, int high) 256 { 257 int low = 0; 258 char cp = *p; 259 high--; 260 p++; 261 len--; 262 263 while (low <= high) 264 { 265 int mid = (low + high) >> 1; 266 int cond = table[mid][0] - cp; 267 268 if (cond == 0) 269 { 270 cond = strncmp(table[mid] + 1, p, len); 271 if (cond == 0) 272 cond = table[mid][len+1]; // same as: if (table[mid][len+1] != '\0') cond = 1; 273 } 274 275 if (cond > 0) 276 high = mid - 1; 277 else if (cond < 0) 278 low = mid + 1; 279 else 280 return mid; /* match index */ 281 } 282 return -1; 283 } 284 285 /********************** 286 * If c is a power of 2, return that power else -1. 287 */ 288 289 int ispow2(uint64_t c) 290 { int i; 291 292 if (c == 0 || (c & (c - 1))) 293 i = -1; 294 else 295 for (i = 0; c >>= 1; i++) 296 { } 297 return i; 298 } 299 300 /*************************** 301 */ 302 303 enum UTIL_PH = true; 304 305 version (MEM_DEBUG) 306 enum MEM_DEBUG = false; //true; 307 else 308 enum MEM_DEBUG = false; 309 310 version (Windows) 311 { 312 void *util_malloc(uint n,uint size) 313 { 314 static if (MEM_DEBUG) 315 { 316 void *p; 317 318 p = mem_malloc(n * size); 319 //dbg_printf("util_calloc(%d) = %p\n",n * size,p); 320 return p; 321 } 322 else static if (UTIL_PH) 323 { 324 return ph_malloc(n * size); 325 } 326 else 327 { 328 size_t nbytes = cast(size_t)n * cast(size_t)size; 329 void *p = malloc(nbytes); 330 if (!p && nbytes) 331 err_nomem(); 332 return p; 333 } 334 } 335 } 336 337 /*************************** 338 */ 339 340 version (Windows) 341 { 342 void *util_calloc(uint n,uint size) 343 { 344 static if (MEM_DEBUG) 345 { 346 void *p; 347 348 p = mem_calloc(n * size); 349 //dbg_printf("util_calloc(%d) = %p\n",n * size,p); 350 return p; 351 } 352 else static if (UTIL_PH) 353 { 354 return ph_calloc(n * size); 355 } 356 else 357 { 358 size_t nbytes = cast(size_t) n * cast(size_t) size; 359 void *p = calloc(n,size); 360 if (!p && nbytes) 361 err_nomem(); 362 return p; 363 } 364 } 365 } 366 367 /*************************** 368 */ 369 370 version (Windows) 371 { 372 void util_free(void *p) 373 { 374 //dbg_printf("util_free(%p)\n",p); 375 static if (MEM_DEBUG) 376 { 377 mem_free(p); 378 } 379 else static if (UTIL_PH) 380 { 381 ph_free(p); 382 } 383 else 384 { 385 free(p); 386 } 387 } 388 } 389 390 /*************************** 391 */ 392 393 version (Windows) 394 { 395 void *util_realloc(void *oldp,size_t n,size_t size) 396 { 397 static if (MEM_DEBUG) 398 { 399 //dbg_printf("util_realloc(%p,%d)\n",oldp,n * size); 400 return mem_realloc(oldp,n * size); 401 } 402 else static if (UTIL_PH) 403 { 404 return ph_realloc(oldp,n * size); 405 } 406 else 407 { 408 const nbytes = n * size; 409 void *p = realloc(oldp,nbytes); 410 if (!p && nbytes) 411 err_nomem(); 412 return p; 413 } 414 } 415 } 416 417 /***************************** 418 */ 419 void *mem_malloc2(uint size) 420 { 421 return mem_malloc(size); 422 }